From 84822c2191f0e1b7fe63792984ec67ea000d2239 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 11 Jun 2020 20:07:16 +0800 Subject: [PATCH 001/356] =?UTF-8?q?tableView=E5=AE=9E=E7=8E=B0=E5=8E=9F?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WKWebView/SLTableViewController.m | 51 +++++++++++++++++-- .../WebTableView/SLScrollViewController.m | 6 +++ 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m b/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m index 3f44d197..3a7e2939 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m +++ b/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m @@ -8,10 +8,13 @@ #import "SLTableViewController.h" -@interface SLTableViewController () +@interface SLTableViewController () @property (nonatomic, strong) UIScrollView *scrollView; + ///复用池 +@property (nonatomic, strong) NSMutableDictionary *> *multiplexingPool; + @end @implementation SLTableViewController @@ -33,16 +36,54 @@ - (void)setupUI { #pragma mark - Getter - (UIScrollView *)scrollView { if (!_scrollView) { - _scrollView = [[UIScrollView alloc] init]; + _scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; + _scrollView.delegate = self; + } + return _scrollView; +} +- (NSMutableDictionary *)multiplexingPool { + if (!_multiplexingPool) { + _multiplexingPool = [NSMutableDictionary dictionary]; } - return _scrollView;; + return _multiplexingPool;; } -#pragma mark - HelpMethods +#pragma mark - Help Methods +///刷新数据 +- (void)reloadData { + +} +///注册样式 +- (void)registerClass:(Class)class forCellReuseIdentifier:(NSString *)cellID { + self.multiplexingPool[cellID] = [NSHashTable weakObjectsHashTable]; +} +///行数 +- (NSInteger)numberOfRowsInScrollView:(UIScrollView *)scrollView { + return 20; +} +///行高 +- (CGFloat)scrollView:(UIScrollView *)scrollView heightForRowAtIndex:(NSInteger)index { + return 0; +} +///行内容 +- (UIView *)scrollView:(UIScrollView *)scrollView cellForRowAtIndex:(NSInteger)index{ + UIView *view = [UIView new]; + view.backgroundColor = SL_UIColorFromRandomColor; + return view; +} +///点击行 +- (void)scrollView:(UIScrollView *)scrollView didSelectRowAtIndex:(NSInteger)index { + +} #pragma mark - EventsHandle -#pragma mark - UICollectionViewDelegate, UICollectionViewDataSource +#pragma mark - UIScrollViewDelegate +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + + +} + @end diff --git a/iOS_Tips/DarkMode/WKWebView/WebTableView/SLScrollViewController.m b/iOS_Tips/DarkMode/WKWebView/WebTableView/SLScrollViewController.m index d6474521..25b5af22 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebTableView/SLScrollViewController.m +++ b/iOS_Tips/DarkMode/WKWebView/WebTableView/SLScrollViewController.m @@ -215,6 +215,12 @@ - (void)dynamicAnimatorWillResume:(UIDynamicAnimator *)animator { //动力装置暂停 - (void)dynamicAnimatorDidPause:(UIDynamicAnimator *)animator { +} +#pragma mark - UIGestureRecognizerDelegate +// 避免影响横滑手势 +- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { + CGPoint velocity = [(UIPanGestureRecognizer *)gestureRecognizer velocityInView:self]; + return fabs(velocity.y) > fabs(velocity.x); } @end From a560043da71461b3c8b7f0f20733f743b14c3d48 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 12 Jun 2020 10:45:43 +0800 Subject: [PATCH 002/356] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 调整文件目录 --- .DS_Store | Bin 8196 -> 8196 bytes iOS_Tips/.DS_Store | Bin 10244 -> 10244 bytes .../xcshareddata/xcschemes/DarkMode.xcscheme | 98 + .../contents.xcworkspacedata | 10 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - iOS_Tips/Podfile.lock | 43 - .../Associations/FBAssociationManager.h | 36 - .../Associations/FBAssociationManager.mm | 207 -- .../Internal/FBAssociationManager+Internal.h | 25 - .../Detector/FBNodeEnumerator.h | 29 - .../Detector/FBNodeEnumerator.mm | 62 - .../Detector/FBRetainCycleDetector+Internal.h | 17 - .../Detector/FBRetainCycleDetector.h | 86 - .../Detector/FBRetainCycleDetector.mm | 294 -- .../FBRetainCycleUtils.h | 33 - .../FBRetainCycleUtils.m | 66 - .../Filtering/FBStandardGraphEdgeFilters.h | 36 - .../Filtering/FBStandardGraphEdgeFilters.mm | 74 - .../Graph/FBObjectGraphConfiguration.h | 86 - .../Graph/FBObjectGraphConfiguration.m | 55 - .../Graph/FBObjectiveCBlock.h | 20 - .../Graph/FBObjectiveCBlock.m | 100 - .../Graph/FBObjectiveCGraphElement.h | 59 - .../Graph/FBObjectiveCGraphElement.mm | 130 - .../Graph/FBObjectiveCObject.h | 21 - .../Graph/FBObjectiveCObject.m | 147 - .../FBObjectiveCGraphElement+Internal.h | 18 - .../Specialization/FBObjectiveCNSCFTimer.h | 20 - .../Specialization/FBObjectiveCNSCFTimer.mm | 64 - .../Layout/Blocks/FBBlockInterface.h | 41 - .../Layout/Blocks/FBBlockStrongLayout.h | 26 - .../Layout/Blocks/FBBlockStrongLayout.m | 123 - .../Blocks/FBBlockStrongRelationDetector.h | 41 - .../Blocks/FBBlockStrongRelationDetector.m | 55 - .../Layout/Classes/FBClassStrongLayout.h | 32 - .../Layout/Classes/FBClassStrongLayout.mm | 212 -- .../Classes/FBClassStrongLayoutHelpers.h | 29 - .../Classes/FBClassStrongLayoutHelpers.m | 20 - .../Layout/Classes/Parser/BaseType.h | 30 - .../Classes/Parser/FBStructEncodingParser.h | 37 - .../Classes/Parser/FBStructEncodingParser.mm | 168 - .../Layout/Classes/Parser/Struct.h | 41 - .../Layout/Classes/Parser/Struct.mm | 51 - .../Layout/Classes/Parser/Type.h | 38 - .../Classes/Reference/FBIvarReference.h | 33 - .../Classes/Reference/FBIvarReference.m | 71 - .../Reference/FBObjectInStructReference.h | 26 - .../Reference/FBObjectInStructReference.m | 53 - .../Classes/Reference/FBObjectReference.h | 46 - iOS_Tips/Pods/FBRetainCycleDetector/LICENSE | 30 - iOS_Tips/Pods/FBRetainCycleDetector/README.md | 135 - .../FBRetainCycleDetector/fishhook/fishhook.c | 208 -- .../FBRetainCycleDetector/fishhook/fishhook.h | 68 - iOS_Tips/Pods/GPUImage/License.txt | 9 - iOS_Tips/Pods/GPUImage/README.md | 733 ---- .../GPUImage/framework/Resources/lookup.png | Bin 2095 -> 0 bytes .../framework/Resources/lookup_amatorka.png | Bin 36390 -> 0 bytes .../Resources/lookup_miss_etikate.png | Bin 202596 -> 0 bytes .../Resources/lookup_soft_elegance_1.png | Bin 129208 -> 0 bytes .../Resources/lookup_soft_elegance_2.png | Bin 2199 -> 0 bytes .../GPUImage/framework/Source/GLProgram.h | 42 - .../GPUImage/framework/Source/GLProgram.m | 236 -- .../Pods/GPUImage/framework/Source/GPUImage.h | 164 - .../Source/GPUImage3x3ConvolutionFilter.h | 18 - .../Source/GPUImage3x3ConvolutionFilter.m | 128 - .../Source/GPUImage3x3TextureSamplingFilter.h | 18 - .../Source/GPUImage3x3TextureSamplingFilter.m | 121 - .../Source/GPUImageAdaptiveThresholdFilter.h | 9 - .../Source/GPUImageAdaptiveThresholdFilter.m | 100 - .../framework/Source/GPUImageAddBlendFilter.h | 5 - .../framework/Source/GPUImageAddBlendFilter.m | 100 - .../Source/GPUImageAlphaBlendFilter.h | 11 - .../Source/GPUImageAlphaBlendFilter.m | 72 - .../framework/Source/GPUImageAmatorkaFilter.h | 17 - .../framework/Source/GPUImageAmatorkaFilter.m | 38 - .../framework/Source/GPUImageAverageColor.h | 20 - .../framework/Source/GPUImageAverageColor.m | 210 -- .../GPUImageAverageLuminanceThresholdFilter.h | 8 - .../GPUImageAverageLuminanceThresholdFilter.m | 47 - .../Source/GPUImageBilateralFilter.h | 10 - .../Source/GPUImageBilateralFilter.m | 231 -- .../framework/Source/GPUImageBoxBlurFilter.h | 7 - .../framework/Source/GPUImageBoxBlurFilter.m | 178 - .../Source/GPUImageBrightnessFilter.h | 11 - .../Source/GPUImageBrightnessFilter.m | 66 - .../framework/Source/GPUImageBuffer.h | 10 - .../framework/Source/GPUImageBuffer.m | 112 - .../Source/GPUImageBulgeDistortionFilter.h | 16 - .../Source/GPUImageBulgeDistortionFilter.m | 174 - .../Source/GPUImageCGAColorspaceFilter.h | 5 - .../Source/GPUImageCGAColorspaceFilter.m | 113 - .../Source/GPUImageCannyEdgeDetectionFilter.h | 62 - .../Source/GPUImageCannyEdgeDetectionFilter.m | 125 - .../Source/GPUImageChromaKeyBlendFilter.h | 32 - .../Source/GPUImageChromaKeyBlendFilter.m | 117 - .../Source/GPUImageChromaKeyFilter.h | 30 - .../Source/GPUImageChromaKeyFilter.m | 113 - .../framework/Source/GPUImageClosingFilter.h | 19 - .../framework/Source/GPUImageClosingFilter.m | 57 - .../Source/GPUImageColorBlendFilter.h | 5 - .../Source/GPUImageColorBlendFilter.m | 113 - .../Source/GPUImageColorBurnBlendFilter.h | 9 - .../Source/GPUImageColorBurnBlendFilter.m | 52 - .../Source/GPUImageColorDodgeBlendFilter.h | 9 - .../Source/GPUImageColorDodgeBlendFilter.m | 75 - .../Source/GPUImageColorInvertFilter.h | 7 - .../Source/GPUImageColorInvertFilter.m | 46 - .../Source/GPUImageColorMatrixFilter.h | 19 - .../Source/GPUImageColorMatrixFilter.m | 87 - .../Source/GPUImageColorPackingFilter.h | 10 - .../Source/GPUImageColorPackingFilter.m | 139 - .../framework/Source/GPUImageContrastFilter.h | 14 - .../framework/Source/GPUImageContrastFilter.m | 66 - .../framework/Source/GPUImageCropFilter.h | 14 - .../framework/Source/GPUImageCropFilter.m | 274 -- .../Source/GPUImageCrosshairGenerator.h | 17 - .../Source/GPUImageCrosshairGenerator.m | 139 - .../Source/GPUImageCrosshatchFilter.h | 13 - .../Source/GPUImageCrosshatchFilter.m | 163 - .../Source/GPUImageDarkenBlendFilter.h | 7 - .../Source/GPUImageDarkenBlendFilter.m | 52 - .../Source/GPUImageDifferenceBlendFilter.h | 7 - .../Source/GPUImageDifferenceBlendFilter.m | 50 - .../framework/Source/GPUImageDilationFilter.h | 16 - .../framework/Source/GPUImageDilationFilter.m | 431 --- ...geDirectionalNonMaximumSuppressionFilter.h | 19 - ...geDirectionalNonMaximumSuppressionFilter.m | 141 - ...ImageDirectionalSobelEdgeDetectionFilter.h | 5 - ...ImageDirectionalSobelEdgeDetectionFilter.m | 103 - .../Source/GPUImageDissolveBlendFilter.h | 11 - .../Source/GPUImageDissolveBlendFilter.m | 72 - .../Source/GPUImageDivideBlendFilter.h | 5 - .../Source/GPUImageDivideBlendFilter.m | 96 - .../framework/Source/GPUImageEmbossFilter.h | 8 - .../framework/Source/GPUImageEmbossFilter.m | 49 - .../framework/Source/GPUImageErosionFilter.h | 11 - .../framework/Source/GPUImageErosionFilter.m | 312 -- .../Source/GPUImageExclusionBlendFilter.h | 7 - .../Source/GPUImageExclusionBlendFilter.m | 56 - .../framework/Source/GPUImageExposureFilter.h | 11 - .../framework/Source/GPUImageExposureFilter.m | 66 - .../GPUImageFASTCornerDetectionFilter.h | 33 - .../GPUImageFASTCornerDetectionFilter.m | 89 - .../Source/GPUImageFalseColorFilter.h | 15 - .../Source/GPUImageFalseColorFilter.m | 101 - .../framework/Source/GPUImageFilter.h | 134 - .../framework/Source/GPUImageFilter.m | 753 ----- .../framework/Source/GPUImageFilterGroup.h | 19 - .../framework/Source/GPUImageFilterGroup.m | 208 -- .../framework/Source/GPUImageFilterPipeline.h | 30 - .../framework/Source/GPUImageFilterPipeline.m | 218 -- .../framework/Source/GPUImageFramebuffer.h | 58 - .../framework/Source/GPUImageFramebuffer.m | 448 --- .../Source/GPUImageFramebufferCache.h | 15 - .../Source/GPUImageFramebufferCache.m | 179 - .../framework/Source/GPUImageGammaFilter.h | 11 - .../framework/Source/GPUImageGammaFilter.m | 66 - .../Source/GPUImageGaussianBlurFilter.h | 36 - .../Source/GPUImageGaussianBlurFilter.m | 513 --- .../GPUImageGaussianBlurPositionFilter.h | 22 - .../GPUImageGaussianBlurPositionFilter.m | 232 -- .../GPUImageGaussianSelectiveBlurFilter.h | 30 - .../GPUImageGaussianSelectiveBlurFilter.m | 147 - .../Source/GPUImageGlassSphereFilter.h | 5 - .../Source/GPUImageGlassSphereFilter.m | 106 - .../Source/GPUImageGrayscaleFilter.h | 9 - .../Source/GPUImageGrayscaleFilter.m | 141 - .../framework/Source/GPUImageHSBFilter.h | 27 - .../framework/Source/GPUImageHSBFilter.m | 414 --- .../framework/Source/GPUImageHalftoneFilter.h | 5 - .../framework/Source/GPUImageHalftoneFilter.m | 79 - .../Source/GPUImageHardLightBlendFilter.h | 7 - .../Source/GPUImageHardLightBlendFilter.m | 99 - .../GPUImageHarrisCornerDetectionFilter.h | 53 - .../GPUImageHarrisCornerDetectionFilter.m | 292 -- .../framework/Source/GPUImageHazeFilter.h | 29 - .../framework/Source/GPUImageHazeFilter.m | 96 - .../framework/Source/GPUImageHighPassFilter.h | 14 - .../framework/Source/GPUImageHighPassFilter.m | 46 - .../Source/GPUImageHighlightShadowFilter.h | 20 - .../Source/GPUImageHighlightShadowFilter.m | 93 - .../GPUImageHistogramEqualizationFilter.h | 26 - .../GPUImageHistogramEqualizationFilter.m | 307 -- .../Source/GPUImageHistogramFilter.h | 22 - .../Source/GPUImageHistogramFilter.m | 341 -- .../Source/GPUImageHistogramGenerator.h | 8 - .../Source/GPUImageHistogramGenerator.m | 87 - .../GPUImageHoughTransformLineDetector.h | 49 - .../GPUImageHoughTransformLineDetector.m | 241 -- .../framework/Source/GPUImageHueBlendFilter.h | 5 - .../framework/Source/GPUImageHueBlendFilter.m | 212 -- .../framework/Source/GPUImageHueFilter.h | 11 - .../framework/Source/GPUImageHueFilter.m | 123 - .../Source/GPUImageJFAVoronoiFilter.h | 17 - .../Source/GPUImageJFAVoronoiFilter.m | 446 --- .../framework/Source/GPUImageKuwaharaFilter.h | 13 - .../framework/Source/GPUImageKuwaharaFilter.m | 223 -- .../Source/GPUImageKuwaharaRadius3Filter.h | 8 - .../Source/GPUImageKuwaharaRadius3Filter.m | 547 --- .../Source/GPUImageLanczosResamplingFilter.h | 7 - .../Source/GPUImageLanczosResamplingFilter.m | 239 -- .../Source/GPUImageLaplacianFilter.h | 5 - .../Source/GPUImageLaplacianFilter.m | 115 - .../framework/Source/GPUImageLevelsFilter.h | 45 - .../framework/Source/GPUImageLevelsFilter.m | 152 - .../Source/GPUImageLightenBlendFilter.h | 8 - .../Source/GPUImageLightenBlendFilter.m | 52 - .../framework/Source/GPUImageLineGenerator.h | 18 - .../framework/Source/GPUImageLineGenerator.m | 164 - .../Source/GPUImageLinearBurnBlendFilter.h | 5 - .../Source/GPUImageLinearBurnBlendFilter.m | 51 - .../Source/GPUImageLocalBinaryPatternFilter.h | 5 - .../Source/GPUImageLocalBinaryPatternFilter.m | 123 - .../framework/Source/GPUImageLookupFilter.h | 34 - .../framework/Source/GPUImageLookupFilter.m | 115 - .../framework/Source/GPUImageLowPassFilter.h | 14 - .../framework/Source/GPUImageLowPassFilter.m | 61 - .../Source/GPUImageLuminanceRangeFilter.h | 12 - .../Source/GPUImageLuminanceRangeFilter.m | 76 - .../Source/GPUImageLuminanceThresholdFilter.h | 14 - .../Source/GPUImageLuminanceThresholdFilter.m | 74 - .../framework/Source/GPUImageLuminosity.h | 17 - .../framework/Source/GPUImageLuminosity.m | 329 -- .../Source/GPUImageLuminosityBlendFilter.h | 5 - .../Source/GPUImageLuminosityBlendFilter.m | 113 - .../framework/Source/GPUImageMaskFilter.h | 5 - .../framework/Source/GPUImageMaskFilter.m | 76 - .../framework/Source/GPUImageMedianFilter.h | 5 - .../framework/Source/GPUImageMedianFilter.m | 178 - .../Source/GPUImageMissEtikateFilter.h | 17 - .../Source/GPUImageMissEtikateFilter.m | 38 - .../Source/GPUImageMonochromeFilter.h | 13 - .../Source/GPUImageMonochromeFilter.m | 115 - .../framework/Source/GPUImageMosaicFilter.h | 22 - .../framework/Source/GPUImageMosaicFilter.m | 188 -- .../Source/GPUImageMotionBlurFilter.h | 13 - .../Source/GPUImageMotionBlurFilter.m | 209 -- .../framework/Source/GPUImageMotionDetector.h | 18 - .../framework/Source/GPUImageMotionDetector.m | 112 - .../GPUImage/framework/Source/GPUImageMovie.h | 61 - .../GPUImage/framework/Source/GPUImageMovie.m | 761 ----- .../Source/GPUImageMovieComposition.h | 21 - .../Source/GPUImageMovieComposition.m | 70 - .../Source/GPUImageMultiplyBlendFilter.h | 7 - .../Source/GPUImageMultiplyBlendFilter.m | 52 - .../GPUImageNobleCornerDetectionFilter.h | 12 - .../GPUImageNobleCornerDetectionFilter.m | 74 - .../GPUImageNonMaximumSuppressionFilter.h | 5 - .../GPUImageNonMaximumSuppressionFilter.m | 107 - .../Source/GPUImageNormalBlendFilter.h | 8 - .../Source/GPUImageNormalBlendFilter.m | 96 - .../framework/Source/GPUImageOpacityFilter.h | 11 - .../framework/Source/GPUImageOpacityFilter.m | 65 - .../framework/Source/GPUImageOpeningFilter.h | 19 - .../framework/Source/GPUImageOpeningFilter.m | 57 - .../framework/Source/GPUImageOutput.h | 127 - .../framework/Source/GPUImageOutput.m | 428 --- .../Source/GPUImageOverlayBlendFilter.h | 5 - .../Source/GPUImageOverlayBlendFilter.m | 94 - ...ageParallelCoordinateLineTransformFilter.h | 16 - ...ageParallelCoordinateLineTransformFilter.m | 266 -- .../Source/GPUImagePerlinNoiseFilter.h | 13 - .../Source/GPUImagePerlinNoiseFilter.m | 239 -- .../Source/GPUImagePinchDistortionFilter.h | 20 - .../Source/GPUImagePinchDistortionFilter.m | 176 - .../Source/GPUImagePixellateFilter.h | 12 - .../Source/GPUImagePixellateFilter.m | 151 - .../Source/GPUImagePixellatePositionFilter.h | 17 - .../Source/GPUImagePixellatePositionFilter.m | 194 -- .../Source/GPUImagePoissonBlendFilter.h | 18 - .../Source/GPUImagePoissonBlendFilter.m | 175 - .../Source/GPUImagePolarPixellateFilter.h | 13 - .../Source/GPUImagePolarPixellateFilter.m | 128 - .../framework/Source/GPUImagePolkaDotFilter.h | 10 - .../framework/Source/GPUImagePolkaDotFilter.m | 85 - .../Source/GPUImagePosterizeFilter.h | 14 - .../Source/GPUImagePosterizeFilter.m | 66 - .../GPUImagePrewittEdgeDetectionFilter.h | 5 - .../GPUImagePrewittEdgeDetectionFilter.m | 97 - .../Source/GPUImageRGBClosingFilter.h | 18 - .../Source/GPUImageRGBClosingFilter.m | 41 - .../Source/GPUImageRGBDilationFilter.h | 11 - .../Source/GPUImageRGBDilationFilter.m | 306 -- .../Source/GPUImageRGBErosionFilter.h | 11 - .../Source/GPUImageRGBErosionFilter.m | 304 -- .../framework/Source/GPUImageRGBFilter.h | 15 - .../framework/Source/GPUImageRGBFilter.m | 89 - .../Source/GPUImageRGBOpeningFilter.h | 17 - .../Source/GPUImageRGBOpeningFilter.m | 41 - .../framework/Source/GPUImageRawDataInput.h | 43 - .../framework/Source/GPUImageRawDataInput.m | 139 - .../framework/Source/GPUImageRawDataOutput.h | 44 - .../framework/Source/GPUImageRawDataOutput.m | 307 -- .../Source/GPUImageSaturationBlendFilter.h | 5 - .../Source/GPUImageSaturationBlendFilter.m | 213 -- .../Source/GPUImageSaturationFilter.h | 14 - .../Source/GPUImageSaturationFilter.m | 78 - .../Source/GPUImageScreenBlendFilter.h | 7 - .../Source/GPUImageScreenBlendFilter.m | 52 - .../framework/Source/GPUImageSepiaFilter.h | 6 - .../framework/Source/GPUImageSepiaFilter.m | 24 - .../framework/Source/GPUImageSharpenFilter.h | 12 - .../framework/Source/GPUImageSharpenFilter.m | 147 - .../GPUImageShiTomasiFeatureDetectionFilter.h | 13 - .../GPUImageShiTomasiFeatureDetectionFilter.m | 65 - ...PUImageSingleComponentGaussianBlurFilter.h | 7 - ...PUImageSingleComponentGaussianBlurFilter.m | 189 -- .../framework/Source/GPUImageSketchFilter.h | 11 - .../framework/Source/GPUImageSketchFilter.m | 98 - .../Source/GPUImageSmoothToonFilter.h | 28 - .../Source/GPUImageSmoothToonFilter.m | 94 - .../Source/GPUImageSobelEdgeDetectionFilter.h | 16 - .../Source/GPUImageSobelEdgeDetectionFilter.m | 188 -- .../Source/GPUImageSoftEleganceFilter.h | 19 - .../Source/GPUImageSoftEleganceFilter.m | 62 - .../Source/GPUImageSoftLightBlendFilter.h | 7 - .../Source/GPUImageSoftLightBlendFilter.m | 54 - .../Source/GPUImageSolidColorGenerator.h | 19 - .../Source/GPUImageSolidColorGenerator.m | 123 - .../Source/GPUImageSourceOverBlendFilter.h | 5 - .../Source/GPUImageSourceOverBlendFilter.m | 51 - .../Source/GPUImageSphereRefractionFilter.h | 15 - .../Source/GPUImageSphereRefractionFilter.m | 179 - .../framework/Source/GPUImageStillCamera.h | 24 - .../framework/Source/GPUImageStillCamera.m | 338 -- .../Source/GPUImageStretchDistortionFilter.h | 13 - .../Source/GPUImageStretchDistortionFilter.m | 99 - .../Source/GPUImageSubtractBlendFilter.h | 5 - .../Source/GPUImageSubtractBlendFilter.m | 52 - .../framework/Source/GPUImageSwirlFilter.h | 17 - .../framework/Source/GPUImageSwirlFilter.m | 123 - .../framework/Source/GPUImageTextureInput.h | 14 - .../framework/Source/GPUImageTextureInput.m | 46 - .../framework/Source/GPUImageTextureOutput.h | 21 - .../framework/Source/GPUImageTextureOutput.m | 83 - .../Source/GPUImageThreeInputFilter.h | 21 - .../Source/GPUImageThreeInputFilter.m | 328 -- .../GPUImageThresholdEdgeDetectionFilter.h | 12 - .../GPUImageThresholdEdgeDetectionFilter.m | 145 - .../Source/GPUImageThresholdSketchFilter.h | 5 - .../Source/GPUImageThresholdSketchFilter.m | 103 - ...geThresholdedNonMaximumSuppressionFilter.h | 14 - ...geThresholdedNonMaximumSuppressionFilter.m | 297 -- .../Source/GPUImageTiltShiftFilter.h | 24 - .../Source/GPUImageTiltShiftFilter.m | 126 - .../Source/GPUImageToneCurveFilter.h | 30 - .../Source/GPUImageToneCurveFilter.m | 621 ---- .../framework/Source/GPUImageToonFilter.h | 19 - .../framework/Source/GPUImageToonFilter.m | 149 - .../Source/GPUImageTransformFilter.h | 19 - .../Source/GPUImageTransformFilter.m | 260 -- ...UImageTwoInputCrossTextureSamplingFilter.h | 15 - ...UImageTwoInputCrossTextureSamplingFilter.m | 108 - .../framework/Source/GPUImageTwoInputFilter.h | 21 - .../framework/Source/GPUImageTwoInputFilter.m | 264 -- .../framework/Source/GPUImageTwoPassFilter.h | 19 - .../framework/Source/GPUImageTwoPassFilter.m | 201 -- .../GPUImageTwoPassTextureSamplingFilter.h | 13 - .../GPUImageTwoPassTextureSamplingFilter.m | 85 - .../framework/Source/GPUImageUIElement.h | 15 - .../framework/Source/GPUImageUIElement.m | 123 - .../Source/GPUImageUnsharpMaskFilter.h | 16 - .../Source/GPUImageUnsharpMaskFilter.m | 101 - .../framework/Source/GPUImageVideoCamera.h | 154 - .../framework/Source/GPUImageVideoCamera.m | 1129 ------- .../framework/Source/GPUImageVignetteFilter.h | 22 - .../framework/Source/GPUImageVignetteFilter.m | 104 - .../Source/GPUImageVoronoiConsumerFilter.h | 10 - .../Source/GPUImageVoronoiConsumerFilter.m | 94 - .../Source/GPUImageWeakPixelInclusionFilter.h | 5 - .../Source/GPUImageWeakPixelInclusionFilter.m | 94 - .../Source/GPUImageWhiteBalanceFilter.h | 17 - .../Source/GPUImageWhiteBalanceFilter.m | 107 - .../Source/GPUImageXYDerivativeFilter.h | 5 - .../Source/GPUImageXYDerivativeFilter.m | 106 - .../framework/Source/GPUImageZoomBlurFilter.h | 13 - .../framework/Source/GPUImageZoomBlurFilter.m | 115 - .../framework/Source/GPUImageiOSBlurFilter.h | 31 - .../framework/Source/GPUImageiOSBlurFilter.m | 114 - .../Source/iOS/Framework/GPUImageFramework.h | 172 - .../framework/Source/iOS/GPUImageContext.h | 55 - .../framework/Source/iOS/GPUImageContext.m | 318 -- .../Source/iOS/GPUImageMovieWriter.h | 67 - .../Source/iOS/GPUImageMovieWriter.m | 934 ------ .../iOS/GPUImagePicture+TextureSubimage.h | 19 - .../iOS/GPUImagePicture+TextureSubimage.m | 103 - .../framework/Source/iOS/GPUImagePicture.h | 34 - .../framework/Source/iOS/GPUImagePicture.m | 304 -- .../framework/Source/iOS/GPUImageView.h | 39 - .../framework/Source/iOS/GPUImageView.m | 481 --- .../Private/FBRetainCycleDetector/BaseType.h | 1 - .../FBAssociationManager+Internal.h | 1 - .../FBAssociationManager.h | 1 - .../FBRetainCycleDetector/FBBlockInterface.h | 1 - .../FBBlockStrongLayout.h | 1 - .../FBBlockStrongRelationDetector.h | 1 - .../FBClassStrongLayout.h | 1 - .../FBClassStrongLayoutHelpers.h | 1 - .../FBRetainCycleDetector/FBIvarReference.h | 1 - .../FBRetainCycleDetector/FBNodeEnumerator.h | 1 - .../FBObjectGraphConfiguration.h | 1 - .../FBObjectInStructReference.h | 1 - .../FBRetainCycleDetector/FBObjectReference.h | 1 - .../FBRetainCycleDetector/FBObjectiveCBlock.h | 1 - .../FBObjectiveCGraphElement+Internal.h | 1 - .../FBObjectiveCGraphElement.h | 1 - .../FBObjectiveCNSCFTimer.h | 1 - .../FBObjectiveCObject.h | 1 - .../FBRetainCycleDetector+Internal.h | 1 - .../FBRetainCycleDetector.h | 1 - .../FBRetainCycleUtils.h | 1 - .../FBStandardGraphEdgeFilters.h | 1 - .../FBStructEncodingParser.h | 1 - .../Private/FBRetainCycleDetector/Struct.h | 1 - .../Private/FBRetainCycleDetector/Type.h | 1 - .../Private/FBRetainCycleDetector/fishhook.h | 1 - .../Pods/Headers/Private/GPUImage/GLProgram.h | 1 - .../Pods/Headers/Private/GPUImage/GPUImage.h | 1 - .../GPUImage/GPUImage3x3ConvolutionFilter.h | 1 - .../GPUImage3x3TextureSamplingFilter.h | 1 - .../GPUImageAdaptiveThresholdFilter.h | 1 - .../Private/GPUImage/GPUImageAddBlendFilter.h | 1 - .../GPUImage/GPUImageAlphaBlendFilter.h | 1 - .../Private/GPUImage/GPUImageAmatorkaFilter.h | 1 - .../Private/GPUImage/GPUImageAverageColor.h | 1 - .../GPUImageAverageLuminanceThresholdFilter.h | 1 - .../GPUImage/GPUImageBilateralFilter.h | 1 - .../Private/GPUImage/GPUImageBoxBlurFilter.h | 1 - .../GPUImage/GPUImageBrightnessFilter.h | 1 - .../Headers/Private/GPUImage/GPUImageBuffer.h | 1 - .../GPUImage/GPUImageBulgeDistortionFilter.h | 1 - .../GPUImage/GPUImageCGAColorspaceFilter.h | 1 - .../GPUImageCannyEdgeDetectionFilter.h | 1 - .../GPUImage/GPUImageChromaKeyBlendFilter.h | 1 - .../GPUImage/GPUImageChromaKeyFilter.h | 1 - .../Private/GPUImage/GPUImageClosingFilter.h | 1 - .../GPUImage/GPUImageColorBlendFilter.h | 1 - .../GPUImage/GPUImageColorBurnBlendFilter.h | 1 - .../GPUImage/GPUImageColorDodgeBlendFilter.h | 1 - .../GPUImage/GPUImageColorInvertFilter.h | 1 - .../GPUImage/GPUImageColorMatrixFilter.h | 1 - .../GPUImage/GPUImageColorPackingFilter.h | 1 - .../Private/GPUImage/GPUImageContext.h | 1 - .../Private/GPUImage/GPUImageContrastFilter.h | 1 - .../Private/GPUImage/GPUImageCropFilter.h | 1 - .../GPUImage/GPUImageCrosshairGenerator.h | 1 - .../GPUImage/GPUImageCrosshatchFilter.h | 1 - .../GPUImage/GPUImageDarkenBlendFilter.h | 1 - .../GPUImage/GPUImageDifferenceBlendFilter.h | 1 - .../Private/GPUImage/GPUImageDilationFilter.h | 1 - ...geDirectionalNonMaximumSuppressionFilter.h | 1 - ...ImageDirectionalSobelEdgeDetectionFilter.h | 1 - .../GPUImage/GPUImageDissolveBlendFilter.h | 1 - .../GPUImage/GPUImageDivideBlendFilter.h | 1 - .../Private/GPUImage/GPUImageEmbossFilter.h | 1 - .../Private/GPUImage/GPUImageErosionFilter.h | 1 - .../GPUImage/GPUImageExclusionBlendFilter.h | 1 - .../Private/GPUImage/GPUImageExposureFilter.h | 1 - .../GPUImageFASTCornerDetectionFilter.h | 1 - .../GPUImage/GPUImageFalseColorFilter.h | 1 - .../Headers/Private/GPUImage/GPUImageFilter.h | 1 - .../Private/GPUImage/GPUImageFilterGroup.h | 1 - .../Private/GPUImage/GPUImageFilterPipeline.h | 1 - .../Private/GPUImage/GPUImageFramebuffer.h | 1 - .../GPUImage/GPUImageFramebufferCache.h | 1 - .../Private/GPUImage/GPUImageFramework.h | 1 - .../Private/GPUImage/GPUImageGammaFilter.h | 1 - .../GPUImage/GPUImageGaussianBlurFilter.h | 1 - .../GPUImageGaussianBlurPositionFilter.h | 1 - .../GPUImageGaussianSelectiveBlurFilter.h | 1 - .../GPUImage/GPUImageGlassSphereFilter.h | 1 - .../GPUImage/GPUImageGrayscaleFilter.h | 1 - .../Private/GPUImage/GPUImageHSBFilter.h | 1 - .../Private/GPUImage/GPUImageHalftoneFilter.h | 1 - .../GPUImage/GPUImageHardLightBlendFilter.h | 1 - .../GPUImageHarrisCornerDetectionFilter.h | 1 - .../Private/GPUImage/GPUImageHazeFilter.h | 1 - .../Private/GPUImage/GPUImageHighPassFilter.h | 1 - .../GPUImage/GPUImageHighlightShadowFilter.h | 1 - .../GPUImageHistogramEqualizationFilter.h | 1 - .../GPUImage/GPUImageHistogramFilter.h | 1 - .../GPUImage/GPUImageHistogramGenerator.h | 1 - .../GPUImageHoughTransformLineDetector.h | 1 - .../Private/GPUImage/GPUImageHueBlendFilter.h | 1 - .../Private/GPUImage/GPUImageHueFilter.h | 1 - .../GPUImage/GPUImageJFAVoronoiFilter.h | 1 - .../Private/GPUImage/GPUImageKuwaharaFilter.h | 1 - .../GPUImage/GPUImageKuwaharaRadius3Filter.h | 1 - .../GPUImageLanczosResamplingFilter.h | 1 - .../GPUImage/GPUImageLaplacianFilter.h | 1 - .../Private/GPUImage/GPUImageLevelsFilter.h | 1 - .../GPUImage/GPUImageLightenBlendFilter.h | 1 - .../Private/GPUImage/GPUImageLineGenerator.h | 1 - .../GPUImage/GPUImageLinearBurnBlendFilter.h | 1 - .../GPUImageLocalBinaryPatternFilter.h | 1 - .../Private/GPUImage/GPUImageLookupFilter.h | 1 - .../Private/GPUImage/GPUImageLowPassFilter.h | 1 - .../GPUImage/GPUImageLuminanceRangeFilter.h | 1 - .../GPUImageLuminanceThresholdFilter.h | 1 - .../Private/GPUImage/GPUImageLuminosity.h | 1 - .../GPUImage/GPUImageLuminosityBlendFilter.h | 1 - .../Private/GPUImage/GPUImageMaskFilter.h | 1 - .../Private/GPUImage/GPUImageMedianFilter.h | 1 - .../GPUImage/GPUImageMissEtikateFilter.h | 1 - .../GPUImage/GPUImageMonochromeFilter.h | 1 - .../Private/GPUImage/GPUImageMosaicFilter.h | 1 - .../GPUImage/GPUImageMotionBlurFilter.h | 1 - .../Private/GPUImage/GPUImageMotionDetector.h | 1 - .../Headers/Private/GPUImage/GPUImageMovie.h | 1 - .../GPUImage/GPUImageMovieComposition.h | 1 - .../Private/GPUImage/GPUImageMovieWriter.h | 1 - .../GPUImage/GPUImageMultiplyBlendFilter.h | 1 - .../GPUImageNobleCornerDetectionFilter.h | 1 - .../GPUImageNonMaximumSuppressionFilter.h | 1 - .../GPUImage/GPUImageNormalBlendFilter.h | 1 - .../Private/GPUImage/GPUImageOpacityFilter.h | 1 - .../Private/GPUImage/GPUImageOpeningFilter.h | 1 - .../Headers/Private/GPUImage/GPUImageOutput.h | 1 - .../GPUImage/GPUImageOverlayBlendFilter.h | 1 - ...ageParallelCoordinateLineTransformFilter.h | 1 - .../GPUImage/GPUImagePerlinNoiseFilter.h | 1 - .../GPUImagePicture+TextureSubimage.h | 1 - .../Private/GPUImage/GPUImagePicture.h | 1 - .../GPUImage/GPUImagePinchDistortionFilter.h | 1 - .../GPUImage/GPUImagePixellateFilter.h | 1 - .../GPUImagePixellatePositionFilter.h | 1 - .../GPUImage/GPUImagePoissonBlendFilter.h | 1 - .../GPUImage/GPUImagePolarPixellateFilter.h | 1 - .../Private/GPUImage/GPUImagePolkaDotFilter.h | 1 - .../GPUImage/GPUImagePosterizeFilter.h | 1 - .../GPUImagePrewittEdgeDetectionFilter.h | 1 - .../GPUImage/GPUImageRGBClosingFilter.h | 1 - .../GPUImage/GPUImageRGBDilationFilter.h | 1 - .../GPUImage/GPUImageRGBErosionFilter.h | 1 - .../Private/GPUImage/GPUImageRGBFilter.h | 1 - .../GPUImage/GPUImageRGBOpeningFilter.h | 1 - .../Private/GPUImage/GPUImageRawDataInput.h | 1 - .../Private/GPUImage/GPUImageRawDataOutput.h | 1 - .../GPUImage/GPUImageSaturationBlendFilter.h | 1 - .../GPUImage/GPUImageSaturationFilter.h | 1 - .../GPUImage/GPUImageScreenBlendFilter.h | 1 - .../Private/GPUImage/GPUImageSepiaFilter.h | 1 - .../Private/GPUImage/GPUImageSharpenFilter.h | 1 - .../GPUImageShiTomasiFeatureDetectionFilter.h | 1 - ...PUImageSingleComponentGaussianBlurFilter.h | 1 - .../Private/GPUImage/GPUImageSketchFilter.h | 1 - .../GPUImage/GPUImageSmoothToonFilter.h | 1 - .../GPUImageSobelEdgeDetectionFilter.h | 1 - .../GPUImage/GPUImageSoftEleganceFilter.h | 1 - .../GPUImage/GPUImageSoftLightBlendFilter.h | 1 - .../GPUImage/GPUImageSolidColorGenerator.h | 1 - .../GPUImage/GPUImageSourceOverBlendFilter.h | 1 - .../GPUImage/GPUImageSphereRefractionFilter.h | 1 - .../Private/GPUImage/GPUImageStillCamera.h | 1 - .../GPUImageStretchDistortionFilter.h | 1 - .../GPUImage/GPUImageSubtractBlendFilter.h | 1 - .../Private/GPUImage/GPUImageSwirlFilter.h | 1 - .../Private/GPUImage/GPUImageTextureInput.h | 1 - .../Private/GPUImage/GPUImageTextureOutput.h | 1 - .../GPUImage/GPUImageThreeInputFilter.h | 1 - .../GPUImageThresholdEdgeDetectionFilter.h | 1 - .../GPUImage/GPUImageThresholdSketchFilter.h | 1 - ...geThresholdedNonMaximumSuppressionFilter.h | 1 - .../GPUImage/GPUImageTiltShiftFilter.h | 1 - .../GPUImage/GPUImageToneCurveFilter.h | 1 - .../Private/GPUImage/GPUImageToonFilter.h | 1 - .../GPUImage/GPUImageTransformFilter.h | 1 - ...UImageTwoInputCrossTextureSamplingFilter.h | 1 - .../Private/GPUImage/GPUImageTwoInputFilter.h | 1 - .../Private/GPUImage/GPUImageTwoPassFilter.h | 1 - .../GPUImageTwoPassTextureSamplingFilter.h | 1 - .../Private/GPUImage/GPUImageUIElement.h | 1 - .../GPUImage/GPUImageUnsharpMaskFilter.h | 1 - .../Private/GPUImage/GPUImageVideoCamera.h | 1 - .../Headers/Private/GPUImage/GPUImageView.h | 1 - .../Private/GPUImage/GPUImageVignetteFilter.h | 1 - .../GPUImage/GPUImageVoronoiConsumerFilter.h | 1 - .../GPUImageWeakPixelInclusionFilter.h | 1 - .../GPUImage/GPUImageWhiteBalanceFilter.h | 1 - .../GPUImage/GPUImageXYDerivativeFilter.h | 1 - .../Private/GPUImage/GPUImageZoomBlurFilter.h | 1 - .../Private/GPUImage/GPUImageiOSBlurFilter.h | 1 - .../Private/MBProgressHUD/MBProgressHUD.h | 1 - .../Private/MLeaksFinder/MLeakedObjectProxy.h | 1 - .../Private/MLeaksFinder/MLeaksFinder.h | 1 - .../Private/MLeaksFinder/MLeaksMessenger.h | 1 - .../MLeaksFinder/NSObject+MemoryLeak.h | 1 - .../MLeaksFinder/UIApplication+MemoryLeak.h | 1 - .../UINavigationController+MemoryLeak.h | 1 - .../UIPageViewController+MemoryLeak.h | 1 - .../UISplitViewController+MemoryLeak.h | 1 - .../UITabBarController+MemoryLeak.h | 1 - .../Private/MLeaksFinder/UITouch+MemoryLeak.h | 1 - .../Private/MLeaksFinder/UIView+MemoryLeak.h | 1 - .../UIViewController+MemoryLeak.h | 1 - .../Private/Masonry/MASCompositeConstraint.h | 1 - .../Private/Masonry/MASConstraint+Private.h | 1 - .../Headers/Private/Masonry/MASConstraint.h | 1 - .../Private/Masonry/MASConstraintMaker.h | 1 - .../Private/Masonry/MASLayoutConstraint.h | 1 - .../Headers/Private/Masonry/MASUtilities.h | 1 - .../Private/Masonry/MASViewAttribute.h | 1 - .../Private/Masonry/MASViewConstraint.h | 1 - .../Pods/Headers/Private/Masonry/Masonry.h | 1 - .../Private/Masonry/NSArray+MASAdditions.h | 1 - .../Masonry/NSArray+MASShorthandAdditions.h | 1 - .../NSLayoutConstraint+MASDebugAdditions.h | 1 - .../Private/Masonry/View+MASAdditions.h | 1 - .../Masonry/View+MASShorthandAdditions.h | 1 - .../Masonry/ViewController+MASAdditions.h | 1 - .../FBAssociationManager.h | 1 - .../FBObjectGraphConfiguration.h | 1 - .../FBRetainCycleDetector/FBObjectiveCBlock.h | 1 - .../FBObjectiveCGraphElement.h | 1 - .../FBObjectiveCNSCFTimer.h | 1 - .../FBObjectiveCObject.h | 1 - .../FBRetainCycleDetector.h | 1 - .../FBStandardGraphEdgeFilters.h | 1 - .../Pods/Headers/Public/GPUImage/GLProgram.h | 1 - .../Pods/Headers/Public/GPUImage/GPUImage.h | 1 - .../GPUImage/GPUImage3x3ConvolutionFilter.h | 1 - .../GPUImage3x3TextureSamplingFilter.h | 1 - .../GPUImageAdaptiveThresholdFilter.h | 1 - .../Public/GPUImage/GPUImageAddBlendFilter.h | 1 - .../GPUImage/GPUImageAlphaBlendFilter.h | 1 - .../Public/GPUImage/GPUImageAmatorkaFilter.h | 1 - .../Public/GPUImage/GPUImageAverageColor.h | 1 - .../GPUImageAverageLuminanceThresholdFilter.h | 1 - .../Public/GPUImage/GPUImageBilateralFilter.h | 1 - .../Public/GPUImage/GPUImageBoxBlurFilter.h | 1 - .../GPUImage/GPUImageBrightnessFilter.h | 1 - .../Headers/Public/GPUImage/GPUImageBuffer.h | 1 - .../GPUImage/GPUImageBulgeDistortionFilter.h | 1 - .../GPUImage/GPUImageCGAColorspaceFilter.h | 1 - .../GPUImageCannyEdgeDetectionFilter.h | 1 - .../GPUImage/GPUImageChromaKeyBlendFilter.h | 1 - .../Public/GPUImage/GPUImageChromaKeyFilter.h | 1 - .../Public/GPUImage/GPUImageClosingFilter.h | 1 - .../GPUImage/GPUImageColorBlendFilter.h | 1 - .../GPUImage/GPUImageColorBurnBlendFilter.h | 1 - .../GPUImage/GPUImageColorDodgeBlendFilter.h | 1 - .../GPUImage/GPUImageColorInvertFilter.h | 1 - .../GPUImage/GPUImageColorMatrixFilter.h | 1 - .../GPUImage/GPUImageColorPackingFilter.h | 1 - .../Headers/Public/GPUImage/GPUImageContext.h | 1 - .../Public/GPUImage/GPUImageContrastFilter.h | 1 - .../Public/GPUImage/GPUImageCropFilter.h | 1 - .../GPUImage/GPUImageCrosshairGenerator.h | 1 - .../GPUImage/GPUImageCrosshatchFilter.h | 1 - .../GPUImage/GPUImageDarkenBlendFilter.h | 1 - .../GPUImage/GPUImageDifferenceBlendFilter.h | 1 - .../Public/GPUImage/GPUImageDilationFilter.h | 1 - ...geDirectionalNonMaximumSuppressionFilter.h | 1 - ...ImageDirectionalSobelEdgeDetectionFilter.h | 1 - .../GPUImage/GPUImageDissolveBlendFilter.h | 1 - .../GPUImage/GPUImageDivideBlendFilter.h | 1 - .../Public/GPUImage/GPUImageEmbossFilter.h | 1 - .../Public/GPUImage/GPUImageErosionFilter.h | 1 - .../GPUImage/GPUImageExclusionBlendFilter.h | 1 - .../Public/GPUImage/GPUImageExposureFilter.h | 1 - .../GPUImageFASTCornerDetectionFilter.h | 1 - .../GPUImage/GPUImageFalseColorFilter.h | 1 - .../Headers/Public/GPUImage/GPUImageFilter.h | 1 - .../Public/GPUImage/GPUImageFilterGroup.h | 1 - .../Public/GPUImage/GPUImageFilterPipeline.h | 1 - .../Public/GPUImage/GPUImageFramebuffer.h | 1 - .../GPUImage/GPUImageFramebufferCache.h | 1 - .../Public/GPUImage/GPUImageFramework.h | 1 - .../Public/GPUImage/GPUImageGammaFilter.h | 1 - .../GPUImage/GPUImageGaussianBlurFilter.h | 1 - .../GPUImageGaussianBlurPositionFilter.h | 1 - .../GPUImageGaussianSelectiveBlurFilter.h | 1 - .../GPUImage/GPUImageGlassSphereFilter.h | 1 - .../Public/GPUImage/GPUImageGrayscaleFilter.h | 1 - .../Public/GPUImage/GPUImageHSBFilter.h | 1 - .../Public/GPUImage/GPUImageHalftoneFilter.h | 1 - .../GPUImage/GPUImageHardLightBlendFilter.h | 1 - .../GPUImageHarrisCornerDetectionFilter.h | 1 - .../Public/GPUImage/GPUImageHazeFilter.h | 1 - .../Public/GPUImage/GPUImageHighPassFilter.h | 1 - .../GPUImage/GPUImageHighlightShadowFilter.h | 1 - .../GPUImageHistogramEqualizationFilter.h | 1 - .../Public/GPUImage/GPUImageHistogramFilter.h | 1 - .../GPUImage/GPUImageHistogramGenerator.h | 1 - .../GPUImageHoughTransformLineDetector.h | 1 - .../Public/GPUImage/GPUImageHueBlendFilter.h | 1 - .../Public/GPUImage/GPUImageHueFilter.h | 1 - .../GPUImage/GPUImageJFAVoronoiFilter.h | 1 - .../Public/GPUImage/GPUImageKuwaharaFilter.h | 1 - .../GPUImage/GPUImageKuwaharaRadius3Filter.h | 1 - .../GPUImageLanczosResamplingFilter.h | 1 - .../Public/GPUImage/GPUImageLaplacianFilter.h | 1 - .../Public/GPUImage/GPUImageLevelsFilter.h | 1 - .../GPUImage/GPUImageLightenBlendFilter.h | 1 - .../Public/GPUImage/GPUImageLineGenerator.h | 1 - .../GPUImage/GPUImageLinearBurnBlendFilter.h | 1 - .../GPUImageLocalBinaryPatternFilter.h | 1 - .../Public/GPUImage/GPUImageLookupFilter.h | 1 - .../Public/GPUImage/GPUImageLowPassFilter.h | 1 - .../GPUImage/GPUImageLuminanceRangeFilter.h | 1 - .../GPUImageLuminanceThresholdFilter.h | 1 - .../Public/GPUImage/GPUImageLuminosity.h | 1 - .../GPUImage/GPUImageLuminosityBlendFilter.h | 1 - .../Public/GPUImage/GPUImageMaskFilter.h | 1 - .../Public/GPUImage/GPUImageMedianFilter.h | 1 - .../GPUImage/GPUImageMissEtikateFilter.h | 1 - .../GPUImage/GPUImageMonochromeFilter.h | 1 - .../Public/GPUImage/GPUImageMosaicFilter.h | 1 - .../GPUImage/GPUImageMotionBlurFilter.h | 1 - .../Public/GPUImage/GPUImageMotionDetector.h | 1 - .../Headers/Public/GPUImage/GPUImageMovie.h | 1 - .../GPUImage/GPUImageMovieComposition.h | 1 - .../Public/GPUImage/GPUImageMovieWriter.h | 1 - .../GPUImage/GPUImageMultiplyBlendFilter.h | 1 - .../GPUImageNobleCornerDetectionFilter.h | 1 - .../GPUImageNonMaximumSuppressionFilter.h | 1 - .../GPUImage/GPUImageNormalBlendFilter.h | 1 - .../Public/GPUImage/GPUImageOpacityFilter.h | 1 - .../Public/GPUImage/GPUImageOpeningFilter.h | 1 - .../Headers/Public/GPUImage/GPUImageOutput.h | 1 - .../GPUImage/GPUImageOverlayBlendFilter.h | 1 - ...ageParallelCoordinateLineTransformFilter.h | 1 - .../GPUImage/GPUImagePerlinNoiseFilter.h | 1 - .../GPUImagePicture+TextureSubimage.h | 1 - .../Headers/Public/GPUImage/GPUImagePicture.h | 1 - .../GPUImage/GPUImagePinchDistortionFilter.h | 1 - .../Public/GPUImage/GPUImagePixellateFilter.h | 1 - .../GPUImagePixellatePositionFilter.h | 1 - .../GPUImage/GPUImagePoissonBlendFilter.h | 1 - .../GPUImage/GPUImagePolarPixellateFilter.h | 1 - .../Public/GPUImage/GPUImagePolkaDotFilter.h | 1 - .../Public/GPUImage/GPUImagePosterizeFilter.h | 1 - .../GPUImagePrewittEdgeDetectionFilter.h | 1 - .../GPUImage/GPUImageRGBClosingFilter.h | 1 - .../GPUImage/GPUImageRGBDilationFilter.h | 1 - .../GPUImage/GPUImageRGBErosionFilter.h | 1 - .../Public/GPUImage/GPUImageRGBFilter.h | 1 - .../GPUImage/GPUImageRGBOpeningFilter.h | 1 - .../Public/GPUImage/GPUImageRawDataInput.h | 1 - .../Public/GPUImage/GPUImageRawDataOutput.h | 1 - .../GPUImage/GPUImageSaturationBlendFilter.h | 1 - .../GPUImage/GPUImageSaturationFilter.h | 1 - .../GPUImage/GPUImageScreenBlendFilter.h | 1 - .../Public/GPUImage/GPUImageSepiaFilter.h | 1 - .../Public/GPUImage/GPUImageSharpenFilter.h | 1 - .../GPUImageShiTomasiFeatureDetectionFilter.h | 1 - ...PUImageSingleComponentGaussianBlurFilter.h | 1 - .../Public/GPUImage/GPUImageSketchFilter.h | 1 - .../GPUImage/GPUImageSmoothToonFilter.h | 1 - .../GPUImageSobelEdgeDetectionFilter.h | 1 - .../GPUImage/GPUImageSoftEleganceFilter.h | 1 - .../GPUImage/GPUImageSoftLightBlendFilter.h | 1 - .../GPUImage/GPUImageSolidColorGenerator.h | 1 - .../GPUImage/GPUImageSourceOverBlendFilter.h | 1 - .../GPUImage/GPUImageSphereRefractionFilter.h | 1 - .../Public/GPUImage/GPUImageStillCamera.h | 1 - .../GPUImageStretchDistortionFilter.h | 1 - .../GPUImage/GPUImageSubtractBlendFilter.h | 1 - .../Public/GPUImage/GPUImageSwirlFilter.h | 1 - .../Public/GPUImage/GPUImageTextureInput.h | 1 - .../Public/GPUImage/GPUImageTextureOutput.h | 1 - .../GPUImage/GPUImageThreeInputFilter.h | 1 - .../GPUImageThresholdEdgeDetectionFilter.h | 1 - .../GPUImage/GPUImageThresholdSketchFilter.h | 1 - ...geThresholdedNonMaximumSuppressionFilter.h | 1 - .../Public/GPUImage/GPUImageTiltShiftFilter.h | 1 - .../Public/GPUImage/GPUImageToneCurveFilter.h | 1 - .../Public/GPUImage/GPUImageToonFilter.h | 1 - .../Public/GPUImage/GPUImageTransformFilter.h | 1 - ...UImageTwoInputCrossTextureSamplingFilter.h | 1 - .../Public/GPUImage/GPUImageTwoInputFilter.h | 1 - .../Public/GPUImage/GPUImageTwoPassFilter.h | 1 - .../GPUImageTwoPassTextureSamplingFilter.h | 1 - .../Public/GPUImage/GPUImageUIElement.h | 1 - .../GPUImage/GPUImageUnsharpMaskFilter.h | 1 - .../Public/GPUImage/GPUImageVideoCamera.h | 1 - .../Headers/Public/GPUImage/GPUImageView.h | 1 - .../Public/GPUImage/GPUImageVignetteFilter.h | 1 - .../GPUImage/GPUImageVoronoiConsumerFilter.h | 1 - .../GPUImageWeakPixelInclusionFilter.h | 1 - .../GPUImage/GPUImageWhiteBalanceFilter.h | 1 - .../GPUImage/GPUImageXYDerivativeFilter.h | 1 - .../Public/GPUImage/GPUImageZoomBlurFilter.h | 1 - .../Public/GPUImage/GPUImageiOSBlurFilter.h | 1 - .../Public/MBProgressHUD/MBProgressHUD.h | 1 - .../Public/MLeaksFinder/MLeaksFinder.h | 1 - .../Public/MLeaksFinder/NSObject+MemoryLeak.h | 1 - .../Public/Masonry/MASCompositeConstraint.h | 1 - .../Public/Masonry/MASConstraint+Private.h | 1 - .../Headers/Public/Masonry/MASConstraint.h | 1 - .../Public/Masonry/MASConstraintMaker.h | 1 - .../Public/Masonry/MASLayoutConstraint.h | 1 - .../Headers/Public/Masonry/MASUtilities.h | 1 - .../Headers/Public/Masonry/MASViewAttribute.h | 1 - .../Public/Masonry/MASViewConstraint.h | 1 - .../Pods/Headers/Public/Masonry/Masonry.h | 1 - .../Public/Masonry/NSArray+MASAdditions.h | 1 - .../Masonry/NSArray+MASShorthandAdditions.h | 1 - .../NSLayoutConstraint+MASDebugAdditions.h | 1 - .../Public/Masonry/View+MASAdditions.h | 1 - .../Masonry/View+MASShorthandAdditions.h | 1 - .../Masonry/ViewController+MASAdditions.h | 1 - iOS_Tips/Pods/MBProgressHUD/LICENSE | 19 - iOS_Tips/Pods/MBProgressHUD/MBProgressHUD.h | 443 --- iOS_Tips/Pods/MBProgressHUD/MBProgressHUD.m | 1495 --------- iOS_Tips/Pods/MBProgressHUD/README.mdown | 126 - iOS_Tips/Pods/MLeaksFinder/LICENSE | 19 - .../MLeaksFinder/MLeakedObjectProxy.h | 16 - .../MLeaksFinder/MLeakedObjectProxy.m | 141 - .../MLeaksFinder/MLeaksFinder/MLeaksFinder.h | 25 - .../MLeaksFinder/MLeaksMessenger.h | 20 - .../MLeaksFinder/MLeaksMessenger.m | 35 - .../MLeaksFinder/NSObject+MemoryLeak.h | 27 - .../MLeaksFinder/NSObject+MemoryLeak.m | 169 - .../MLeaksFinder/UIApplication+MemoryLeak.h | 18 - .../MLeaksFinder/UIApplication+MemoryLeak.m | 34 - .../UINavigationController+MemoryLeak.h | 18 - .../UINavigationController+MemoryLeak.m | 95 - .../UIPageViewController+MemoryLeak.h | 18 - .../UIPageViewController+MemoryLeak.m | 28 - .../UISplitViewController+MemoryLeak.h | 18 - .../UISplitViewController+MemoryLeak.m | 28 - .../UITabBarController+MemoryLeak.h | 18 - .../UITabBarController+MemoryLeak.m | 28 - .../MLeaksFinder/UITouch+MemoryLeak.h | 18 - .../MLeaksFinder/UITouch+MemoryLeak.m | 38 - .../MLeaksFinder/UIView+MemoryLeak.h | 18 - .../MLeaksFinder/UIView+MemoryLeak.m | 28 - .../UIViewController+MemoryLeak.h | 18 - .../UIViewController+MemoryLeak.m | 72 - iOS_Tips/Pods/MLeaksFinder/README-CN.md | 19 - iOS_Tips/Pods/Manifest.lock | 43 - iOS_Tips/Pods/Masonry/LICENSE | 19 - .../Masonry/Masonry/MASCompositeConstraint.h | 26 - .../Masonry/Masonry/MASCompositeConstraint.m | 183 - .../Masonry/Masonry/MASConstraint+Private.h | 66 - iOS_Tips/Pods/Masonry/Masonry/MASConstraint.h | 272 -- iOS_Tips/Pods/Masonry/Masonry/MASConstraint.m | 301 -- .../Pods/Masonry/Masonry/MASConstraintMaker.h | 146 - .../Pods/Masonry/Masonry/MASConstraintMaker.m | 273 -- .../Masonry/Masonry/MASLayoutConstraint.h | 22 - .../Masonry/Masonry/MASLayoutConstraint.m | 13 - iOS_Tips/Pods/Masonry/Masonry/MASUtilities.h | 136 - .../Pods/Masonry/Masonry/MASViewAttribute.h | 49 - .../Pods/Masonry/Masonry/MASViewAttribute.m | 46 - .../Pods/Masonry/Masonry/MASViewConstraint.h | 48 - .../Pods/Masonry/Masonry/MASViewConstraint.m | 401 --- iOS_Tips/Pods/Masonry/Masonry/Masonry.h | 29 - .../Masonry/Masonry/NSArray+MASAdditions.h | 72 - .../Masonry/Masonry/NSArray+MASAdditions.m | 162 - .../Masonry/NSArray+MASShorthandAdditions.h | 41 - .../NSLayoutConstraint+MASDebugAdditions.h | 16 - .../NSLayoutConstraint+MASDebugAdditions.m | 146 - .../Pods/Masonry/Masonry/View+MASAdditions.h | 111 - .../Pods/Masonry/Masonry/View+MASAdditions.m | 186 - .../Masonry/View+MASShorthandAdditions.h | 133 - .../Masonry/ViewController+MASAdditions.h | 30 - .../Masonry/ViewController+MASAdditions.m | 39 - iOS_Tips/Pods/Masonry/README.md | 415 --- iOS_Tips/Pods/Pods.xcodeproj/project.pbxproj | 2981 ----------------- .../FBRetainCycleDetector-dummy.m | 5 - .../FBRetainCycleDetector-prefix.pch | 12 - .../FBRetainCycleDetector.xcconfig | 10 - .../GPUImage/GPUImage-dummy.m | 5 - .../GPUImage/GPUImage-prefix.pch | 12 - .../GPUImage/GPUImage.debug.xcconfig | 11 - .../GPUImage/GPUImage.release.xcconfig | 11 - .../GPUImage/GPUImage.xcconfig | 11 - .../MBProgressHUD/MBProgressHUD-dummy.m | 5 - .../MBProgressHUD/MBProgressHUD-prefix.pch | 12 - .../MBProgressHUD.debug.xcconfig | 10 - .../MBProgressHUD.release.xcconfig | 10 - .../MBProgressHUD/MBProgressHUD.xcconfig | 10 - .../MLeaksFinder/MLeaksFinder-dummy.m | 5 - .../MLeaksFinder/MLeaksFinder-prefix.pch | 12 - .../MLeaksFinder/MLeaksFinder.xcconfig | 10 - .../Masonry/Masonry-dummy.m | 5 - .../Masonry/Masonry-prefix.pch | 12 - .../Masonry/Masonry.debug.xcconfig | 10 - .../Masonry/Masonry.release.xcconfig | 10 - .../Pods-DarkMode-acknowledgements.markdown | 164 - .../Pods-DarkMode-acknowledgements.plist | 232 -- .../Pods-DarkMode/Pods-DarkMode-dummy.m | 5 - ...ode-resources-Debug-input-files.xcfilelist | 6 - ...de-resources-Debug-output-files.xcfilelist | 5 - ...e-resources-Release-input-files.xcfilelist | 6 - ...-resources-Release-output-files.xcfilelist | 5 - .../Pods-DarkMode/Pods-DarkMode-resources.sh | 137 - .../Pods-DarkMode.debug.xcconfig | 10 - .../Pods-DarkMode.release.xcconfig | 10 - 890 files changed, 98 insertions(+), 46451 deletions(-) create mode 100644 iOS_Tips/DarkMode.xcodeproj/xcshareddata/xcschemes/DarkMode.xcscheme delete mode 100644 iOS_Tips/DarkMode.xcworkspace/contents.xcworkspacedata delete mode 100644 iOS_Tips/DarkMode.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 iOS_Tips/Podfile.lock delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Associations/FBAssociationManager.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Associations/FBAssociationManager.mm delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Associations/Internal/FBAssociationManager+Internal.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBNodeEnumerator.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBNodeEnumerator.mm delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBRetainCycleDetector+Internal.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBRetainCycleDetector.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBRetainCycleDetector.mm delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/FBRetainCycleUtils.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/FBRetainCycleUtils.m delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Filtering/FBStandardGraphEdgeFilters.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Filtering/FBStandardGraphEdgeFilters.mm delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectGraphConfiguration.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectGraphConfiguration.m delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCBlock.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCBlock.m delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCGraphElement.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCGraphElement.mm delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCObject.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCObject.m delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/Internal/FBObjectiveCGraphElement+Internal.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/Specialization/FBObjectiveCNSCFTimer.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/Specialization/FBObjectiveCNSCFTimer.mm delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockInterface.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockStrongLayout.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockStrongLayout.m delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockStrongRelationDetector.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockStrongRelationDetector.m delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayout.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayout.mm delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayoutHelpers.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayoutHelpers.m delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/BaseType.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/FBStructEncodingParser.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/FBStructEncodingParser.mm delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/Struct.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/Struct.mm delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/Type.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBIvarReference.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBIvarReference.m delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBObjectInStructReference.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBObjectInStructReference.m delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBObjectReference.h delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/LICENSE delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/README.md delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/fishhook/fishhook.c delete mode 100644 iOS_Tips/Pods/FBRetainCycleDetector/fishhook/fishhook.h delete mode 100755 iOS_Tips/Pods/GPUImage/License.txt delete mode 100755 iOS_Tips/Pods/GPUImage/README.md delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Resources/lookup.png delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Resources/lookup_amatorka.png delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Resources/lookup_miss_etikate.png delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Resources/lookup_soft_elegance_1.png delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Resources/lookup_soft_elegance_2.png delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GLProgram.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GLProgram.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImage.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImage3x3ConvolutionFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImage3x3ConvolutionFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImage3x3TextureSamplingFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImage3x3TextureSamplingFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAdaptiveThresholdFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAdaptiveThresholdFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAddBlendFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAddBlendFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAlphaBlendFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAlphaBlendFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAmatorkaFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAmatorkaFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAverageColor.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAverageColor.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAverageLuminanceThresholdFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAverageLuminanceThresholdFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBilateralFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBilateralFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBoxBlurFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBoxBlurFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBrightnessFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBrightnessFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBuffer.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBuffer.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBulgeDistortionFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBulgeDistortionFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCGAColorspaceFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCGAColorspaceFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCannyEdgeDetectionFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCannyEdgeDetectionFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageChromaKeyBlendFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageChromaKeyBlendFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageChromaKeyFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageChromaKeyFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageClosingFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageClosingFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorBlendFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorBlendFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorBurnBlendFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorBurnBlendFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorDodgeBlendFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorDodgeBlendFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorInvertFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorInvertFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorMatrixFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorMatrixFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorPackingFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorPackingFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageContrastFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageContrastFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCropFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCropFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCrosshairGenerator.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCrosshairGenerator.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCrosshatchFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCrosshatchFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDarkenBlendFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDarkenBlendFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDifferenceBlendFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDifferenceBlendFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDilationFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDilationFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDirectionalNonMaximumSuppressionFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDirectionalNonMaximumSuppressionFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDirectionalSobelEdgeDetectionFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDirectionalSobelEdgeDetectionFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDissolveBlendFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDissolveBlendFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDivideBlendFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDivideBlendFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageEmbossFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageEmbossFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageErosionFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageErosionFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageExclusionBlendFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageExclusionBlendFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageExposureFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageExposureFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFASTCornerDetectionFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFASTCornerDetectionFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFalseColorFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFalseColorFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilterGroup.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilterGroup.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilterPipeline.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilterPipeline.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFramebuffer.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFramebuffer.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFramebufferCache.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFramebufferCache.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGammaFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGammaFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianBlurFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianBlurFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianBlurPositionFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianBlurPositionFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianSelectiveBlurFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianSelectiveBlurFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGlassSphereFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGlassSphereFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGrayscaleFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGrayscaleFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHSBFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHSBFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHalftoneFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHalftoneFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHardLightBlendFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHardLightBlendFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHarrisCornerDetectionFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHarrisCornerDetectionFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHazeFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHazeFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHighPassFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHighPassFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHighlightShadowFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHighlightShadowFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramEqualizationFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramEqualizationFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramGenerator.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramGenerator.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHoughTransformLineDetector.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHoughTransformLineDetector.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHueBlendFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHueBlendFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHueFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHueFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageJFAVoronoiFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageJFAVoronoiFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageKuwaharaFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageKuwaharaFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageKuwaharaRadius3Filter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageKuwaharaRadius3Filter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLanczosResamplingFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLanczosResamplingFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLaplacianFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLaplacianFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLevelsFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLevelsFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLightenBlendFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLightenBlendFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLineGenerator.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLineGenerator.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLinearBurnBlendFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLinearBurnBlendFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLocalBinaryPatternFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLocalBinaryPatternFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLookupFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLookupFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLowPassFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLowPassFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminanceRangeFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminanceRangeFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminanceThresholdFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminanceThresholdFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminosity.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminosity.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminosityBlendFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminosityBlendFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMaskFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMaskFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMedianFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMedianFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMissEtikateFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMissEtikateFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMonochromeFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMonochromeFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMosaicFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMosaicFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMotionBlurFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMotionBlurFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMotionDetector.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMotionDetector.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMovie.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMovie.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMovieComposition.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMovieComposition.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMultiplyBlendFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMultiplyBlendFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNobleCornerDetectionFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNobleCornerDetectionFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNonMaximumSuppressionFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNonMaximumSuppressionFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNormalBlendFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNormalBlendFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOpacityFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOpacityFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOpeningFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOpeningFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOutput.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOutput.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOverlayBlendFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOverlayBlendFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageParallelCoordinateLineTransformFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageParallelCoordinateLineTransformFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePerlinNoiseFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePerlinNoiseFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePinchDistortionFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePinchDistortionFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePixellateFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePixellateFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePixellatePositionFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePixellatePositionFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePoissonBlendFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePoissonBlendFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePolarPixellateFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePolarPixellateFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePolkaDotFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePolkaDotFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePosterizeFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePosterizeFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePrewittEdgeDetectionFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePrewittEdgeDetectionFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBClosingFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBClosingFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBDilationFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBDilationFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBErosionFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBErosionFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBOpeningFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBOpeningFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRawDataInput.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRawDataInput.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRawDataOutput.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRawDataOutput.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSaturationBlendFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSaturationBlendFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSaturationFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSaturationFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageScreenBlendFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageScreenBlendFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSepiaFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSepiaFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSharpenFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSharpenFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageShiTomasiFeatureDetectionFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageShiTomasiFeatureDetectionFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSingleComponentGaussianBlurFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSingleComponentGaussianBlurFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSketchFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSketchFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSmoothToonFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSmoothToonFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSobelEdgeDetectionFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSobelEdgeDetectionFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSoftEleganceFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSoftEleganceFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSoftLightBlendFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSoftLightBlendFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSolidColorGenerator.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSolidColorGenerator.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSourceOverBlendFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSourceOverBlendFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSphereRefractionFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSphereRefractionFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageStillCamera.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageStillCamera.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageStretchDistortionFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageStretchDistortionFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSubtractBlendFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSubtractBlendFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSwirlFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSwirlFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTextureInput.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTextureInput.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTextureOutput.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTextureOutput.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThreeInputFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThreeInputFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdEdgeDetectionFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdEdgeDetectionFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdSketchFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdSketchFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdedNonMaximumSuppressionFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdedNonMaximumSuppressionFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTiltShiftFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTiltShiftFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageToneCurveFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageToneCurveFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageToonFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageToonFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTransformFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTransformFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoInputCrossTextureSamplingFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoInputCrossTextureSamplingFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoInputFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoInputFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoPassFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoPassFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoPassTextureSamplingFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoPassTextureSamplingFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageUIElement.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageUIElement.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageUnsharpMaskFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageUnsharpMaskFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVideoCamera.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVideoCamera.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVignetteFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVignetteFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVoronoiConsumerFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVoronoiConsumerFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageWeakPixelInclusionFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageWeakPixelInclusionFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageWhiteBalanceFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageWhiteBalanceFilter.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageXYDerivativeFilter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageXYDerivativeFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageZoomBlurFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageZoomBlurFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageiOSBlurFilter.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/GPUImageiOSBlurFilter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/iOS/Framework/GPUImageFramework.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageContext.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageContext.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageMovieWriter.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageMovieWriter.m delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImagePicture+TextureSubimage.h delete mode 100644 iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImagePicture+TextureSubimage.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImagePicture.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImagePicture.m delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageView.h delete mode 100755 iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageView.m delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/BaseType.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBAssociationManager+Internal.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBAssociationManager.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBBlockInterface.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBBlockStrongLayout.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBBlockStrongRelationDetector.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBClassStrongLayout.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBClassStrongLayoutHelpers.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBIvarReference.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBNodeEnumerator.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectGraphConfiguration.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectInStructReference.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectReference.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectiveCBlock.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectiveCGraphElement+Internal.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectiveCGraphElement.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectiveCNSCFTimer.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectiveCObject.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBRetainCycleDetector+Internal.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBRetainCycleDetector.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBRetainCycleUtils.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBStandardGraphEdgeFilters.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBStructEncodingParser.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/Struct.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/Type.h delete mode 120000 iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/fishhook.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GLProgram.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImage.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImage3x3ConvolutionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImage3x3TextureSamplingFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAdaptiveThresholdFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAddBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAlphaBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAmatorkaFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAverageColor.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAverageLuminanceThresholdFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageBilateralFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageBoxBlurFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageBrightnessFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageBuffer.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageBulgeDistortionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageCGAColorspaceFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageCannyEdgeDetectionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageChromaKeyBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageChromaKeyFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageClosingFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorBurnBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorDodgeBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorInvertFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorMatrixFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorPackingFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageContext.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageContrastFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageCropFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageCrosshairGenerator.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageCrosshatchFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDarkenBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDifferenceBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDilationFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDirectionalNonMaximumSuppressionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDirectionalSobelEdgeDetectionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDissolveBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDivideBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageEmbossFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageErosionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageExclusionBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageExposureFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFASTCornerDetectionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFalseColorFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFilterGroup.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFilterPipeline.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFramebuffer.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFramebufferCache.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFramework.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGammaFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGaussianBlurFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGaussianBlurPositionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGaussianSelectiveBlurFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGlassSphereFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGrayscaleFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHSBFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHalftoneFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHardLightBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHarrisCornerDetectionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHazeFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHighPassFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHighlightShadowFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHistogramEqualizationFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHistogramFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHistogramGenerator.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHoughTransformLineDetector.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHueBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHueFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageJFAVoronoiFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageKuwaharaFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageKuwaharaRadius3Filter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLanczosResamplingFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLaplacianFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLevelsFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLightenBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLineGenerator.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLinearBurnBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLocalBinaryPatternFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLookupFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLowPassFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLuminanceRangeFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLuminanceThresholdFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLuminosity.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLuminosityBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMaskFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMedianFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMissEtikateFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMonochromeFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMosaicFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMotionBlurFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMotionDetector.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMovie.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMovieComposition.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMovieWriter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMultiplyBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageNobleCornerDetectionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageNonMaximumSuppressionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageNormalBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageOpacityFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageOpeningFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageOutput.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageOverlayBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageParallelCoordinateLineTransformFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePerlinNoiseFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePicture+TextureSubimage.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePicture.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePinchDistortionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePixellateFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePixellatePositionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePoissonBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePolarPixellateFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePolkaDotFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePosterizeFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePrewittEdgeDetectionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRGBClosingFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRGBDilationFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRGBErosionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRGBFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRGBOpeningFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRawDataInput.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRawDataOutput.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSaturationBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSaturationFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageScreenBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSepiaFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSharpenFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageShiTomasiFeatureDetectionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSingleComponentGaussianBlurFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSketchFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSmoothToonFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSobelEdgeDetectionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSoftEleganceFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSoftLightBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSolidColorGenerator.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSourceOverBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSphereRefractionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageStillCamera.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageStretchDistortionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSubtractBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSwirlFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTextureInput.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTextureOutput.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageThreeInputFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageThresholdEdgeDetectionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageThresholdSketchFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageThresholdedNonMaximumSuppressionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTiltShiftFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageToneCurveFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageToonFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTransformFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTwoInputCrossTextureSamplingFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTwoInputFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTwoPassFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTwoPassTextureSamplingFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageUIElement.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageUnsharpMaskFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageVideoCamera.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageView.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageVignetteFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageVoronoiConsumerFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageWeakPixelInclusionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageWhiteBalanceFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageXYDerivativeFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageZoomBlurFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageiOSBlurFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Private/MBProgressHUD/MBProgressHUD.h delete mode 120000 iOS_Tips/Pods/Headers/Private/MLeaksFinder/MLeakedObjectProxy.h delete mode 120000 iOS_Tips/Pods/Headers/Private/MLeaksFinder/MLeaksFinder.h delete mode 120000 iOS_Tips/Pods/Headers/Private/MLeaksFinder/MLeaksMessenger.h delete mode 120000 iOS_Tips/Pods/Headers/Private/MLeaksFinder/NSObject+MemoryLeak.h delete mode 120000 iOS_Tips/Pods/Headers/Private/MLeaksFinder/UIApplication+MemoryLeak.h delete mode 120000 iOS_Tips/Pods/Headers/Private/MLeaksFinder/UINavigationController+MemoryLeak.h delete mode 120000 iOS_Tips/Pods/Headers/Private/MLeaksFinder/UIPageViewController+MemoryLeak.h delete mode 120000 iOS_Tips/Pods/Headers/Private/MLeaksFinder/UISplitViewController+MemoryLeak.h delete mode 120000 iOS_Tips/Pods/Headers/Private/MLeaksFinder/UITabBarController+MemoryLeak.h delete mode 120000 iOS_Tips/Pods/Headers/Private/MLeaksFinder/UITouch+MemoryLeak.h delete mode 120000 iOS_Tips/Pods/Headers/Private/MLeaksFinder/UIView+MemoryLeak.h delete mode 120000 iOS_Tips/Pods/Headers/Private/MLeaksFinder/UIViewController+MemoryLeak.h delete mode 120000 iOS_Tips/Pods/Headers/Private/Masonry/MASCompositeConstraint.h delete mode 120000 iOS_Tips/Pods/Headers/Private/Masonry/MASConstraint+Private.h delete mode 120000 iOS_Tips/Pods/Headers/Private/Masonry/MASConstraint.h delete mode 120000 iOS_Tips/Pods/Headers/Private/Masonry/MASConstraintMaker.h delete mode 120000 iOS_Tips/Pods/Headers/Private/Masonry/MASLayoutConstraint.h delete mode 120000 iOS_Tips/Pods/Headers/Private/Masonry/MASUtilities.h delete mode 120000 iOS_Tips/Pods/Headers/Private/Masonry/MASViewAttribute.h delete mode 120000 iOS_Tips/Pods/Headers/Private/Masonry/MASViewConstraint.h delete mode 120000 iOS_Tips/Pods/Headers/Private/Masonry/Masonry.h delete mode 120000 iOS_Tips/Pods/Headers/Private/Masonry/NSArray+MASAdditions.h delete mode 120000 iOS_Tips/Pods/Headers/Private/Masonry/NSArray+MASShorthandAdditions.h delete mode 120000 iOS_Tips/Pods/Headers/Private/Masonry/NSLayoutConstraint+MASDebugAdditions.h delete mode 120000 iOS_Tips/Pods/Headers/Private/Masonry/View+MASAdditions.h delete mode 120000 iOS_Tips/Pods/Headers/Private/Masonry/View+MASShorthandAdditions.h delete mode 120000 iOS_Tips/Pods/Headers/Private/Masonry/ViewController+MASAdditions.h delete mode 120000 iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBAssociationManager.h delete mode 120000 iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBObjectGraphConfiguration.h delete mode 120000 iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBObjectiveCBlock.h delete mode 120000 iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBObjectiveCGraphElement.h delete mode 120000 iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBObjectiveCNSCFTimer.h delete mode 120000 iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBObjectiveCObject.h delete mode 120000 iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBRetainCycleDetector.h delete mode 120000 iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBStandardGraphEdgeFilters.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GLProgram.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImage.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImage3x3ConvolutionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImage3x3TextureSamplingFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAdaptiveThresholdFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAddBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAlphaBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAmatorkaFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAverageColor.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAverageLuminanceThresholdFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageBilateralFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageBoxBlurFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageBrightnessFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageBuffer.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageBulgeDistortionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageCGAColorspaceFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageCannyEdgeDetectionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageChromaKeyBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageChromaKeyFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageClosingFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorBurnBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorDodgeBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorInvertFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorMatrixFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorPackingFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageContext.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageContrastFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageCropFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageCrosshairGenerator.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageCrosshatchFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDarkenBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDifferenceBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDilationFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDirectionalNonMaximumSuppressionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDirectionalSobelEdgeDetectionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDissolveBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDivideBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageEmbossFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageErosionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageExclusionBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageExposureFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFASTCornerDetectionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFalseColorFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFilterGroup.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFilterPipeline.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFramebuffer.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFramebufferCache.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFramework.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGammaFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGaussianBlurFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGaussianBlurPositionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGaussianSelectiveBlurFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGlassSphereFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGrayscaleFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHSBFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHalftoneFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHardLightBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHarrisCornerDetectionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHazeFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHighPassFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHighlightShadowFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHistogramEqualizationFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHistogramFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHistogramGenerator.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHoughTransformLineDetector.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHueBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHueFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageJFAVoronoiFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageKuwaharaFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageKuwaharaRadius3Filter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLanczosResamplingFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLaplacianFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLevelsFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLightenBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLineGenerator.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLinearBurnBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLocalBinaryPatternFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLookupFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLowPassFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLuminanceRangeFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLuminanceThresholdFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLuminosity.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLuminosityBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMaskFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMedianFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMissEtikateFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMonochromeFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMosaicFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMotionBlurFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMotionDetector.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMovie.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMovieComposition.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMovieWriter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMultiplyBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageNobleCornerDetectionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageNonMaximumSuppressionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageNormalBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageOpacityFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageOpeningFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageOutput.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageOverlayBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageParallelCoordinateLineTransformFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePerlinNoiseFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePicture+TextureSubimage.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePicture.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePinchDistortionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePixellateFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePixellatePositionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePoissonBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePolarPixellateFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePolkaDotFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePosterizeFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePrewittEdgeDetectionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRGBClosingFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRGBDilationFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRGBErosionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRGBFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRGBOpeningFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRawDataInput.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRawDataOutput.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSaturationBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSaturationFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageScreenBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSepiaFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSharpenFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageShiTomasiFeatureDetectionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSingleComponentGaussianBlurFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSketchFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSmoothToonFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSobelEdgeDetectionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSoftEleganceFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSoftLightBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSolidColorGenerator.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSourceOverBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSphereRefractionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageStillCamera.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageStretchDistortionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSubtractBlendFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSwirlFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTextureInput.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTextureOutput.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageThreeInputFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageThresholdEdgeDetectionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageThresholdSketchFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageThresholdedNonMaximumSuppressionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTiltShiftFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageToneCurveFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageToonFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTransformFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTwoInputCrossTextureSamplingFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTwoInputFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTwoPassFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTwoPassTextureSamplingFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageUIElement.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageUnsharpMaskFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageVideoCamera.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageView.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageVignetteFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageVoronoiConsumerFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageWeakPixelInclusionFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageWhiteBalanceFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageXYDerivativeFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageZoomBlurFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageiOSBlurFilter.h delete mode 120000 iOS_Tips/Pods/Headers/Public/MBProgressHUD/MBProgressHUD.h delete mode 120000 iOS_Tips/Pods/Headers/Public/MLeaksFinder/MLeaksFinder.h delete mode 120000 iOS_Tips/Pods/Headers/Public/MLeaksFinder/NSObject+MemoryLeak.h delete mode 120000 iOS_Tips/Pods/Headers/Public/Masonry/MASCompositeConstraint.h delete mode 120000 iOS_Tips/Pods/Headers/Public/Masonry/MASConstraint+Private.h delete mode 120000 iOS_Tips/Pods/Headers/Public/Masonry/MASConstraint.h delete mode 120000 iOS_Tips/Pods/Headers/Public/Masonry/MASConstraintMaker.h delete mode 120000 iOS_Tips/Pods/Headers/Public/Masonry/MASLayoutConstraint.h delete mode 120000 iOS_Tips/Pods/Headers/Public/Masonry/MASUtilities.h delete mode 120000 iOS_Tips/Pods/Headers/Public/Masonry/MASViewAttribute.h delete mode 120000 iOS_Tips/Pods/Headers/Public/Masonry/MASViewConstraint.h delete mode 120000 iOS_Tips/Pods/Headers/Public/Masonry/Masonry.h delete mode 120000 iOS_Tips/Pods/Headers/Public/Masonry/NSArray+MASAdditions.h delete mode 120000 iOS_Tips/Pods/Headers/Public/Masonry/NSArray+MASShorthandAdditions.h delete mode 120000 iOS_Tips/Pods/Headers/Public/Masonry/NSLayoutConstraint+MASDebugAdditions.h delete mode 120000 iOS_Tips/Pods/Headers/Public/Masonry/View+MASAdditions.h delete mode 120000 iOS_Tips/Pods/Headers/Public/Masonry/View+MASShorthandAdditions.h delete mode 120000 iOS_Tips/Pods/Headers/Public/Masonry/ViewController+MASAdditions.h delete mode 100644 iOS_Tips/Pods/MBProgressHUD/LICENSE delete mode 100644 iOS_Tips/Pods/MBProgressHUD/MBProgressHUD.h delete mode 100644 iOS_Tips/Pods/MBProgressHUD/MBProgressHUD.m delete mode 100644 iOS_Tips/Pods/MBProgressHUD/README.mdown delete mode 100644 iOS_Tips/Pods/MLeaksFinder/LICENSE delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/MLeakedObjectProxy.h delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/MLeakedObjectProxy.m delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/MLeaksFinder.h delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/MLeaksMessenger.h delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/MLeaksMessenger.m delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/NSObject+MemoryLeak.h delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/NSObject+MemoryLeak.m delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIApplication+MemoryLeak.h delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIApplication+MemoryLeak.m delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UINavigationController+MemoryLeak.h delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UINavigationController+MemoryLeak.m delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIPageViewController+MemoryLeak.h delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIPageViewController+MemoryLeak.m delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UISplitViewController+MemoryLeak.h delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UISplitViewController+MemoryLeak.m delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UITabBarController+MemoryLeak.h delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UITabBarController+MemoryLeak.m delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UITouch+MemoryLeak.h delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UITouch+MemoryLeak.m delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIView+MemoryLeak.h delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIView+MemoryLeak.m delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIViewController+MemoryLeak.h delete mode 100644 iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIViewController+MemoryLeak.m delete mode 100644 iOS_Tips/Pods/MLeaksFinder/README-CN.md delete mode 100644 iOS_Tips/Pods/Manifest.lock delete mode 100644 iOS_Tips/Pods/Masonry/LICENSE delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/MASCompositeConstraint.h delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/MASCompositeConstraint.m delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/MASConstraint+Private.h delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/MASConstraint.h delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/MASConstraint.m delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/MASConstraintMaker.h delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/MASConstraintMaker.m delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/MASLayoutConstraint.h delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/MASLayoutConstraint.m delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/MASUtilities.h delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/MASViewAttribute.h delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/MASViewAttribute.m delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/MASViewConstraint.h delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/MASViewConstraint.m delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/Masonry.h delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/NSArray+MASAdditions.h delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/NSArray+MASAdditions.m delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/NSArray+MASShorthandAdditions.h delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/NSLayoutConstraint+MASDebugAdditions.h delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/NSLayoutConstraint+MASDebugAdditions.m delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/View+MASAdditions.h delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/View+MASAdditions.m delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/View+MASShorthandAdditions.h delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/ViewController+MASAdditions.h delete mode 100644 iOS_Tips/Pods/Masonry/Masonry/ViewController+MASAdditions.m delete mode 100644 iOS_Tips/Pods/Masonry/README.md delete mode 100644 iOS_Tips/Pods/Pods.xcodeproj/project.pbxproj delete mode 100644 iOS_Tips/Pods/Target Support Files/FBRetainCycleDetector/FBRetainCycleDetector-dummy.m delete mode 100644 iOS_Tips/Pods/Target Support Files/FBRetainCycleDetector/FBRetainCycleDetector-prefix.pch delete mode 100644 iOS_Tips/Pods/Target Support Files/FBRetainCycleDetector/FBRetainCycleDetector.xcconfig delete mode 100644 iOS_Tips/Pods/Target Support Files/GPUImage/GPUImage-dummy.m delete mode 100644 iOS_Tips/Pods/Target Support Files/GPUImage/GPUImage-prefix.pch delete mode 100644 iOS_Tips/Pods/Target Support Files/GPUImage/GPUImage.debug.xcconfig delete mode 100644 iOS_Tips/Pods/Target Support Files/GPUImage/GPUImage.release.xcconfig delete mode 100644 iOS_Tips/Pods/Target Support Files/GPUImage/GPUImage.xcconfig delete mode 100644 iOS_Tips/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-dummy.m delete mode 100644 iOS_Tips/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-prefix.pch delete mode 100644 iOS_Tips/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.debug.xcconfig delete mode 100644 iOS_Tips/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.release.xcconfig delete mode 100644 iOS_Tips/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.xcconfig delete mode 100644 iOS_Tips/Pods/Target Support Files/MLeaksFinder/MLeaksFinder-dummy.m delete mode 100644 iOS_Tips/Pods/Target Support Files/MLeaksFinder/MLeaksFinder-prefix.pch delete mode 100644 iOS_Tips/Pods/Target Support Files/MLeaksFinder/MLeaksFinder.xcconfig delete mode 100644 iOS_Tips/Pods/Target Support Files/Masonry/Masonry-dummy.m delete mode 100644 iOS_Tips/Pods/Target Support Files/Masonry/Masonry-prefix.pch delete mode 100644 iOS_Tips/Pods/Target Support Files/Masonry/Masonry.debug.xcconfig delete mode 100644 iOS_Tips/Pods/Target Support Files/Masonry/Masonry.release.xcconfig delete mode 100644 iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-acknowledgements.markdown delete mode 100644 iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-acknowledgements.plist delete mode 100644 iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-dummy.m delete mode 100644 iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-resources-Debug-input-files.xcfilelist delete mode 100644 iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-resources-Debug-output-files.xcfilelist delete mode 100644 iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-resources-Release-input-files.xcfilelist delete mode 100644 iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-resources-Release-output-files.xcfilelist delete mode 100755 iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-resources.sh delete mode 100644 iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode.debug.xcconfig delete mode 100644 iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode.release.xcconfig diff --git a/.DS_Store b/.DS_Store index b8d57b474fd5822e911df723f1ae4be612ed825e..6702a13f40249250b4401664897ab48a3077d2dd 100644 GIT binary patch delta 170 zcmZp1XmQx!E5O{OmOVK@K!UAFB~MJ-b8?=56pYy?AjQn8C$M?7z-$%{Lt`Ty1!Dt~ z$$p~o%o<(clQ)PeaLnp5*vRX7$Pvg9oBU3ciwz<$`JbpVb3g(EP*`NMg%}?@CA!Zr F0syFxGui+E delta 170 zcmZp1XmQx!E5ID(cz1GufCO9W-3fjnhLiIIq+rZG0V!sdBM&yO7MRV#VQOHhqhM@i zG}%uyo>|rK)8q}J3LHfjADYc`KjaAHh)sSc%Ebl|nEX#vnb~^*15j9GvxOKRJ0-f$ GFaiMJyF5++ diff --git a/iOS_Tips/.DS_Store b/iOS_Tips/.DS_Store index d08765152a9de4751076b6da3014e43b32a26515..8c4ab2dc6d1cf2d0178693b6200368214c93a819 100644 GIT binary patch delta 201 zcmZn(XbG6$&nU4mU^hRb#N5rqj`&okz+H&0S^>lCf(&F=eAxV2f`>_zg&_dw+7yQ3r1IhdsBgbajuBYNC0<=^ zW~ifJY-BcBKv16P;GxNeg7Wo;fv$n;LGhR7*}2Ga$Ub@TeS7XCVDO{LBixQn9>ulx n6M$Ml_6k89TNYfDmy@5D4iseESXj@rnO(t^9W_!3#Bu-td?KHB diff --git a/iOS_Tips/DarkMode.xcodeproj/xcshareddata/xcschemes/DarkMode.xcscheme b/iOS_Tips/DarkMode.xcodeproj/xcshareddata/xcschemes/DarkMode.xcscheme new file mode 100644 index 00000000..f394f659 --- /dev/null +++ b/iOS_Tips/DarkMode.xcodeproj/xcshareddata/xcschemes/DarkMode.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOS_Tips/DarkMode.xcworkspace/contents.xcworkspacedata b/iOS_Tips/DarkMode.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index a8c127c2..00000000 --- a/iOS_Tips/DarkMode.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/iOS_Tips/DarkMode.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/iOS_Tips/DarkMode.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/iOS_Tips/DarkMode.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/iOS_Tips/Podfile.lock b/iOS_Tips/Podfile.lock deleted file mode 100644 index 3be33660..00000000 --- a/iOS_Tips/Podfile.lock +++ /dev/null @@ -1,43 +0,0 @@ -PODS: - - GPUImage (0.1.7) - - Masonry (1.1.0) - - MBProgressHUD (1.1.0) - - YYCache (1.0.4) - - YYImage (1.0.4): - - YYImage/Core (= 1.0.4) - - YYImage/Core (1.0.4) - - YYModel (1.0.4) - - YYWebImage (1.0.5): - - YYCache - - YYImage - -DEPENDENCIES: - - GPUImage - - Masonry - - MBProgressHUD - - YYImage - - YYModel - - YYWebImage - -SPEC REPOS: - https://github.com/CocoaPods/Specs.git: - - GPUImage - - Masonry - - MBProgressHUD - - YYCache - - YYImage - - YYModel - - YYWebImage - -SPEC CHECKSUMS: - GPUImage: 733a5f0fab92df9de1c37ba9df520a833ccb406d - Masonry: 678fab65091a9290e40e2832a55e7ab731aad201 - MBProgressHUD: e7baa36a220447d8aeb12769bf0585582f3866d9 - YYCache: 8105b6638f5e849296c71f331ff83891a4942952 - YYImage: 1e1b62a9997399593e4b9c4ecfbbabbf1d3f3b54 - YYModel: 2a7fdd96aaa4b86a824e26d0c517de8928c04b30 - YYWebImage: 5f7f36aee2ae293f016d418c7d6ba05c4863e928 - -PODFILE CHECKSUM: b400933f5b26aee061a3055185a9866897951c9e - -COCOAPODS: 1.9.1 diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Associations/FBAssociationManager.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Associations/FBAssociationManager.h deleted file mode 100644 index d2b91335..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Associations/FBAssociationManager.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -/** - FBAssociationManager is a tracker of object associations. For given object it can return all objects that - are being retained by this object with objc_setAssociatedObject & retain policy. - */ -@interface FBAssociationManager : NSObject - -/** - Start tracking associations. It will use fishhook to swizzle C methods: - objc_(set/remove)AssociatedObject and inject some tracker code. - */ -+ (void)hook; - -/** - Stop tracking associations, fishhooks. - */ -+ (void)unhook; - -/** - For given object return all objects that are retained by it using associated objects. - - @return NSArray of objects associated with given object - */ -+ (nullable NSArray *)associationsForObject:(nullable id)object; - -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Associations/FBAssociationManager.mm b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Associations/FBAssociationManager.mm deleted file mode 100644 index c0e0e402..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Associations/FBAssociationManager.mm +++ /dev/null @@ -1,207 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#if __has_feature(objc_arc) -#error This file must be compiled with MRR. Use -fno-objc-arc flag. -#endif - -#import -#import -#import -#import -#import -#import -#import - -#import "FBAssociationManager+Internal.h" -#import "FBRetainCycleDetector.h" - -#import "fishhook.h" - -#if _INTERNAL_RCD_ENABLED - -namespace FB { namespace AssociationManager { - using ObjectAssociationSet = std::unordered_set; - using AssociationMap = std::unordered_map; - - static auto _associationMap = new AssociationMap(); - static auto _associationMutex = new std::mutex; - - static std::mutex *hookMutex(new std::mutex); - static bool hookTaken = false; - - void _threadUnsafeResetAssociationAtKey(id object, void *key) { - auto i = _associationMap->find(object); - - if (i == _associationMap->end()) { - return; - } - - auto *refs = i->second; - auto j = refs->find(key); - if (j != refs->end()) { - refs->erase(j); - } - } - - void _threadUnsafeSetStrongAssociation(id object, void *key, id value) { - if (value) { - auto i = _associationMap->find(object); - ObjectAssociationSet *refs; - if (i != _associationMap->end()) { - refs = i->second; - } else { - refs = new ObjectAssociationSet; - (*_associationMap)[object] = refs; - } - refs->insert(key); - } else { - _threadUnsafeResetAssociationAtKey(object, key); - } - } - - void _threadUnsafeRemoveAssociations(id object) { - if (_associationMap->size() == 0 ){ - return; - } - - auto i = _associationMap->find(object); - if (i == _associationMap->end()) { - return; - } - - auto *refs = i->second; - delete refs; - _associationMap->erase(i); - } - - NSArray *associations(id object) { - std::lock_guard l(*_associationMutex); - if (_associationMap->size() == 0 ){ - return nil; - } - - auto i = _associationMap->find(object); - if (i == _associationMap->end()) { - return nil; - } - - auto *refs = i->second; - - NSMutableArray *array = [NSMutableArray array]; - for (auto &key: *refs) { - id value = objc_getAssociatedObject(object, key); - if (value) { - [array addObject:value]; - } - } - - return array; - } - - static void (*fb_orig_objc_setAssociatedObject)(id object, void *key, id value, objc_AssociationPolicy policy); - static void (*fb_orig_objc_removeAssociatedObjects)(id object); - - static void fb_objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy) { - { - std::lock_guard l(*_associationMutex); - // Track strong references only - if (policy == OBJC_ASSOCIATION_RETAIN || - policy == OBJC_ASSOCIATION_RETAIN_NONATOMIC) { - _threadUnsafeSetStrongAssociation(object, key, value); - } else { - // We can change the policy, we need to clear out the key - _threadUnsafeResetAssociationAtKey(object, key); - } - } - - /** - We are doing that behind the lock. Otherwise it could deadlock. - The reason for that is when objc calls up _object_set_associative_reference, when we nil out - a reference for some object, it will also release this value, which could cause it to dealloc. - This is done inside _object_set_associative_reference without lock. Otherwise it would deadlock, - since the object that is released, could also clean up some associated objects. - - If we would keep a lock during that, we would fall for that deadlock. - - Unfortunately this also means the association manager can be not a 100% accurate, since there - can technically be a race condition between setting values on the same object and same key from - different threads. (One thread sets value, other nil, we are missing this value) - */ - fb_orig_objc_setAssociatedObject(object, key, value, policy); - } - - static void fb_objc_removeAssociatedObjects(id object) { - { - std::lock_guard l(*_associationMutex); - _threadUnsafeRemoveAssociations(object); - } - - fb_orig_objc_removeAssociatedObjects(object); - } - - static void cleanUp() { - std::lock_guard l(*_associationMutex); - _associationMap->clear(); - } - -} } - -#endif - -@implementation FBAssociationManager - -+ (void)hook -{ -#if _INTERNAL_RCD_ENABLED - std::lock_guard l(*FB::AssociationManager::hookMutex); - rcd_rebind_symbols((struct rcd_rebinding[2]){ - { - "objc_setAssociatedObject", - (void *)FB::AssociationManager::fb_objc_setAssociatedObject, - (void **)&FB::AssociationManager::fb_orig_objc_setAssociatedObject - }, - { - "objc_removeAssociatedObjects", - (void *)FB::AssociationManager::fb_objc_removeAssociatedObjects, - (void **)&FB::AssociationManager::fb_orig_objc_removeAssociatedObjects - }}, 2); - FB::AssociationManager::hookTaken = true; -#endif //_INTERNAL_RCD_ENABLED -} - -+ (void)unhook -{ -#if _INTERNAL_RCD_ENABLED - std::lock_guard l(*FB::AssociationManager::hookMutex); - if (FB::AssociationManager::hookTaken) { - rcd_rebind_symbols((struct rcd_rebinding[2]){ - { - "objc_setAssociatedObject", - (void *)FB::AssociationManager::fb_orig_objc_setAssociatedObject, - }, - { - "objc_removeAssociatedObjects", - (void *)FB::AssociationManager::fb_orig_objc_removeAssociatedObjects, - }}, 2); - FB::AssociationManager::cleanUp(); - } -#endif //_INTERNAL_RCD_ENABLED -} - -+ (NSArray *)associationsForObject:(id)object -{ -#if _INTERNAL_RCD_ENABLED - return FB::AssociationManager::associations(object); -#else - return nil; -#endif //_INTERNAL_RCD_ENABLED -} - -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Associations/Internal/FBAssociationManager+Internal.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Associations/Internal/FBAssociationManager+Internal.h deleted file mode 100644 index 220be959..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Associations/Internal/FBAssociationManager+Internal.h +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "FBAssociationManager.h" -#import "FBRetainCycleDetector.h" - -#if _INTERNAL_RCD_ENABLED - -namespace FB { namespace AssociationManager { - - void _threadUnsafeResetAssociationAtKey(id object, void *key); - void _threadUnsafeSetStrongAssociation(id object, void *key, id value); - void _threadUnsafeRemoveAssociations(id object); - - NSArray *associations(id object); - -} } - -#endif diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBNodeEnumerator.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBNodeEnumerator.h deleted file mode 100644 index ecf15478..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBNodeEnumerator.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -@class FBObjectiveCGraphElement; - -/** - FBNodeEnumerator wraps any object graph element (FBObjectiveCGraphElement) and lets you enumerate over its - retained references - */ -@interface FBNodeEnumerator : NSEnumerator - -/** - Designated initializer - */ -- (nonnull instancetype)initWithObject:(nonnull FBObjectiveCGraphElement *)object; - -- (nullable FBNodeEnumerator *)nextObject; - -@property (nonatomic, strong, readonly, nonnull) FBObjectiveCGraphElement *object; - -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBNodeEnumerator.mm b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBNodeEnumerator.mm deleted file mode 100644 index de38173e..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBNodeEnumerator.mm +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "FBNodeEnumerator.h" - -#import "FBObjectiveCGraphElement.h" - -@implementation FBNodeEnumerator -{ - NSSet *_retainedObjectsSnapshot; - NSEnumerator *_enumerator; -} - -- (instancetype)initWithObject:(FBObjectiveCGraphElement *)object -{ - if (self = [super init]) { - _object = object; - } - - return self; -} - -- (FBNodeEnumerator *)nextObject -{ - if (!_object) { - return nil; - } else if (!_retainedObjectsSnapshot) { - _retainedObjectsSnapshot = [_object allRetainedObjects]; - _enumerator = [_retainedObjectsSnapshot objectEnumerator]; - } - - FBObjectiveCGraphElement *next = [_enumerator nextObject]; - - if (next) { - return [[FBNodeEnumerator alloc] initWithObject:next]; - } - - return nil; -} - -- (BOOL)isEqual:(id)object -{ - if ([object isKindOfClass:[FBNodeEnumerator class]]) { - FBNodeEnumerator *enumerator = (FBNodeEnumerator *)object; - return [self.object isEqual:enumerator.object]; - } - - return NO; -} - -- (NSUInteger)hash -{ - return [self.object hash]; -} - -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBRetainCycleDetector+Internal.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBRetainCycleDetector+Internal.h deleted file mode 100644 index 62c21f7f..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBRetainCycleDetector+Internal.h +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "FBRetainCycleDetector.h" - -@interface FBRetainCycleDetector () - -// Unit tests -- (NSArray *)_shiftToUnifiedCycle:(NSArray *)array; - -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBRetainCycleDetector.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBRetainCycleDetector.h deleted file mode 100644 index f86992c0..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBRetainCycleDetector.h +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -//! Project version number for FBRetainCycleDetector. -FOUNDATION_EXPORT double FBRetainCycleDetectorVersionNumber; - -//! Project version string for FBRetainCycleDetector. -FOUNDATION_EXPORT const unsigned char FBRetainCycleDetectorVersionString[]; - -#import "FBAssociationManager.h" -#import "FBObjectiveCBlock.h" -#import "FBObjectiveCGraphElement.h" -#import "FBObjectiveCNSCFTimer.h" -#import "FBObjectiveCObject.h" -#import "FBObjectGraphConfiguration.h" -#import "FBStandardGraphEdgeFilters.h" - -/** - Retain Cycle Detector is enabled by default in DEBUG builds, but you can also force it in other builds by - uncommenting the line below. Beware, Retain Cycle Detector uses some private APIs that shouldn't be compiled in - production builds. - */ -//#define RETAIN_CYCLE_DETECTOR_ENABLED 1 - -/** - FBRetainCycleDetector - - The main class responsible for detecting retain cycles. - - Be cautious, the class is NOT thread safe. - - The process of detecting retain cycles is relatively slow and consumes a lot of CPU. - */ - -@interface FBRetainCycleDetector : NSObject - -/** - Designated initializer - - @param configuration Configuration for detector. Can include specific filters and options. - @see FBRetainCycleDetectorConfiguration - */ -- (nonnull instancetype)initWithConfiguration:(nonnull FBObjectGraphConfiguration *)configuration NS_DESIGNATED_INITIALIZER; - -/** - Adds candidate you are interested in getting retain cycles from. - - @param candidate Any Objective-C object you want to verify for cycles. - */ -- (void)addCandidate:(nonnull id)candidate; - -/** - Searches for all retain cycles for all candidates the detector has been - provided with. - - @return NSSet with retain cycles. An element of this array will be - an array representing retain cycle. That array will hold elements - of type FBObjectiveCGraphElement. - - @discussion For given candidate, the detector will go through all object graph rooted in this candidate and return - ALL retain cycles that this candidate references. It will also take care of removing duplicates. It will not look for - cycles longer than 10 elements. If you want to look for longer ones use findRetainCyclesWithMaxCycleLenght: - */ -- (nonnull NSSet *> *)findRetainCycles; - -- (nonnull NSSet *> *)findRetainCyclesWithMaxCycleLength:(NSUInteger)length; - -/** - This macro is used across FBRetainCycleDetector to compile out sensitive code. - If you do not define it anywhere, Retain Cycle Detector will be available in DEBUG builds. - */ -#ifdef RETAIN_CYCLE_DETECTOR_ENABLED -#define _INTERNAL_RCD_ENABLED RETAIN_CYCLE_DETECTOR_ENABLED -#else -#define _INTERNAL_RCD_ENABLED DEBUG -#endif - -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBRetainCycleDetector.mm b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBRetainCycleDetector.mm deleted file mode 100644 index b3409434..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBRetainCycleDetector.mm +++ /dev/null @@ -1,294 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import -#import -#import - -#import "FBNodeEnumerator.h" -#import "FBObjectiveCGraphElement.h" -#import "FBObjectiveCObject.h" -#import "FBRetainCycleDetector+Internal.h" -#import "FBRetainCycleUtils.h" -#import "FBStandardGraphEdgeFilters.h" - -static const NSUInteger kFBRetainCycleDetectorDefaultStackDepth = 10; - -@implementation FBRetainCycleDetector -{ - NSMutableArray *_candidates; - FBObjectGraphConfiguration *_configuration; - NSMutableSet *_objectSet; -} - -- (instancetype)initWithConfiguration:(FBObjectGraphConfiguration *)configuration -{ - if (self = [super init]) { - _configuration = configuration; - _candidates = [NSMutableArray new]; - _objectSet = [NSMutableSet new]; - } - - return self; -} - -- (instancetype)init -{ - return [self initWithConfiguration: - [[FBObjectGraphConfiguration alloc] initWithFilterBlocks:FBGetStandardGraphEdgeFilters() - shouldInspectTimers:YES]]; -} - -- (void)addCandidate:(id)candidate -{ - FBObjectiveCGraphElement *graphElement = FBWrapObjectGraphElement(nil, candidate, _configuration); - if (graphElement) { - [_candidates addObject:graphElement]; - } -} - -- (NSSet *> *)findRetainCycles -{ - return [self findRetainCyclesWithMaxCycleLength:kFBRetainCycleDetectorDefaultStackDepth]; -} - -- (NSSet *> *)findRetainCyclesWithMaxCycleLength:(NSUInteger)length -{ - NSMutableSet *> *allRetainCycles = [NSMutableSet new]; - for (FBObjectiveCGraphElement *graphElement in _candidates) { - NSSet *> *retainCycles = [self _findRetainCyclesInObject:graphElement - stackDepth:length]; - [allRetainCycles unionSet:retainCycles]; - } - [_candidates removeAllObjects]; - [_objectSet removeAllObjects]; - - // Filter cycles that have been broken down since we found them. - // These are false-positive that were picked-up and are transient cycles. - NSMutableSet *> *brokenCycles = [NSMutableSet set]; - for (NSArray *itemCycle in allRetainCycles) { - for (FBObjectiveCGraphElement *element in itemCycle) { - if (element.object == nil) { - // At least one element of the cycle has been removed, thus breaking - // the cycle. - [brokenCycles addObject:itemCycle]; - break; - } - } - } - [allRetainCycles minusSet:brokenCycles]; - - return allRetainCycles; -} - -- (NSSet *> *)_findRetainCyclesInObject:(FBObjectiveCGraphElement *)graphElement - stackDepth:(NSUInteger)stackDepth -{ - NSMutableSet *> *retainCycles = [NSMutableSet new]; - FBNodeEnumerator *wrappedObject = [[FBNodeEnumerator alloc] initWithObject:graphElement]; - - // We will be doing DFS over graph of objects - - // Stack will keep current path in the graph - NSMutableArray *stack = [NSMutableArray new]; - - // To make the search non-linear we will also keep - // a set of previously visited nodes. - NSMutableSet *objectsOnPath = [NSMutableSet new]; - - // Let's start with the root - [stack addObject:wrappedObject]; - - while ([stack count] > 0) { - // Algorithm creates many short-living objects. It can contribute to few - // hundred megabytes memory jumps if not handled correctly, therefore - // we're gonna drain the objects with our autoreleasepool. - @autoreleasepool { - // Take topmost node in stack and mark it as visited - FBNodeEnumerator *top = [stack lastObject]; - - // We don't want to retraverse the same subtree - if (![objectsOnPath containsObject:top]) { - if ([_objectSet containsObject:@([top.object objectAddress])]) { - [stack removeLastObject]; - continue; - } - // Add the object address to the set as an NSNumber to avoid - // unnecessarily retaining the object - [_objectSet addObject:@([top.object objectAddress])]; - } - - [objectsOnPath addObject:top]; - - // Take next adjecent node to that child. Wrapper object can - // persist iteration state. If we see that node again, it will - // give us new adjacent node unless it runs out of them - FBNodeEnumerator *firstAdjacent = [top nextObject]; - if (firstAdjacent) { - // Current node still has some adjacent not-visited nodes - - BOOL shouldPushToStack = NO; - - // Check if child was already seen in that path - if ([objectsOnPath containsObject:firstAdjacent]) { - // We have caught a retain cycle - - // Ignore the first element which is equal to firstAdjacent, use firstAdjacent - // we're doing that because firstAdjacent has set all contexts, while its - // first occurence could be a root without any context - NSUInteger index = [stack indexOfObject:firstAdjacent]; - NSInteger length = [stack count] - index; - - if (index == NSNotFound) { - // Object got deallocated between checking if it exists and grabbing its index - shouldPushToStack = YES; - } else { - NSRange cycleRange = NSMakeRange(index, length); - NSMutableArray *cycle = [[stack subarrayWithRange:cycleRange] mutableCopy]; - [cycle replaceObjectAtIndex:0 withObject:firstAdjacent]; - - // 1. Unwrap the cycle - // 2. Shift to lowest address (if we omit that, and the cycle is created by same class, - // we might have duplicates) - // 3. Shift by class (lexicographically) - - [retainCycles addObject:[self _shiftToUnifiedCycle:[self _unwrapCycle:cycle]]]; - } - } else { - // Node is clear to check, add it to stack and continue - shouldPushToStack = YES; - } - - if (shouldPushToStack) { - if ([stack count] < stackDepth) { - [stack addObject:firstAdjacent]; - } - } - } else { - // Node has no more adjacent nodes, it itself is done, move on - [stack removeLastObject]; - [objectsOnPath removeObject:top]; - } - } - } - return retainCycles; -} - -// Turn all enumerators into object graph elements -- (NSArray *)_unwrapCycle:(NSArray *)cycle -{ - NSMutableArray *unwrappedArray = [NSMutableArray new]; - for (FBNodeEnumerator *wrapped in cycle) { - [unwrappedArray addObject:wrapped.object]; - } - - return unwrappedArray; -} - -// We do that so two cycles can be recognized as duplicates -- (NSArray *)_shiftToUnifiedCycle:(NSArray *)array -{ - return [self _shiftToLowestLexicographically:[self _shiftBufferToLowestAddress:array]]; -} - -- (NSArray *)_extractClassNamesFromGraphObjects:(NSArray *)array -{ - NSMutableArray *arrayOfClassNames = [NSMutableArray new]; - - for (FBObjectiveCGraphElement *obj in array) { - [arrayOfClassNames addObject:[obj classNameOrNull]]; - } - - return arrayOfClassNames; -} - -/** - The problem this circular shift solves is when we have few retain cycles for different runs that - are technically the same cycle shifted. Object instances are different so if objects A and B - create cycle, but on one run the address of A is lower than B, and on second B is lower than A, - we will get a duplicate we have to get rid off. - - For that not to happen we use the circular shift that is smallest lexicographically when - looking at class names. - - The version of this algorithm is pretty inefficient. It just compares given shifts and - tries to find the smallest one. Doing something faster here is premature optimisation though - since the retain cycles are usually arrays of length not bigger than 10 and there is not a lot - of them (like 100 per run tops). - - If that ever occurs to be a problem for future reference use lexicographically minimal - string rotation algorithm variation. - */ -- (NSArray *)_shiftToLowestLexicographically:(NSArray *)array -{ - NSArray *arrayOfClassNames = [self _extractClassNamesFromGraphObjects:array]; - - NSArray *copiedArray = [arrayOfClassNames arrayByAddingObjectsFromArray:arrayOfClassNames]; - NSUInteger originalLength = [arrayOfClassNames count]; - - NSArray *currentMinimalArray = arrayOfClassNames; - NSUInteger minimumIndex = 0; - - for (NSUInteger i = 0; i < originalLength; ++i) { - NSArray *nextSubarray = [copiedArray subarrayWithRange:NSMakeRange(i, originalLength)]; - if ([self _compareStringArray:currentMinimalArray - withArray:nextSubarray] == NSOrderedDescending) { - currentMinimalArray = nextSubarray; - minimumIndex = i; - } - } - - NSRange minimumArrayRange = NSMakeRange(minimumIndex, - [array count] - minimumIndex); - NSMutableArray *minimumArray = [[array subarrayWithRange:minimumArrayRange] mutableCopy]; - [minimumArray addObjectsFromArray:[array subarrayWithRange:NSMakeRange(0, minimumIndex)]]; - return minimumArray; -} - -- (NSComparisonResult)_compareStringArray:(NSArray *)a1 - withArray:(NSArray *)a2 -{ - // a1 and a2 should be the same length - for (NSUInteger i = 0; i < [a1 count]; ++i) { - NSString *s1 = a1[i]; - NSString *s2 = a2[i]; - - NSComparisonResult comparision = [s1 compare:s2]; - if (comparision != NSOrderedSame) { - return comparision; - } - } - - return NSOrderedSame; -} - -- (NSArray *)_shiftBufferToLowestAddress:(NSArray *)cycle -{ - NSUInteger idx = 0, lowestAddressIndex = 0; - size_t lowestAddress = NSUIntegerMax; - for (FBObjectiveCGraphElement *obj in cycle) { - if ([obj objectAddress] < lowestAddress) { - lowestAddress = [obj objectAddress]; - lowestAddressIndex = idx; - } - - idx++; - } - - if (lowestAddressIndex == 0) { - return cycle; - } - - NSRange cycleRange = NSMakeRange(lowestAddressIndex, [cycle count] - lowestAddressIndex); - NSMutableArray *array = [[cycle subarrayWithRange:cycleRange] mutableCopy]; - [array addObjectsFromArray:[cycle subarrayWithRange:NSMakeRange(0, lowestAddressIndex)]]; - return array; -} - -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/FBRetainCycleUtils.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/FBRetainCycleUtils.h deleted file mode 100644 index 763a7b25..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/FBRetainCycleUtils.h +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -@class FBObjectGraphConfiguration; -@class FBObjectiveCGraphElement; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - Wrapper functions, for given object they will categorize it and create proper Graph Element subclass instance - for it. - */ -FBObjectiveCGraphElement *_Nullable FBWrapObjectGraphElementWithContext(FBObjectiveCGraphElement *_Nullable sourceElement, - id _Nullable object, - FBObjectGraphConfiguration *_Nullable configuration, - NSArray *_Nullable namePath); -FBObjectiveCGraphElement *_Nullable FBWrapObjectGraphElement(FBObjectiveCGraphElement *_Nullable sourceElement, - id _Nullable object, - FBObjectGraphConfiguration *_Nullable configuration); - -#ifdef __cplusplus -} -#endif diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/FBRetainCycleUtils.m b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/FBRetainCycleUtils.m deleted file mode 100644 index 959a1532..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/FBRetainCycleUtils.m +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "FBRetainCycleUtils.h" - -#import - -#import "FBBlockStrongLayout.h" -#import "FBClassStrongLayout.h" -#import "FBObjectiveCBlock.h" -#import "FBObjectiveCGraphElement.h" -#import "FBObjectiveCNSCFTimer.h" -#import "FBObjectiveCObject.h" -#import "FBObjectGraphConfiguration.h" - -static BOOL _ShouldBreakGraphEdge(FBObjectGraphConfiguration *configuration, - FBObjectiveCGraphElement *fromObject, - NSString *byIvar, - Class toObjectOfClass) { - for (FBGraphEdgeFilterBlock filterBlock in configuration.filterBlocks) { - if (filterBlock(fromObject, byIvar, toObjectOfClass) == FBGraphEdgeInvalid) { - return YES; - } - } - - return NO; -} - -FBObjectiveCGraphElement *FBWrapObjectGraphElementWithContext(FBObjectiveCGraphElement *sourceElement, - id object, - FBObjectGraphConfiguration *configuration, - NSArray *namePath) { - if (_ShouldBreakGraphEdge(configuration, sourceElement, [namePath firstObject], object_getClass(object))) { - return nil; - } - FBObjectiveCGraphElement *newElement; - if (FBObjectIsBlock((__bridge void *)object)) { - newElement = [[FBObjectiveCBlock alloc] initWithObject:object - configuration:configuration - namePath:namePath]; - } else { - if ([object_getClass(object) isSubclassOfClass:[NSTimer class]] && - configuration.shouldInspectTimers) { - newElement = [[FBObjectiveCNSCFTimer alloc] initWithObject:object - configuration:configuration - namePath:namePath]; - } else { - newElement = [[FBObjectiveCObject alloc] initWithObject:object - configuration:configuration - namePath:namePath]; - } - } - return (configuration && configuration.transformerBlock) ? configuration.transformerBlock(newElement) : newElement; -} - -FBObjectiveCGraphElement *FBWrapObjectGraphElement(FBObjectiveCGraphElement *sourceElement, - id object, - FBObjectGraphConfiguration *configuration) { - return FBWrapObjectGraphElementWithContext(sourceElement, object, configuration, nil); -} diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Filtering/FBStandardGraphEdgeFilters.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Filtering/FBStandardGraphEdgeFilters.h deleted file mode 100644 index 3773466e..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Filtering/FBStandardGraphEdgeFilters.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#import "FBObjectGraphConfiguration.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - Standard filters mostly filters excluding some UIKit references we have caught during testing on some apps. - */ -NSArray *_Nonnull FBGetStandardGraphEdgeFilters(); - -/** - Helper functions for some typical patterns. - */ -FBGraphEdgeFilterBlock _Nonnull FBFilterBlockWithObjectIvarRelation(Class _Nonnull aCls, - NSString *_Nonnull ivarName); -FBGraphEdgeFilterBlock _Nonnull FBFilterBlockWithObjectToManyIvarsRelation(Class _Nonnull aCls, - NSSet *_Nonnull ivarNames); -FBGraphEdgeFilterBlock _Nonnull FBFilterBlockWithObjectIvarObjectRelation(Class _Nonnull fromClass, - NSString *_Nonnull ivarName, - Class _Nonnull toClass); - -#ifdef __cplusplus -} -#endif diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Filtering/FBStandardGraphEdgeFilters.mm b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Filtering/FBStandardGraphEdgeFilters.mm deleted file mode 100644 index 0a88d907..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Filtering/FBStandardGraphEdgeFilters.mm +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "FBStandardGraphEdgeFilters.h" - -#import - -#import - -#import "FBObjectiveCGraphElement.h" -#import "FBRetainCycleDetector.h" - -FBGraphEdgeFilterBlock FBFilterBlockWithObjectIvarRelation(Class aCls, NSString *ivarName) { - return FBFilterBlockWithObjectToManyIvarsRelation(aCls, [NSSet setWithObject:ivarName]); -} - -FBGraphEdgeFilterBlock FBFilterBlockWithObjectToManyIvarsRelation(Class aCls, - NSSet *ivarNames) { - return ^(FBObjectiveCGraphElement *fromObject, - NSString *byIvar, - Class toObjectOfClass){ - if (aCls && - [[fromObject objectClass] isSubclassOfClass:aCls]) { - // If graph element holds metadata about an ivar, it will be held in the name path, as early as possible - if ([ivarNames containsObject:byIvar]) { - return FBGraphEdgeInvalid; - } - } - return FBGraphEdgeValid; - }; -} - -FBGraphEdgeFilterBlock FBFilterBlockWithObjectIvarObjectRelation(Class fromClass, NSString *ivarName, Class toClass) { - return ^(FBObjectiveCGraphElement *fromObject, - NSString *byIvar, - Class toObjectOfClass) { - if (toClass && - [toObjectOfClass isSubclassOfClass:toClass]) { - return FBFilterBlockWithObjectIvarRelation(fromClass, ivarName)(fromObject, byIvar, toObjectOfClass); - } - return FBGraphEdgeValid; - }; -} - -NSArray *FBGetStandardGraphEdgeFilters() { -#if _INTERNAL_RCD_ENABLED - static Class heldActionClass; - static Class transitionContextClass; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - heldActionClass = NSClassFromString(@"UIHeldAction"); - transitionContextClass = NSClassFromString(@"_UIViewControllerOneToOneTransitionContext"); - }); - - return @[FBFilterBlockWithObjectIvarRelation([UIView class], @"_subviewCache"), - FBFilterBlockWithObjectIvarRelation(heldActionClass, @"m_target"), - FBFilterBlockWithObjectToManyIvarsRelation([UITouch class], - [NSSet setWithArray:@[@"_view", - @"_gestureRecognizers", - @"_window", - @"_warpedIntoView"]]), - FBFilterBlockWithObjectToManyIvarsRelation(transitionContextClass, - [NSSet setWithArray:@[@"_toViewController", - @"_fromViewController"]])]; -#else - return nil; -#endif // _INTERNAL_RCD_ENABLED -} diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectGraphConfiguration.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectGraphConfiguration.h deleted file mode 100644 index 55eb87e8..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectGraphConfiguration.h +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#import "FBObjectiveCGraphElement.h" - -typedef NS_ENUM(NSUInteger, FBGraphEdgeType) { - FBGraphEdgeValid, - FBGraphEdgeInvalid, -}; - -@protocol FBObjectReference; - -/** - Every filter has to be of type FBGraphEdgeFilterBlock. Filter, given two object graph elements, it should decide, - whether a reference between them should be filtered out or not. - @see FBGetStandardGraphEdgeFilters() - */ -typedef FBGraphEdgeType (^FBGraphEdgeFilterBlock)(FBObjectiveCGraphElement *_Nullable fromObject, - NSString *_Nullable byIvar, - Class _Nullable toObjectOfClass); - -typedef FBObjectiveCGraphElement *_Nullable(^FBObjectiveCGraphElementTransformerBlock)(FBObjectiveCGraphElement *_Nonnull fromObject); - -/** - FBObjectGraphConfiguration represents a configuration for object graph walking. - It can hold filters and detector specific options. - */ -@interface FBObjectGraphConfiguration : NSObject - -/** - Every block represents a filter that every reference must pass in order to be inspected. - Reference will be described as relation from one object to another object. See definition of - FBGraphEdgeFilterBlock above. - - Invalid relations would be the relations that we are guaranteed are going to be broken at some point. - Be careful though, it's not so straightforward to tell if the relation will be broken *with 100% - certainty*, and if you'll filter out something that could otherwise show retain cycle that leaks - - it would never be caught by detector. - - For examples of what are the relations that will be broken at some point check FBStandardGraphEdgeFilters.mm - */ -@property (nonatomic, readonly, copy, nullable) NSArray *filterBlocks; - -@property (nonatomic, readonly, copy, nullable) FBObjectiveCGraphElementTransformerBlock transformerBlock; - -/** - Decides if object graph walker should look for retain cycles inside NSTimers. - */ -@property (nonatomic, readonly) BOOL shouldInspectTimers; - -/** - Decides if block objects should include their invocation address (the code part of the block) in the report. - If set to YES, then it will change from: `MallocBlock` to `<>`. - You can then symbolicate the address to retrieve a symbol name which will look like: - `__FOO_block_invoke` where FOO is replaced by the function creating the block. - This will allow easier understanding of the code involved in the cycle when blocks are involved. - */ -@property (nonatomic, readonly) BOOL shouldIncludeBlockAddress; - -/** - Will cache layout - */ -@property (nonatomic, readonly, nullable) NSMutableDictionary> *> *layoutCache; -@property (nonatomic, readonly) BOOL shouldCacheLayouts; - -- (nonnull instancetype)initWithFilterBlocks:(nonnull NSArray *)filterBlocks - shouldInspectTimers:(BOOL)shouldInspectTimers - transformerBlock:(nullable FBObjectiveCGraphElementTransformerBlock)transformerBlock - shouldIncludeBlockAddress:(BOOL)shouldIncludeBlockAddress NS_DESIGNATED_INITIALIZER; - -- (nonnull instancetype)initWithFilterBlocks:(nonnull NSArray *)filterBlocks - shouldInspectTimers:(BOOL)shouldInspectTimers - transformerBlock:(nullable FBObjectiveCGraphElementTransformerBlock)transformerBlock; - -- (nonnull instancetype)initWithFilterBlocks:(nonnull NSArray *)filterBlocks - shouldInspectTimers:(BOOL)shouldInspectTimers; - -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectGraphConfiguration.m b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectGraphConfiguration.m deleted file mode 100644 index 825c73d1..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectGraphConfiguration.m +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "FBObjectGraphConfiguration.h" - -@implementation FBObjectGraphConfiguration - -- (instancetype)initWithFilterBlocks:(NSArray *)filterBlocks - shouldInspectTimers:(BOOL)shouldInspectTimers - transformerBlock:(nullable FBObjectiveCGraphElementTransformerBlock)transformerBlock - shouldIncludeBlockAddress:(BOOL)shouldIncludeBlockAddress -{ - if (self = [super init]) { - _filterBlocks = [filterBlocks copy]; - _shouldInspectTimers = shouldInspectTimers; - _shouldIncludeBlockAddress = shouldIncludeBlockAddress; - _transformerBlock = [transformerBlock copy]; - _layoutCache = [NSMutableDictionary new]; - } - - return self; -} - -- (instancetype)initWithFilterBlocks:(NSArray *)filterBlocks - shouldInspectTimers:(BOOL)shouldInspectTimers - transformerBlock:(nullable FBObjectiveCGraphElementTransformerBlock)transformerBlock -{ - return [self initWithFilterBlocks:filterBlocks - shouldInspectTimers:shouldInspectTimers - transformerBlock:transformerBlock - shouldIncludeBlockAddress:NO]; -} - -- (instancetype)initWithFilterBlocks:(NSArray *)filterBlocks - shouldInspectTimers:(BOOL)shouldInspectTimers -{ - return [self initWithFilterBlocks:filterBlocks - shouldInspectTimers:shouldInspectTimers - transformerBlock:nil]; -} - -- (instancetype)init -{ - // By default we are inspecting timers - return [self initWithFilterBlocks:@[] - shouldInspectTimers:YES]; -} - -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCBlock.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCBlock.h deleted file mode 100644 index 6131a39a..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCBlock.h +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#import "FBObjectiveCGraphElement.h" - -@class FBGraphEdgeFilterProvider; - -/** - Object Graph element representing block. - */ -@interface FBObjectiveCBlock : FBObjectiveCGraphElement -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCBlock.m b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCBlock.m deleted file mode 100644 index 7097999b..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCBlock.m +++ /dev/null @@ -1,100 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "FBObjectiveCBlock.h" - -#import - -#import "FBBlockStrongLayout.h" -#import "FBBlockStrongRelationDetector.h" -#import "FBObjectGraphConfiguration.h" -#import "FBObjectiveCObject.h" -#import "FBRetainCycleUtils.h" - -struct __attribute__((packed)) BlockLiteral { - void *isa; - int flags; - int reserved; - void *invoke; - void *descriptor; -}; - -@implementation FBObjectiveCBlock - -- (NSSet *)allRetainedObjects -{ - NSMutableArray *results = [[[super allRetainedObjects] allObjects] mutableCopy]; - - // Grab a strong reference to the object, otherwise it can crash while doing - // nasty stuff on deallocation - __attribute__((objc_precise_lifetime)) id anObject = self.object; - - void *blockObjectReference = (__bridge void *)anObject; - NSArray *allRetainedReferences = FBGetBlockStrongReferences(blockObjectReference); - - for (id object in allRetainedReferences) { - FBObjectiveCGraphElement *element = FBWrapObjectGraphElement(self, object, self.configuration); - if (element) { - [results addObject:element]; - } - } - - return [NSSet setWithArray:results]; -} - -/** - * We want to add more information to blocks because they show up - * in reports as MallocBlock and StackBlock which is not very informative. - * - * A block object is composed of: - * - code: what should be executed, it's stored in the .TEXT section ; - * - data: the variables that have been captured ; - * - metadata: notably the function signature. - * - * We extract the address of the code, which can then be converted to a - * human readable name given the debug symbol file. - * - * The symbol name contains the name of the function which allocated - * the block, making is easier to track the piece of code participating - * in the cycle. The symbolication must be done outside of this code - * since it will require access to the debug symbols, not present at - * runtime. - * - * Format: <> - */ -- (NSString *)classNameOrNull -{ - NSString *className = NSStringFromClass([self objectClass]); - if (!className) { - className = @"(null)"; - } - - if (!self.configuration.shouldIncludeBlockAddress) { - return className; - } - - // Find the reference of the block object. - __attribute__((objc_precise_lifetime)) id anObject = self.object; - if ([anObject isKindOfClass:[FBBlockStrongRelationDetector class]]) { - FBBlockStrongRelationDetector *blockObject = anObject; - anObject = [blockObject forwarding]; - } - void *blockObjectReference = (__bridge void *)anObject; - if (!blockObjectReference) { - return className; - } - - // Extract the invocated block of code from the structure. - const struct BlockLiteral *block = (struct BlockLiteral*) blockObjectReference; - const void *blockCodePtr = block->invoke; - - return [NSString stringWithFormat:@"<<%@:0x%llx>>", className, (unsigned long long)blockCodePtr]; -} - -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCGraphElement.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCGraphElement.h deleted file mode 100644 index 38d0f12f..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCGraphElement.h +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -@class FBObjectGraphConfiguration; - -/** - Base Graph Element representation. It carries some data about the object and should be overridden in subclass - to provide references that subclass holds strongly (different for blocks, objects, other specializations). - The Graph Element itself can only provide references from FBAssociationManager. - */ -@interface FBObjectiveCGraphElement : NSObject - -/** - Designated initializer. - @param object Object this Graph Element will represent. - @param configuration Provides detector's configuration that contains filters and options - @param filterProvider Filter Provider that Graph Element will use to determine which references need to be dropped - @param namePath Description of how the object was retrieved from it's parent. Check namePath property. - */ -- (nonnull instancetype)initWithObject:(nullable id)object - configuration:(nonnull FBObjectGraphConfiguration *)configuration - namePath:(nullable NSArray *)namePath; - -- (nonnull instancetype)initWithObject:(nullable id)object - configuration:(nonnull FBObjectGraphConfiguration *)configuration; - - -/** - Name path that describes how this object was retrieved from its parent object by names - (for example ivar names, struct references). For more check FBObjectReference protocol. - */ -@property (nonatomic, copy, readonly, nullable) NSArray *namePath; -@property (nonatomic, weak, nullable) id object; -@property (nonatomic, readonly, nonnull) FBObjectGraphConfiguration *configuration; - -/** - Main accessor to all objects that the given object is retaining. Thread unsafe. - - @return NSSet of all objects this object is retaining. - */ -- (nullable NSSet *)allRetainedObjects; - -/** - @return address of the object represented by this element - */ -- (size_t)objectAddress; - -- (nullable Class)objectClass; -- (nonnull NSString *)classNameOrNull; - -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCGraphElement.mm b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCGraphElement.mm deleted file mode 100644 index c9015abe..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCGraphElement.mm +++ /dev/null @@ -1,130 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "FBObjectiveCGraphElement+Internal.h" - -#import -#import - -#import "FBAssociationManager.h" -#import "FBClassStrongLayout.h" -#import "FBObjectGraphConfiguration.h" -#import "FBRetainCycleUtils.h" -#import "FBRetainCycleDetector.h" - -@implementation FBObjectiveCGraphElement - -- (instancetype)initWithObject:(id)object -{ - return [self initWithObject:object - configuration:[FBObjectGraphConfiguration new]]; -} - -- (instancetype)initWithObject:(id)object - configuration:(nonnull FBObjectGraphConfiguration *)configuration -{ - return [self initWithObject:object - configuration:configuration - namePath:nil]; -} - -- (instancetype)initWithObject:(id)object - configuration:(nonnull FBObjectGraphConfiguration *)configuration - namePath:(NSArray *)namePath -{ - if (self = [super init]) { -#if _INTERNAL_RCD_ENABLED - // We are trying to mimic how ObjectiveC does storeWeak to not fall into - // _objc_fatal path - // https://github.com/bavarious/objc4/blob/3f282b8dbc0d1e501f97e4ed547a4a99cb3ac10b/runtime/objc-weak.mm#L369 - - Class aCls = object_getClass(object); - - BOOL (*allowsWeakReference)(id, SEL) = - (__typeof__(allowsWeakReference))class_getMethodImplementation(aCls, @selector(allowsWeakReference)); - - if (allowsWeakReference && (IMP)allowsWeakReference != _objc_msgForward) { - if (allowsWeakReference(object, @selector(allowsWeakReference))) { - // This is still racey since allowsWeakReference could change it value by now. - _object = object; - } - } else { - _object = object; - } -#endif - _namePath = namePath; - _configuration = configuration; - } - - return self; -} - -- (NSSet *)allRetainedObjects -{ - NSArray *retainedObjectsNotWrapped = [FBAssociationManager associationsForObject:_object]; - NSMutableSet *retainedObjects = [NSMutableSet new]; - - for (id obj in retainedObjectsNotWrapped) { - FBObjectiveCGraphElement *element = FBWrapObjectGraphElementWithContext(self, - obj, - _configuration, - @[@"__associated_object"]); - if (element) { - [retainedObjects addObject:element]; - } - } - - return retainedObjects; -} - -- (BOOL)isEqual:(id)object -{ - if ([object isKindOfClass:[FBObjectiveCGraphElement class]]) { - FBObjectiveCGraphElement *objcObject = object; - // Use pointer equality - return objcObject.object == _object; - } - return NO; -} - -- (NSUInteger)hash -{ - return (size_t)_object; -} - -- (NSString *)description -{ - if (_namePath) { - NSString *namePathStringified = [_namePath componentsJoinedByString:@" -> "]; - return [NSString stringWithFormat:@"-> %@ -> %@ ", namePathStringified, [self classNameOrNull]]; - } - return [NSString stringWithFormat:@"-> %@ ", [self classNameOrNull]]; -} - -- (size_t)objectAddress -{ - return (size_t)_object; -} - -- (NSString *)classNameOrNull -{ - NSString *className = NSStringFromClass([self objectClass]); - if (!className) { - className = @"(null)"; - } - - return className; -} - -- (Class)objectClass -{ - return object_getClass(_object); -} - -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCObject.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCObject.h deleted file mode 100644 index 71e67ef8..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCObject.h +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#import "FBObjectiveCGraphElement.h" - -@class FBGraphEdgeFilterProvider; - -/** - FBObjectiveCGraphElement specialization that can gather all references kept in ivars, as part of collection - etc. - */ -@interface FBObjectiveCObject : FBObjectiveCGraphElement -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCObject.m b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCObject.m deleted file mode 100644 index a2694013..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCObject.m +++ /dev/null @@ -1,147 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "FBObjectiveCObject.h" - -#import - -#import "FBClassStrongLayout.h" -#import "FBObjectGraphConfiguration.h" -#import "FBObjectReference.h" -#import "FBRetainCycleUtils.h" - -@implementation FBObjectiveCObject - -- (NSSet *)allRetainedObjects -{ - Class aCls = object_getClass(self.object); - if (!self.object || !aCls) { - return nil; - } - - NSArray *strongIvars = FBGetObjectStrongReferences(self.object, self.configuration.layoutCache); - - NSMutableArray *retainedObjects = [[[super allRetainedObjects] allObjects] mutableCopy]; - - for (id ref in strongIvars) { - id referencedObject = [ref objectReferenceFromObject:self.object]; - - if (referencedObject) { - NSArray *namePath = [ref namePath]; - FBObjectiveCGraphElement *element = FBWrapObjectGraphElementWithContext(self, - referencedObject, - self.configuration, - namePath); - if (element) { - [retainedObjects addObject:element]; - } - } - } - - if ([NSStringFromClass(aCls) hasPrefix:@"__NSCF"]) { - /** - If we are dealing with toll-free bridged collections, we are not guaranteed that the collection - will hold only Objective-C objects. We are not able to check in runtime what callbacks it uses to - retain/release (if any) and we could easily crash here. - */ - return [NSSet setWithArray:retainedObjects]; - } - - if (class_isMetaClass(aCls)) { - // If it's a meta-class it can conform to following protocols, - // but it would crash when trying enumerating - return nil; - } - - if ([aCls conformsToProtocol:@protocol(NSFastEnumeration)]) { - BOOL retainsKeys = [self _objectRetainsEnumerableKeys]; - BOOL retainsValues = [self _objectRetainsEnumerableValues]; - - BOOL isKeyValued = NO; - if ([aCls instancesRespondToSelector:@selector(objectForKey:)]) { - isKeyValued = YES; - } - - /** - This codepath is prone to errors. When you enumerate a collection that can be mutated while enumeration - we fall into risk of crash. To save ourselves from that we will catch such exception and try again. - We should not try this endlessly, so at some point we will simply give up. - */ - NSInteger tries = 10; - for (NSInteger i = 0; i < tries; ++i) { - // If collection is mutated we want to rollback and try again - let's keep refs in temporary set - NSMutableSet *temporaryRetainedObjects = [NSMutableSet new]; - @try { - for (id subobject in self.object) { - if (retainsKeys) { - FBObjectiveCGraphElement *element = FBWrapObjectGraphElement(self, subobject, self.configuration); - if (element) { - [temporaryRetainedObjects addObject:element]; - } - } - if (isKeyValued && retainsValues) { - FBObjectiveCGraphElement *element = FBWrapObjectGraphElement(self, - [self.object objectForKey:subobject], - self.configuration); - if (element) { - [temporaryRetainedObjects addObject:element]; - } - } - } - } - @catch (NSException *exception) { - // mutation happened, we want to try enumerating again - continue; - } - - // If we are here it means no exception happened and we want to break outer loop - [retainedObjects addObjectsFromArray:[temporaryRetainedObjects allObjects]]; - break; - } - } - - return [NSSet setWithArray:retainedObjects]; -} - -- (BOOL)_objectRetainsEnumerableValues -{ - if ([self.object respondsToSelector:@selector(valuePointerFunctions)]) { - NSPointerFunctions *pointerFunctions = [self.object valuePointerFunctions]; - if (pointerFunctions.usesWeakReadAndWriteBarriers) { - return NO; - } - } - - return YES; -} - -- (BOOL)_objectRetainsEnumerableKeys -{ - if ([self.object respondsToSelector:@selector(pointerFunctions)]) { - // NSHashTable and similar - // If object shows what pointer functions are used, lets try to determine - // if it's not retaining objects - NSPointerFunctions *pointerFunctions = [self.object pointerFunctions]; - if (pointerFunctions.usesWeakReadAndWriteBarriers) { - // It's weak - we should not touch it - return NO; - } - } - - if ([self.object respondsToSelector:@selector(keyPointerFunctions)]) { - NSPointerFunctions *pointerFunctions = [self.object keyPointerFunctions]; - if (pointerFunctions.usesWeakReadAndWriteBarriers) { - return NO; - } - } - - return YES; -} - -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/Internal/FBObjectiveCGraphElement+Internal.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/Internal/FBObjectiveCGraphElement+Internal.h deleted file mode 100644 index e181842b..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/Internal/FBObjectiveCGraphElement+Internal.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#import "FBObjectiveCGraphElement.h" - -@interface FBObjectiveCGraphElement () - -- (instancetype)initWithObject:(id)object; - -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/Specialization/FBObjectiveCNSCFTimer.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/Specialization/FBObjectiveCNSCFTimer.h deleted file mode 100644 index cb3a3e56..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/Specialization/FBObjectiveCNSCFTimer.h +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#import "FBObjectiveCObject.h" - -/** - Specialization of FBObjectiveCObject for NSTimer. - Standard methods that FBObjectiveCObject uses will not fetch us all objects retained by NSTimer. - One good example is target of NSTimer. - */ -@interface FBObjectiveCNSCFTimer : FBObjectiveCObject -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/Specialization/FBObjectiveCNSCFTimer.mm b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/Specialization/FBObjectiveCNSCFTimer.mm deleted file mode 100644 index 7a21f30b..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/Specialization/FBObjectiveCNSCFTimer.mm +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "FBObjectiveCNSCFTimer.h" - -#import - -#import "FBRetainCycleDetector.h" -#import "FBRetainCycleUtils.h" - -@implementation FBObjectiveCNSCFTimer - -#if _INTERNAL_RCD_ENABLED - -typedef struct { - long _unknown; // This is always 1 - id target; - SEL selector; - NSDictionary *userInfo; -} _FBNSCFTimerInfoStruct; - -- (NSSet *)allRetainedObjects -{ - // Let's retain our timer - __attribute__((objc_precise_lifetime)) NSTimer *timer = self.object; - - if (!timer) { - return nil; - } - - NSMutableSet *retained = [[super allRetainedObjects] mutableCopy]; - - CFRunLoopTimerContext context; - CFRunLoopTimerGetContext((CFRunLoopTimerRef)timer, &context); - - // If it has a retain function, let's assume it retains strongly - if (context.info && context.retain) { - _FBNSCFTimerInfoStruct infoStruct = *(_FBNSCFTimerInfoStruct *)(context.info); - if (infoStruct.target) { - FBObjectiveCGraphElement *element = FBWrapObjectGraphElementWithContext(self, infoStruct.target, self.configuration, @[@"target"]); - if (element) { - [retained addObject:element]; - } - } - if (infoStruct.userInfo) { - FBObjectiveCGraphElement *element = FBWrapObjectGraphElementWithContext(self, infoStruct.userInfo, self.configuration, @[@"userInfo"]); - if (element) { - [retained addObject:element]; - } - } - } - - return retained; -} - -#endif // _INTERNAL_RCD_ENABLED - -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockInterface.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockInterface.h deleted file mode 100644 index 3ae1ba9f..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockInterface.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -/** - We are mimicing Block structure based on Clang documentation: - http://clang.llvm.org/docs/Block-ABI-Apple.html - */ - -enum { // Flags from BlockLiteral - BLOCK_HAS_COPY_DISPOSE = (1 << 25), - BLOCK_HAS_CTOR = (1 << 26), // helpers have C++ code - BLOCK_IS_GLOBAL = (1 << 28), - BLOCK_HAS_STRET = (1 << 29), // IFF BLOCK_HAS_SIGNATURE - BLOCK_HAS_SIGNATURE = (1 << 30), -}; - -struct BlockDescriptor { - unsigned long int reserved; // NULL - unsigned long int size; - // optional helper functions - void (*copy_helper)(void *dst, void *src); // IFF (1<<25) - void (*dispose_helper)(void *src); // IFF (1<<25) - const char *signature; // IFF (1<<30) -}; - -struct BlockLiteral { - void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock - int flags; - int reserved; - void (*invoke)(void *, ...); - struct BlockDescriptor *descriptor; - // imported variables -}; diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockStrongLayout.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockStrongLayout.h deleted file mode 100644 index bb084159..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockStrongLayout.h +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#ifdef __cplusplus -extern "C" { -#endif - -/** - Returns an array of id objects that will have only those references - that are retained by block. - */ -NSArray *_Nullable FBGetBlockStrongReferences(void *_Nonnull block); - -BOOL FBObjectIsBlock(void *_Nullable object); - -#ifdef __cplusplus -} -#endif diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockStrongLayout.m b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockStrongLayout.m deleted file mode 100644 index cc408efe..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockStrongLayout.m +++ /dev/null @@ -1,123 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#if __has_feature(objc_arc) -#error This file must be compiled with MRR. Use -fno-objc-arc flag. -#endif - -#import "FBBlockStrongLayout.h" - -#import - -#import "FBBlockInterface.h" -#import "FBBlockStrongRelationDetector.h" - -/** - We will be blackboxing variables that the block holds with our own custom class, - and we will check which of them were retained. - - The idea is based on the approach Circle uses: - https://github.com/mikeash/Circle - https://github.com/mikeash/Circle/blob/master/Circle/CircleIVarLayout.m - */ -static NSIndexSet *_GetBlockStrongLayout(void *block) { - struct BlockLiteral *blockLiteral = block; - - /** - BLOCK_HAS_CTOR - Block has a C++ constructor/destructor, which gives us a good chance it retains - objects that are not pointer aligned, so omit them. - - !BLOCK_HAS_COPY_DISPOSE - Block doesn't have a dispose function, so it does not retain objects and - we are not able to blackbox it. - */ - if ((blockLiteral->flags & BLOCK_HAS_CTOR) - || !(blockLiteral->flags & BLOCK_HAS_COPY_DISPOSE)) { - return nil; - } - - void (*dispose_helper)(void *src) = blockLiteral->descriptor->dispose_helper; - const size_t ptrSize = sizeof(void *); - - // Figure out the number of pointers it takes to fill out the object, rounding up. - const size_t elements = (blockLiteral->descriptor->size + ptrSize - 1) / ptrSize; - - // Create a fake object of the appropriate length. - void *obj[elements]; - void *detectors[elements]; - - for (size_t i = 0; i < elements; ++i) { - FBBlockStrongRelationDetector *detector = [FBBlockStrongRelationDetector new]; - obj[i] = detectors[i] = detector; - } - - @autoreleasepool { - dispose_helper(obj); - } - - // Run through the release detectors and add each one that got released to the object's - // strong ivar layout. - NSMutableIndexSet *layout = [NSMutableIndexSet indexSet]; - - for (size_t i = 0; i < elements; ++i) { - FBBlockStrongRelationDetector *detector = (FBBlockStrongRelationDetector *)(detectors[i]); - if (detector.isStrong) { - [layout addIndex:i]; - } - - // Destroy detectors - [detector trueRelease]; - } - - return layout; -} - -NSArray *FBGetBlockStrongReferences(void *block) { - if (!FBObjectIsBlock(block)) { - return nil; - } - - NSMutableArray *results = [NSMutableArray new]; - - void **blockReference = block; - NSIndexSet *strongLayout = _GetBlockStrongLayout(block); - [strongLayout enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { - void **reference = &blockReference[idx]; - - if (reference && (*reference)) { - id object = (id)(*reference); - - if (object) { - [results addObject:object]; - } - } - }]; - - return [results autorelease]; -} - -static Class _BlockClass() { - static dispatch_once_t onceToken; - static Class blockClass; - dispatch_once(&onceToken, ^{ - void (^testBlock)() = [^{} copy]; - blockClass = [testBlock class]; - while(class_getSuperclass(blockClass) && class_getSuperclass(blockClass) != [NSObject class]) { - blockClass = class_getSuperclass(blockClass); - } - [testBlock release]; - }); - return blockClass; -} - -BOOL FBObjectIsBlock(void *object) { - Class blockClass = _BlockClass(); - - Class candidate = object_getClass((__bridge id)object); - return [candidate isSubclassOfClass:blockClass]; -} diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockStrongRelationDetector.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockStrongRelationDetector.h deleted file mode 100644 index 8c706bdc..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockStrongRelationDetector.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -/** - We created a detector object that will fake *any* object that block can retain. - - Using clever trickery from Circle: - https://github.com/mikeash/Circle/blob/master/Circle/CircleIVarLayout.m - - We are also faking that this object can be treated as a block. - Otherwise if the block is retained by block, it will try to call byref_dispose and - our object won't be able to respond. - */ - -struct _block_byref_block; -@interface FBBlockStrongRelationDetector : NSObject -{ - // __block fakery - void *forwarding; - int flags; //refcount; - int size; - void (*byref_keep)(struct _block_byref_block *dst, struct _block_byref_block *src); - void (*byref_dispose)(struct _block_byref_block *); - void *captured[16]; -} - -@property (nonatomic, assign, getter=isStrong) BOOL strong; - -- (oneway void)trueRelease; - -- (void *)forwarding; - -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockStrongRelationDetector.m b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockStrongRelationDetector.m deleted file mode 100644 index 52b43c86..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockStrongRelationDetector.m +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#if __has_feature(objc_arc) -#error This file must be compiled with MRR. Use -fno-objc-arc flag. -#endif - -#import "FBBlockStrongRelationDetector.h" - -#import - -static void byref_keep_nop(struct _block_byref_block *dst, struct _block_byref_block *src) {} -static void byref_dispose_nop(struct _block_byref_block *param) {} - -@implementation FBBlockStrongRelationDetector - -- (oneway void)release -{ - _strong = YES; -} - -- (id)retain -{ - return self; -} - -+ (id)alloc -{ - FBBlockStrongRelationDetector *obj = [super alloc]; - - // Setting up block fakery - obj->forwarding = obj; - obj->byref_keep = byref_keep_nop; - obj->byref_dispose = byref_dispose_nop; - - return obj; -} - -- (oneway void)trueRelease -{ - [super release]; -} - -- (void *)forwarding -{ - return self->forwarding; -} - -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayout.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayout.h deleted file mode 100644 index 4ddaf810..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayout.h +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#ifdef __cplusplus -extern "C" { -#endif - -@protocol FBObjectReference; -/** - @return An array of id objects that will have *all* references - the object has (also not retained ivars, structs etc.) - */ -NSArray> *_Nonnull FBGetClassReferences(__unsafe_unretained Class _Nullable aCls); - -/** - @return An array of id objects that will have only those references - that are retained by the object. It also goes through parent classes. - */ -NSArray> *_Nonnull FBGetObjectStrongReferences(id _Nullable obj, - NSMutableDictionary> *> *_Nullable layoutCache); - -#ifdef __cplusplus -} -#endif diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayout.mm b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayout.mm deleted file mode 100644 index 5dbb558b..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayout.mm +++ /dev/null @@ -1,212 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "FBClassStrongLayout.h" - -#import -#import -#import -#import - -#import - -#import "FBIvarReference.h" -#import "FBObjectInStructReference.h" -#import "FBStructEncodingParser.h" -#import "Struct.h" -#import "Type.h" - -/** - If we stumble upon a struct, we need to go through it and check if it doesn't retain some objects. - */ -static NSArray *FBGetReferencesForObjectsInStructEncoding(FBIvarReference *ivar, std::string encoding) { - NSMutableArray *references = [NSMutableArray new]; - - std::string ivarName = std::string([ivar.name cStringUsingEncoding:NSUTF8StringEncoding]); - FB::RetainCycleDetector::Parser::Struct parsedStruct = - FB::RetainCycleDetector::Parser::parseStructEncodingWithName(encoding, ivarName); - - std::vector> types = parsedStruct.flattenTypes(); - - ptrdiff_t offset = ivar.offset; - - for (auto &type: types) { - NSUInteger size, align; - - std::string typeEncoding = type->typeEncoding; - if (typeEncoding[0] == '^') { - // It's a pointer, let's skip - size = sizeof(void *); - align = _Alignof(void *); - } else { - @try { - NSGetSizeAndAlignment(typeEncoding.c_str(), - &size, - &align); - } @catch (NSException *e) { - /** - If we failed, we probably have C++ and ObjC cannot get it's size and alignment. We are skipping. - If we would like to support it, we would need to derive size and alignment of type from the string. - C++ does not have reflection so we can't really do that unless we create the mapping ourselves. - */ - break; - } - } - - - // The object must be aligned - NSUInteger overAlignment = offset % align; - NSUInteger whatsMissing = (overAlignment == 0) ? 0 : align - overAlignment; - offset += whatsMissing; - - if (typeEncoding[0] == '@') { - - // The index that ivar layout will ask for is going to be aligned with pointer size - - // Prepare additional context - NSString *typeEncodingName = [NSString stringWithCString:type->name.c_str() encoding:NSUTF8StringEncoding]; - - NSMutableArray *namePath = [NSMutableArray new]; - - for (auto &name: type->typePath) { - NSString *nameString = [NSString stringWithCString:name.c_str() encoding:NSUTF8StringEncoding]; - if (nameString) { - [namePath addObject:nameString]; - } - } - - if (typeEncodingName) { - [namePath addObject:typeEncodingName]; - } - [references addObject:[[FBObjectInStructReference alloc] initWithIndex:(offset / sizeof(void *)) - namePath:namePath]]; - } - - offset += size; - } - - return references; -} - -NSArray> *FBGetClassReferences(Class aCls) { - NSMutableArray> *result = [NSMutableArray new]; - - unsigned int count; - Ivar *ivars = class_copyIvarList(aCls, &count); - - for (unsigned int i = 0; i < count; ++i) { - Ivar ivar = ivars[i]; - FBIvarReference *wrapper = [[FBIvarReference alloc] initWithIvar:ivar]; - - if (wrapper.type == FBStructType) { - std::string encoding = std::string(ivar_getTypeEncoding(wrapper.ivar)); - NSArray *references = FBGetReferencesForObjectsInStructEncoding(wrapper, encoding); - - [result addObjectsFromArray:references]; - } else { - [result addObject:wrapper]; - } - } - free(ivars); - - return [result copy]; -} - -static NSIndexSet *FBGetLayoutAsIndexesForDescription(NSUInteger minimumIndex, const uint8_t *layoutDescription) { - NSMutableIndexSet *interestingIndexes = [NSMutableIndexSet new]; - NSUInteger currentIndex = minimumIndex; - - while (*layoutDescription != '\x00') { - int upperNibble = (*layoutDescription & 0xf0) >> 4; - int lowerNibble = *layoutDescription & 0xf; - - // Upper nimble is for skipping - currentIndex += upperNibble; - - // Lower nimble describes count - [interestingIndexes addIndexesInRange:NSMakeRange(currentIndex, lowerNibble)]; - currentIndex += lowerNibble; - - ++layoutDescription; - } - - return interestingIndexes; -} - -static NSUInteger FBGetMinimumIvarIndex(__unsafe_unretained Class aCls) { - NSUInteger minimumIndex = 1; - unsigned int count; - Ivar *ivars = class_copyIvarList(aCls, &count); - - if (count > 0) { - Ivar ivar = ivars[0]; - ptrdiff_t offset = ivar_getOffset(ivar); - minimumIndex = offset / (sizeof(void *)); - } - - free(ivars); - - return minimumIndex; -} - -static NSArray> *FBGetStrongReferencesForClass(Class aCls) { - NSArray> *ivars = [FBGetClassReferences(aCls) filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) { - if ([evaluatedObject isKindOfClass:[FBIvarReference class]]) { - FBIvarReference *wrapper = evaluatedObject; - return wrapper.type != FBUnknownType; - } - return YES; - }]]; - - const uint8_t *fullLayout = class_getIvarLayout(aCls); - - if (!fullLayout) { - return nil; - } - - NSUInteger minimumIndex = FBGetMinimumIvarIndex(aCls); - NSIndexSet *parsedLayout = FBGetLayoutAsIndexesForDescription(minimumIndex, fullLayout); - - NSArray> *filteredIvars = - [ivars filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, - NSDictionary *bindings) { - return [parsedLayout containsIndex:[evaluatedObject indexInIvarLayout]]; - }]]; - - return filteredIvars; -} - -NSArray> *FBGetObjectStrongReferences(id obj, - NSMutableDictionary> *> *layoutCache) { - NSMutableArray> *array = [NSMutableArray new]; - - __unsafe_unretained Class previousClass = nil; - __unsafe_unretained Class currentClass = object_getClass(obj); - - while (previousClass != currentClass) { - NSArray> *ivars; - - if (layoutCache && currentClass) { - ivars = layoutCache[currentClass]; - } - - if (!ivars) { - ivars = FBGetStrongReferencesForClass(currentClass); - if (layoutCache && currentClass) { - layoutCache[currentClass] = ivars; - } - } - [array addObjectsFromArray:ivars]; - - previousClass = currentClass; - currentClass = class_getSuperclass(currentClass); - } - - return [array copy]; -} diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayoutHelpers.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayoutHelpers.h deleted file mode 100644 index 8ae718a5..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayoutHelpers.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#import - -#ifdef __cplusplus -extern "C" { -#endif - -/** - Returns object on given index for obj in its ivar layout. - It will try to map the object to an Objective-C object, so if the index - is invalid it will crash with BAD_ACCESS. - - It cannot be called under ARC. - */ -id FBExtractObjectByOffset(id obj, NSUInteger index); - -#ifdef __cplusplus -} -#endif diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayoutHelpers.m b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayoutHelpers.m deleted file mode 100644 index 2528dfc9..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayoutHelpers.m +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#if __has_feature(objc_arc) -#error This file must be compiled with MRR. Use -fno-objc-arc flag. -#endif - -#import "FBClassStrongLayoutHelpers.h" - -id FBExtractObjectByOffset(id obj, NSUInteger index) { - id *idx = (id *)((uintptr_t)obj + (index * sizeof(void *))); - - return *idx; -} diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/BaseType.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/BaseType.h deleted file mode 100644 index 026bafdf..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/BaseType.h +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#import - -namespace FB { namespace RetainCycleDetector { namespace Parser { - class BaseType { - public: - virtual ~BaseType() {} - }; - - class Unresolved: public BaseType { - public: - std::string value; - Unresolved(std::string value): value(value) {} - Unresolved(Unresolved&&) = default; - Unresolved &operator=(Unresolved&&) = default; - - Unresolved(const Unresolved&) = delete; - Unresolved &operator=(const Unresolved&) = delete; - }; -} } } diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/FBStructEncodingParser.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/FBStructEncodingParser.h deleted file mode 100644 index ffcf6759..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/FBStructEncodingParser.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#import "Struct.h" -#import "Type.h" - -namespace FB { namespace RetainCycleDetector { namespace Parser { - - /** - This function will parse a struct encoding from an ivar, and return an FBParsedStruct instance. - Check FBParsedStruct to learn more on how to interact with it. - - FBParseStructEncoding assumes the string passed to it will be a proper struct encoding. - It will not work with encodings provided by @encode() because they do not add names. - It will work with encodings provided by ivars (ivar_getTypeEncoding) - */ - Struct parseStructEncoding(const std::string &structEncodingString); - - - /** - You can provide name for root struct you are passing. The name will be then used - in typePath (check out FBParsedType for details). - The name here can be for example a name of an ivar with this struct. - */ - Struct parseStructEncodingWithName(const std::string &structEncodingString, - const std::string &structName); - - -} } } diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/FBStructEncodingParser.mm b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/FBStructEncodingParser.mm deleted file mode 100644 index dead2f62..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/FBStructEncodingParser.mm +++ /dev/null @@ -1,168 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "FBStructEncodingParser.h" - -#import -#import -#import -#import -#import - -#import "BaseType.h" - -namespace { - class _StringScanner { - public: - const std::string string; - size_t index; - - _StringScanner(const std::string &string): string(string), index(0) {} - - bool scanString(const std::string &stringToScan) { - if (!(string.compare(index, stringToScan.length(), stringToScan) == 0)) { - return false; - } - index += stringToScan.length(); - return true; - } - - const std::string scanUpToString(const std::string &upToString) { - size_t pos = string.find(upToString, index); - if (pos == std::string::npos) { - // Mark as whole string scanned - index = string.length(); - return ""; - } - - std::string inBetweenString = string.substr(index, pos - index); - index = pos; - return inBetweenString; - } - - const char currentCharacter() { - return string[index]; - } - - const std::string scanUpToCharacterFromSet(const std::string &characterSet) { - size_t pos = string.find_first_of(characterSet, index); - if (pos == std::string::npos) { - index = string.length(); - return ""; - } - - std::string inBetweenString = string.substr(index, pos-index); - index = pos; - return inBetweenString; - } - }; - -}; - -namespace FB { namespace RetainCycleDetector { namespace Parser { - - /** - Intermediate struct object used inside the algorithm to pass some - information when parsing nested structures. - */ - struct _StructParseResult { - std::vector> containedTypes; - const std::string typeName; - }; - - static const auto kOpenStruct = "{"; - static const auto kCloseStruct = "}"; - static const auto kLiteralEndingCharacters = "\"}"; - static const auto kQuote = "\""; - - static struct _StructParseResult _ParseStructEncodingWithScanner(_StringScanner &scanner, - NSString *debugStruct) { - std::vector> types; - - // Every struct starts with '{' - __unused const auto scannedCorrectly = scanner.scanString(kOpenStruct); - NSCAssert(scannedCorrectly, @"The first character of struct encoding should be {; debug_struct: %@", debugStruct); - - // Parse name - const auto structTypeName = scanner.scanUpToString("="); - scanner.scanString("="); - - while (!(scanner.scanString(kCloseStruct))) { - if (scanner.scanString(kQuote)) { - const auto parseResult = scanner.scanUpToString(kQuote); - scanner.scanString(kQuote); - if (parseResult.length() > 0) { - types.push_back(std::make_shared(parseResult)); - } - } else if (scanner.currentCharacter() == '{') { - // We do not want to consume '{' because we will call parser recursively - const auto locBefore = scanner.index; - auto parseResult = _ParseStructEncodingWithScanner(scanner, debugStruct); - - std::shared_ptr valueFromBefore; - if (!types.empty()) { - valueFromBefore = std::dynamic_pointer_cast(types.back()); - types.pop_back(); - } - const auto extractedNameFromBefore = valueFromBefore ? valueFromBefore->value - : ""; - std::shared_ptr type = std::make_shared(extractedNameFromBefore, - scanner.string.substr(locBefore, (scanner.index - locBefore)), - parseResult.typeName, - parseResult.containedTypes); - - types.emplace_back(type); - } else { - // It's a type name (literal), let's advance until we find '"', or '}' - const auto parseResult = scanner.scanUpToCharacterFromSet(kLiteralEndingCharacters); - std::string nameFromBefore = ""; - if (types.size() > 0) { - if (std::shared_ptr maybeUnresolved = std::dynamic_pointer_cast(types.back())) { - nameFromBefore = maybeUnresolved->value; - types.pop_back(); - } - } - std::shared_ptr type = std::make_shared(nameFromBefore, parseResult); - types.emplace_back(type); - } - } - - std::vector> filteredVector; - - for (const auto &t: types) { - if (const auto convertedType = std::dynamic_pointer_cast(t)) { - filteredVector.emplace_back(convertedType); - } - } - - return { - .containedTypes = filteredVector, - .typeName = structTypeName, - }; - } - - Struct parseStructEncoding(const std::string &structEncodingString) { - return parseStructEncodingWithName(structEncodingString, ""); - } - - Struct parseStructEncodingWithName(const std::string &structEncodingString, - const std::string &structName) { - _StringScanner scanner = _StringScanner(structEncodingString); - auto result = _ParseStructEncodingWithScanner(scanner, - [NSString stringWithCString:structEncodingString.c_str() - encoding:NSUTF8StringEncoding]); - - Struct outerStruct = Struct(structName, - structEncodingString, - result.typeName, - result.containedTypes); - outerStruct.passTypePath({}); - return outerStruct; - } -} } } diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/Struct.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/Struct.h deleted file mode 100644 index f7516167..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/Struct.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#import "Type.h" - -#import -#import -#import - -namespace FB { namespace RetainCycleDetector { namespace Parser { - class Struct: public Type { - public: - const std::string structTypeName; - - Struct(const std::string &name, - const std::string &typeEncoding, - const std::string &structTypeName, - std::vector> &typesContainedInStruct) - : Type(name, typeEncoding), - structTypeName(structTypeName), - typesContainedInStruct(std::move(typesContainedInStruct)) {}; - Struct(Struct&&) = default; - Struct &operator=(Struct&&) = default; - - Struct(const Struct&) = delete; - Struct &operator=(const Struct&) = delete; - - std::vector> flattenTypes(); - - virtual void passTypePath(std::vector typePath); - std::vector> typesContainedInStruct; - }; -} } } diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/Struct.mm b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/Struct.mm deleted file mode 100644 index 6e22ef13..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/Struct.mm +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "Struct.h" - -#import - -namespace FB { namespace RetainCycleDetector { namespace Parser { - void Struct::passTypePath(std::vector typePath) { - this->typePath = typePath; - - if (name.length() > 0) { - typePath.emplace_back(name); - } - if (structTypeName.length() > 0 && structTypeName != "?") { - typePath.emplace_back(structTypeName); - } - - for (auto &type: typesContainedInStruct) { - type->passTypePath(typePath); - } - } - - std::vector> Struct::flattenTypes() { - std::vector> flattenedTypes; - - for (const auto &type:typesContainedInStruct) { - const auto maybeStruct = std::dynamic_pointer_cast(type); - if (maybeStruct) { - // Complex type, recursively grab all references - flattenedTypes.reserve(flattenedTypes.size() + std::distance(maybeStruct->typesContainedInStruct.begin(), - maybeStruct->typesContainedInStruct.end())); - flattenedTypes.insert(flattenedTypes.end(), - maybeStruct->typesContainedInStruct.begin(), - maybeStruct->typesContainedInStruct.end()); - } else { - // Simple type - flattenedTypes.emplace_back(type); - } - } - - return flattenedTypes; - } - -} } } diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/Type.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/Type.h deleted file mode 100644 index 993e5ed6..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/Type.h +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#import -#import -#import - -#import "BaseType.h" - -namespace FB { namespace RetainCycleDetector { namespace Parser { - class Type: public BaseType { - public: - const std::string name; - const std::string typeEncoding; - - Type(const std::string &name, - const std::string &typeEncoding): name(name), typeEncoding(typeEncoding) {} - Type(Type&&) = default; - Type &operator=(Type&&) = default; - - Type(const Type&) = delete; - Type &operator=(const Type&) = delete; - - virtual void passTypePath(std::vector typePath) { - this->typePath = typePath; - } - - std::vector typePath; - }; -} } } diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBIvarReference.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBIvarReference.h deleted file mode 100644 index c95a818d..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBIvarReference.h +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#import - -#import "FBObjectReference.h" - -typedef NS_ENUM(NSUInteger, FBType) { - FBObjectType, - FBBlockType, - FBStructType, - FBUnknownType, -}; - -@interface FBIvarReference : NSObject - -@property (nonatomic, copy, readonly, nullable) NSString *name; -@property (nonatomic, readonly) FBType type; -@property (nonatomic, readonly) ptrdiff_t offset; -@property (nonatomic, readonly) NSUInteger index; -@property (nonatomic, readonly, nonnull) Ivar ivar; - -- (nonnull instancetype)initWithIvar:(nonnull Ivar)ivar; - -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBIvarReference.m b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBIvarReference.m deleted file mode 100644 index f8cd7809..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBIvarReference.m +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "FBIvarReference.h" - -@implementation FBIvarReference - -- (instancetype)initWithIvar:(Ivar)ivar -{ - if (self = [super init]) { - _name = @(ivar_getName(ivar)); - _type = [self _convertEncodingToType:ivar_getTypeEncoding(ivar)]; - _offset = ivar_getOffset(ivar); - _index = _offset / sizeof(void *); - _ivar = ivar; - } - - return self; -} - -- (FBType)_convertEncodingToType:(const char *)typeEncoding -{ - if (typeEncoding[0] == '{') { - return FBStructType; - } - - if (typeEncoding[0] == '@') { - // It's an object or block - - // Let's try to determine if it's a block. Blocks tend to have - // @? typeEncoding. Docs state that it's undefined type, so - // we should still verify that ivar with that type is a block - if (strncmp(typeEncoding, "@?", 2) == 0) { - return FBBlockType; - } - - return FBObjectType; - } - - return FBUnknownType; -} - -- (NSString *)description -{ - return [NSString stringWithFormat:@"[%@, index: %lu]", _name, (unsigned long)_index]; -} - -#pragma mark - FBObjectReference - -- (NSUInteger)indexInIvarLayout -{ - return _index; -} - -- (id)objectReferenceFromObject:(id)object -{ - return object_getIvar(object, _ivar); -} - -- (NSArray *)namePath -{ - return @[@(ivar_getName(_ivar))]; -} - -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBObjectInStructReference.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBObjectInStructReference.h deleted file mode 100644 index 9c5b3090..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBObjectInStructReference.h +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#import "FBObjectReference.h" - -/** - Struct object is an Objective-C object that is created inside - a struct. In Objective-C++ that object will be retained - by an object owning the struct, therefore will be listed in - ivar layout for the class. - */ - -@interface FBObjectInStructReference : NSObject - -- (nonnull instancetype)initWithIndex:(NSUInteger)index - namePath:(nullable NSArray *)namePath; - -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBObjectInStructReference.m b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBObjectInStructReference.m deleted file mode 100644 index 6d5c8e2f..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBObjectInStructReference.m +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "FBObjectInStructReference.h" - -#import "FBClassStrongLayoutHelpers.h" - -@implementation FBObjectInStructReference -{ - NSUInteger _index; - NSArray *_namePath; -} - -- (instancetype)initWithIndex:(NSUInteger)index - namePath:(NSArray *)namePath -{ - if (self = [super init]) { - _index = index; - _namePath = namePath; - } - - return self; -} - -- (NSString *)description -{ - return [NSString stringWithFormat:@"[in_struct; index: %td]", _index]; -} - -#pragma mark - FBObjectReference - -- (id)objectReferenceFromObject:(id)object -{ - return FBExtractObjectByOffset(object, _index); -} - -- (NSUInteger)indexInIvarLayout -{ - return _index; -} - -- (NSArray *)namePath -{ - return _namePath; -} - -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBObjectReference.h b/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBObjectReference.h deleted file mode 100644 index c00c217c..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBObjectReference.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -/** - Defines an outgoing reference from Objective-C object. - */ - -@protocol FBObjectReference - -/** - What is the index of that reference in ivar layout? - index * sizeof(void *) gives you offset from the - beginning of the object. - */ -- (NSUInteger)indexInIvarLayout; - -/** - For given object we need to be able to grab that object reference. - */ -- (nullable id)objectReferenceFromObject:(nullable id)object; - - -/** - For given reference in an object, there can be a path of names that leads to it. - For example it can be an ivar, thus the path will consist of ivar name only: - @[@"_myIvar"] - - But it also can be a reference in some nested struct like: - struct SomeStruct { - NSObject *myObject; - }; - - If that struct will be used in class, then name path would look like this: - @[@"_myIvar", @"SomeStruct", @"myObject"] - */ -- (nullable NSArray *)namePath; - -@end diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/LICENSE b/iOS_Tips/Pods/FBRetainCycleDetector/LICENSE deleted file mode 100644 index e1fe9070..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/LICENSE +++ /dev/null @@ -1,30 +0,0 @@ -License - -For FBRetainCycleDetector software - -Copyright (c) 2016-present, Facebook, Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the name Facebook nor the names of its contributors may be used to - endorse or promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/README.md b/iOS_Tips/Pods/FBRetainCycleDetector/README.md deleted file mode 100644 index 79bf40ea..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/README.md +++ /dev/null @@ -1,135 +0,0 @@ -# FBRetainCycleDetector -[![Build Status](https://travis-ci.org/facebook/FBRetainCycleDetector.svg?branch=master)](https://travis-ci.org/facebook/FBRetainCycleDetector) -[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) -[![CocoaPods](https://img.shields.io/cocoapods/v/FBRetainCycleDetector.svg?maxAge=2592000)]() -[![License](https://img.shields.io/cocoapods/l/FBRetainCycleDetector.svg)](https://github.com/facebook/FBRetainCycledetector/blob/master/LICENSE) - -An iOS library that finds retain cycles using runtime analysis. - -## About -Retain cycles are one of the most common ways of creating memory leaks. It's incredibly easy to create a retain cycle, and tends to be hard to spot it. -The goal of FBRetainCycleDetector is to help find retain cycles at runtime. -The features of this project were influenced by [Circle](https://github.com/mikeash/Circle). - -## Installation - -### Carthage - -To your Cartfile add: - - github "facebook/FBRetainCycleDetector" - -`FBRetainCycleDetector` is built out from non-debug builds, so when you want to test it, use - - carthage update --configuration Debug - -### CocoaPods - -To your podspec add: - - pod 'FBRetainCycleDetector' - -You'll be able to use `FBRetainCycleDetector` fully only in `Debug` builds. This is controlled by [compilation flag](https://github.com/facebook/FBRetainCycleDetector/blob/master/FBRetainCycleDetector/Detector/FBRetainCycleDetector.h#L83) that can be provided to the build to make it work in other configurations. - -## Example usage - -Let's quickly dive in - -```objc -#import -``` - -```objc -FBRetainCycleDetector *detector = [FBRetainCycleDetector new]; -[detector addCandidate:myObject]; -NSSet *retainCycles = [detector findRetainCycles]; -NSLog(@"%@", retainCycles); -``` - -`- (NSSet *> *)findRetainCycles` will return a set of arrays of wrapped objects. It's pretty hard to look at at first, but let's go through it. Every array in this set will represent one retain cycle. Every element in this array is a wrapper around one object in this retain cycle. Check [FBObjectiveCGraphElement](https://github.com/facebook/FBRetainCycleDetector/blob/master/FBRetainCycleDetector/Graph/FBObjectiveCGraphElement.h). - -Example output could look like this: -``` -{( - ( - "-> MyObject ", - "-> _someObject -> __NSArrayI " - ) -)} -``` -`MyObject` through `someObject` property retained `NSArray` that it was a part of. - -FBRetainCycleDetector will look for cycles that are no longer than 10 objects. -We can make it bigger (although it's going to be slower!). - -```objc -FBRetainCycleDetector *detector = [FBRetainCycleDetector new]; -[detector addCandidate:myObject]; -NSSet *retainCycles = [detector findRetainCyclesWithMaxCycleLength:100]; -``` - -### Filters - -There could also be retain cycles that we would like to omit. It's because not every retain cycle is a leak, and we might want to filter them out. -To do so we need to specify filters: - -```objc -NSMutableArray *filters = @[ - FBFilterBlockWithObjectIvarRelation([UIView class], @"_subviewCache"), -]; - -// Configuration object can describe filters as well as some options -FBObjectGraphConfiguration *configuration = -[[FBObjectGraphConfiguration alloc] initWithFilterBlocks:filters - shouldInspectTimers:YES]; -FBRetainCycleDetector *detector = [[FBRetainCycleDetector alloc] initWithConfiguration:configuration]; -[detector addCandidate:myObject]; -NSSet *retainCycles = [detector findRetainCycles]; -``` - -Every filter is a block that having two `FBObjectiveCGraphElement` objects can say, if their relation is valid. - -Check [FBStandardGraphEdgeFilters](FBRetainCycleDetector/Filtering/FBStandardGraphEdgeFilters.h) to learn more about how to use filters. - -### NSTimer - -NSTimer can be troublesome as it will retain it's target. Oftentimes it means a retain cycle. `FBRetainCycleDetector` can detect those, -but if you want to skip them, you can specify that in the configuration you are passing to `FBRetainCycleDetector`. - -```objc -FBObjectGraphConfiguration *configuration = -[[FBObjectGraphConfiguration alloc] initWithFilterBlocks:someFilters - shouldInspectTimers:NO]; -FBRetainCycleDetector *detector = [[FBRetainCycleDetector alloc] initWithConfiguration:configuration]; -``` - -### Associations - -Objective-C let's us set associated objects for every object using [objc_setAssociatedObject](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ObjCRuntimeRef/#//apple_ref/c/func/objc_setAssociatedObject). - -These associated objects can lead to retain cycles if we use retaining policies, like `OBJC_ASSOCIATION_RETAIN_NONATOMIC`. FBRetainCycleDetector can catch these kinds of cycles, but to do so we need to set it up. Early in the application's lifetime, preferably in `main.m` we can add this: - -```objc -#import - -int main(int argc, char * argv[]) { - @autoreleasepool { - [FBAssociationManager hook]; - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} -``` - -In the code above `[FBAssociationManager hook]` will use [fishhook](https://github.com/facebook/fishhook) to interpose functions `objc_setAssociatedObject` and `objc_resetAssociatedObjects` to track associations before they are made. - -## Getting Candidates - -If you want to profile your app, you might want to have an abstraction over how to get candidates for `FBRetainCycleDetector`. While you can simply track it your own, you can also use [FBAllocationTracker](https://github.com/facebook/FBAllocationTracker). It's a small tool we created that can help you track the objects. It offers simple API that you can query for example for all instances of given class, or all class names currently tracked, etc. - -`FBAllocationTracker` and `FBRetainCycleDetector` can work nicely together. We have created a small example and drop-in project called [FBMemoryProfiler](https://github.com/facebook/FBMemoryProfiler) that leverages both these projects. It offers you very basic UI that you can use to track all allocations and force retain cycle detection from UI. - -## Contributing -See the [CONTRIBUTING](CONTRIBUTING.md) file for how to help out. - -## License -[`FBRetainCycleDetector` is BSD-licensed](LICENSE). We also provide an additional [patent grant](PATENTS). diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/fishhook/fishhook.c b/iOS_Tips/Pods/FBRetainCycleDetector/fishhook/fishhook.c deleted file mode 100644 index 00ea9aa9..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/fishhook/fishhook.c +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright (c) 2013, Facebook, Inc. -// All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name Facebook nor the names of its contributors may be used to -// endorse or promote products derived from this software without specific -// prior written permission. -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#import "fishhook.h" - -#import -#import -#import -#import -#import -#import -#import - -#ifdef __LP64__ -typedef struct mach_header_64 mach_header_t; -typedef struct segment_command_64 segment_command_t; -typedef struct section_64 section_t; -typedef struct nlist_64 nlist_t; -#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT_64 -#else -typedef struct mach_header mach_header_t; -typedef struct segment_command segment_command_t; -typedef struct section section_t; -typedef struct nlist nlist_t; -#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT -#endif - -#ifndef SEG_DATA_CONST -#define SEG_DATA_CONST "__DATA_CONST" -#endif - -struct rcd_rebindings_entry { - struct rcd_rebinding *rebindings; - size_t rebindings_nel; - struct rcd_rebindings_entry *next; -}; - -static struct rcd_rebindings_entry *_rebindings_head; - -static int rcd_prepend_rebindings(struct rcd_rebindings_entry **rebindings_head, - struct rcd_rebinding rebindings[], - size_t nel) { - struct rcd_rebindings_entry *new_entry = malloc(sizeof(struct rcd_rebindings_entry)); - if (!new_entry) { - return -1; - } - new_entry->rebindings = malloc(sizeof(struct rcd_rebinding) * nel); - if (!new_entry->rebindings) { - free(new_entry); - return -1; - } - memcpy(new_entry->rebindings, rebindings, sizeof(struct rcd_rebinding) * nel); - new_entry->rebindings_nel = nel; - new_entry->next = *rebindings_head; - *rebindings_head = new_entry; - return 0; -} - -static void rcd_perform_rebinding_with_section(struct rcd_rebindings_entry *rebindings, - section_t *section, - intptr_t slide, - nlist_t *symtab, - char *strtab, - uint32_t *indirect_symtab) { - uint32_t *indirect_symbol_indices = indirect_symtab + section->reserved1; - void **indirect_symbol_bindings = (void **)((uintptr_t)slide + section->addr); - for (uint i = 0; i < section->size / sizeof(void *); i++) { - uint32_t symtab_index = indirect_symbol_indices[i]; - if (symtab_index == INDIRECT_SYMBOL_ABS || symtab_index == INDIRECT_SYMBOL_LOCAL || - symtab_index == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS)) { - continue; - } - uint32_t strtab_offset = symtab[symtab_index].n_un.n_strx; - char *symbol_name = strtab + strtab_offset; - struct rcd_rebindings_entry *cur = rebindings; - while (cur) { - for (uint j = 0; j < cur->rebindings_nel; j++) { - if (strlen(symbol_name) > 1 && - strcmp(&symbol_name[1], cur->rebindings[j].name) == 0) { - if (cur->rebindings[j].replaced != NULL && - indirect_symbol_bindings[i] != cur->rebindings[j].replacement) { - *(cur->rebindings[j].replaced) = indirect_symbol_bindings[i]; - } - indirect_symbol_bindings[i] = cur->rebindings[j].replacement; - goto symbol_loop; - } - } - cur = cur->next; - } - symbol_loop:; - } -} - -static void rebind_symbols_for_image(struct rcd_rebindings_entry *rebindings, - const struct mach_header *header, - intptr_t slide) { - Dl_info info; - if (dladdr(header, &info) == 0) { - return; - } - - segment_command_t *cur_seg_cmd; - segment_command_t *linkedit_segment = NULL; - struct symtab_command* symtab_cmd = NULL; - struct dysymtab_command* dysymtab_cmd = NULL; - - uintptr_t cur = (uintptr_t)header + sizeof(mach_header_t); - for (uint i = 0; i < header->ncmds; i++, cur += cur_seg_cmd->cmdsize) { - cur_seg_cmd = (segment_command_t *)cur; - if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { - if (strcmp(cur_seg_cmd->segname, SEG_LINKEDIT) == 0) { - linkedit_segment = cur_seg_cmd; - } - } else if (cur_seg_cmd->cmd == LC_SYMTAB) { - symtab_cmd = (struct symtab_command*)cur_seg_cmd; - } else if (cur_seg_cmd->cmd == LC_DYSYMTAB) { - dysymtab_cmd = (struct dysymtab_command*)cur_seg_cmd; - } - } - - if (!symtab_cmd || !dysymtab_cmd || !linkedit_segment || - !dysymtab_cmd->nindirectsyms) { - return; - } - - // Find base symbol/string table addresses - uintptr_t linkedit_base = (uintptr_t)slide + linkedit_segment->vmaddr - linkedit_segment->fileoff; - nlist_t *symtab = (nlist_t *)(linkedit_base + symtab_cmd->symoff); - char *strtab = (char *)(linkedit_base + symtab_cmd->stroff); - - // Get indirect symbol table (array of uint32_t indices into symbol table) - uint32_t *indirect_symtab = (uint32_t *)(linkedit_base + dysymtab_cmd->indirectsymoff); - - cur = (uintptr_t)header + sizeof(mach_header_t); - for (uint i = 0; i < header->ncmds; i++, cur += cur_seg_cmd->cmdsize) { - cur_seg_cmd = (segment_command_t *)cur; - if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { - if (strcmp(cur_seg_cmd->segname, SEG_DATA) != 0 && - strcmp(cur_seg_cmd->segname, SEG_DATA_CONST) != 0) { - continue; - } - for (uint j = 0; j < cur_seg_cmd->nsects; j++) { - section_t *sect = - (section_t *)(cur + sizeof(segment_command_t)) + j; - if ((sect->flags & SECTION_TYPE) == S_LAZY_SYMBOL_POINTERS) { - rcd_perform_rebinding_with_section(rebindings, sect, slide, symtab, strtab, indirect_symtab); - } - if ((sect->flags & SECTION_TYPE) == S_NON_LAZY_SYMBOL_POINTERS) { - rcd_perform_rebinding_with_section(rebindings, sect, slide, symtab, strtab, indirect_symtab); - } - } - } - } -} - -static void _rebind_symbols_for_image(const struct mach_header *header, - intptr_t slide) { - rebind_symbols_for_image(_rebindings_head, header, slide); -} - -int rcd_rebind_symbols_image(void *header, - intptr_t slide, - struct rcd_rebinding rebindings[], - size_t rebindings_nel) { - struct rcd_rebindings_entry *rebindings_head = NULL; - int retval = rcd_prepend_rebindings(&rebindings_head, rebindings, rebindings_nel); - rebind_symbols_for_image(rebindings_head, header, slide); - free(rebindings_head); - return retval; -} - -int rcd_rebind_symbols(struct rcd_rebinding rebindings[], size_t rebindings_nel) { - int retval = rcd_prepend_rebindings(&_rebindings_head, rebindings, rebindings_nel); - if (retval < 0) { - return retval; - } - // If this was the first call, register callback for image additions (which is also invoked for - // existing images, otherwise, just run on existing images - if (!_rebindings_head->next) { - _dyld_register_func_for_add_image(_rebind_symbols_for_image); - } else { - uint32_t c = _dyld_image_count(); - for (uint32_t i = 0; i < c; i++) { - _rebind_symbols_for_image(_dyld_get_image_header(i), _dyld_get_image_vmaddr_slide(i)); - } - } - return retval; -} diff --git a/iOS_Tips/Pods/FBRetainCycleDetector/fishhook/fishhook.h b/iOS_Tips/Pods/FBRetainCycleDetector/fishhook/fishhook.h deleted file mode 100644 index 20beedc4..00000000 --- a/iOS_Tips/Pods/FBRetainCycleDetector/fishhook/fishhook.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2013, Facebook, Inc. -// All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name Facebook nor the names of its contributors may be used to -// endorse or promote products derived from this software without specific -// prior written permission. -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef fishhook_h -#define fishhook_h - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif //__cplusplus - -/* - * A structure representing a particular intended rebinding from a symbol - * name to its replacement - */ -struct rcd_rebinding { - const char *name; - void *replacement; - void **replaced; -}; - -/* - * For each rebinding in rebindings, rebinds references to external, indirect - * symbols with the specified name to instead point at replacement for each - * image in the calling process as well as for all future images that are loaded - * by the process. If rebind_functions is called more than once, the symbols to - * rebind are added to the existing list of rebindings, and if a given symbol - * is rebound more than once, the later rebinding will take precedence. - */ -int rcd_rebind_symbols(struct rcd_rebinding rebindings[], size_t rebindings_nel); - -/* - * Rebinds as above, but only in the specified image. The header should point - * to the mach-o header, the slide should be the slide offset. Others as above. - */ -int rcd_rebind_symbols_image(void *header, - intptr_t slide, - struct rcd_rebinding rebindings[], - size_t rebindings_nel); - -#ifdef __cplusplus -} -#endif //__cplusplus - -#endif //fishhook_h - diff --git a/iOS_Tips/Pods/GPUImage/License.txt b/iOS_Tips/Pods/GPUImage/License.txt deleted file mode 100755 index e8062d91..00000000 --- a/iOS_Tips/Pods/GPUImage/License.txt +++ /dev/null @@ -1,9 +0,0 @@ -Copyright (c) 2012, Brad Larson, Ben Cochran, Hugues Lismonde, Keitaroh Kobayashi, Alaric Cole, Matthew Clark, Jacob Gundersen, Chris Williams. -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -Neither the name of the GPUImage framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/iOS_Tips/Pods/GPUImage/README.md b/iOS_Tips/Pods/GPUImage/README.md deleted file mode 100755 index a487f368..00000000 --- a/iOS_Tips/Pods/GPUImage/README.md +++ /dev/null @@ -1,733 +0,0 @@ -# GPUImage # - -
- - - -Brad Larson - -http://www.sunsetlakesoftware.com - -[@bradlarson](http://twitter.com/bradlarson) - -contact@sunsetlakesoftware.com - -## Overview ## - -The GPUImage framework is a BSD-licensed iOS library that lets you apply GPU-accelerated filters and other effects to images, live camera video, and movies. In comparison to Core Image (part of iOS 5.0), GPUImage allows you to write your own custom filters, supports deployment to iOS 4.0, and has a simpler interface. However, it currently lacks some of the more advanced features of Core Image, such as facial detection. - -For massively parallel operations like processing images or live video frames, GPUs have some significant performance advantages over CPUs. On an iPhone 4, a simple image filter can be over 100 times faster to perform on the GPU than an equivalent CPU-based filter. - -However, running custom filters on the GPU requires a lot of code to set up and maintain an OpenGL ES 2.0 rendering target for these filters. I created a sample project to do this: - -http://www.sunsetlakesoftware.com/2010/10/22/gpu-accelerated-video-processing-mac-and-ios - -and found that there was a lot of boilerplate code I had to write in its creation. Therefore, I put together this framework that encapsulates a lot of the common tasks you'll encounter when processing images and video and made it so that you don't need to care about the OpenGL ES 2.0 underpinnings. - -This framework compares favorably to Core Image when handling video, taking only 2.5 ms on an iPhone 4 to upload a frame from the camera, apply a gamma filter, and display, versus 106 ms for the same operation using Core Image. CPU-based processing takes 460 ms, making GPUImage 40X faster than Core Image for this operation on this hardware, and 184X faster than CPU-bound processing. On an iPhone 4S, GPUImage is only 4X faster than Core Image for this case, and 102X faster than CPU-bound processing. However, for more complex operations like Gaussian blurs at larger radii, Core Image currently outpaces GPUImage. - -## License ## - -BSD-style, with the full license available with the framework in License.txt. - -## Technical requirements ## - -- OpenGL ES 2.0: Applications using this will not run on the original iPhone, iPhone 3G, and 1st and 2nd generation iPod touches -- iOS 4.1 as a deployment target (4.0 didn't have some extensions needed for movie reading). iOS 4.3 is needed as a deployment target if you wish to show live video previews when taking a still photo. -- iOS 5.0 SDK to build -- Devices must have a camera to use camera-related functionality (obviously) -- The framework uses automatic reference counting (ARC), but should support projects using both ARC and manual reference counting if added as a subproject as explained below. For manual reference counting applications targeting iOS 4.x, you'll need add -fobjc-arc to the Other Linker Flags for your application project. - -## General architecture ## - -GPUImage uses OpenGL ES 2.0 shaders to perform image and video manipulation much faster than could be done in CPU-bound routines. However, it hides the complexity of interacting with the OpenGL ES API in a simplified Objective-C interface. This interface lets you define input sources for images and video, attach filters in a chain, and send the resulting processed image or video to the screen, to a UIImage, or to a movie on disk. - -Images or frames of video are uploaded from source objects, which are subclasses of GPUImageOutput. These include GPUImageVideoCamera (for live video from an iOS camera), GPUImageStillCamera (for taking photos with the camera), GPUImagePicture (for still images), and GPUImageMovie (for movies). Source objects upload still image frames to OpenGL ES as textures, then hand those textures off to the next objects in the processing chain. - -Filters and other subsequent elements in the chain conform to the GPUImageInput protocol, which lets them take in the supplied or processed texture from the previous link in the chain and do something with it. Objects one step further down the chain are considered targets, and processing can be branched by adding multiple targets to a single output or filter. - -For example, an application that takes in live video from the camera, converts that video to a sepia tone, then displays the video onscreen would set up a chain looking something like the following: - - GPUImageVideoCamera -> GPUImageSepiaFilter -> GPUImageView - -## Adding the static library to your iOS project ## - -Note: if you want to use this in a Swift project, you need to use the steps in the "Adding this as a framework" section instead of the following. Swift needs modules for third-party code. - -Once you have the latest source code for the framework, it's fairly straightforward to add it to your application. Start by dragging the GPUImage.xcodeproj file into your application's Xcode project to embed the framework in your project. Next, go to your application's target and add GPUImage as a Target Dependency. Finally, you'll want to drag the libGPUImage.a library from the GPUImage framework's Products folder to the Link Binary With Libraries build phase in your application's target. - -GPUImage needs a few other frameworks to be linked into your application, so you'll need to add the following as linked libraries in your application target: - -- CoreMedia -- CoreVideo -- OpenGLES -- AVFoundation -- QuartzCore - -You'll also need to find the framework headers, so within your project's build settings set the Header Search Paths to the relative path from your application to the framework/ subdirectory within the GPUImage source directory. Make this header search path recursive. - -To use the GPUImage classes within your application, simply include the core framework header using the following: - - #import "GPUImage.h" - -As a note: if you run into the error "Unknown class GPUImageView in Interface Builder" or the like when trying to build an interface with Interface Builder, you may need to add -ObjC to your Other Linker Flags in your project's build settings. - -Also, if you need to deploy this to iOS 4.x, it appears that the current version of Xcode (4.3) requires that you weak-link the Core Video framework in your final application or you see crashes with the message "Symbol not found: _CVOpenGLESTextureCacheCreate" when you create an archive for upload to the App Store or for ad hoc distribution. To do this, go to your project's Build Phases tab, expand the Link Binary With Libraries group, and find CoreVideo.framework in the list. Change the setting for it in the far right of the list from Required to Optional. - -Additionally, this is an ARC-enabled framework, so if you want to use this within a manual reference counted application targeting iOS 4.x, you'll need to add -fobjc-arc to your Other Linker Flags as well. - -### Building a static library at the command line ### - -If you don't want to include the project as a dependency in your application's Xcode project, you can build a universal static library for the iOS Simulator or device. To do this, run `build.sh` at the command line. The resulting library and header files will be located at `build/Release-iphone`. You may also change the version of the iOS SDK by changing the `IOSSDK_VER` variable in `build.sh` (all available versions can be found using `xcodebuild -showsdks`). - -## Adding this as a framework (module) to your Mac or iOS project ## - -Xcode 6 and iOS 8 support the use of full frameworks, as does the Mac, which simplifies the process of adding this to your application. To add this to your application, I recommend dragging the .xcodeproj project file into your application's project (as you would in the static library target). - -For your application, go to its target build settings and choose the Build Phases tab. Under the Target Dependencies grouping, add GPUImageFramework on iOS (not GPUImage, which builds the static library) or GPUImage on the Mac. Under the Link Binary With Libraries section, add GPUImage.framework. - -This should cause GPUImage to build as a framework. Under Xcode 6, this will also build as a module, which will allow you to use this in Swift projects. When set up as above, you should just need to use - - import GPUImage - -to pull it in. - -You then need to add a new Copy Files build phase, set the Destination to Frameworks, and add the GPUImage.framework build product to that. This will allow the framework to be bundled with your application (otherwise, you'll see cryptic "dyld: Library not loaded: @rpath/GPUImage.framework/GPUImage" errors on execution). - -### Documentation ### - -Documentation is generated from header comments using appledoc. To build the documentation, switch to the "Documentation" scheme in Xcode. You should ensure that "APPLEDOC_PATH" (a User-Defined build setting) points to an appledoc binary, available on Github or through Homebrew. It will also build and install a .docset file, which you can view with your favorite documentation tool. - -## Performing common tasks ## - -### Filtering live video ### - -To filter live video from an iOS device's camera, you can use code like the following: - - GPUImageVideoCamera *videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPreset640x480 cameraPosition:AVCaptureDevicePositionBack]; - videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait; - - GPUImageFilter *customFilter = [[GPUImageFilter alloc] initWithFragmentShaderFromFile:@"CustomShader"]; - GPUImageView *filteredVideoView = [[GPUImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, viewWidth, viewHeight)]; - - // Add the view somewhere so it's visible - - [videoCamera addTarget:customFilter]; - [customFilter addTarget:filteredVideoView]; - - [videoCamera startCameraCapture]; - -This sets up a video source coming from the iOS device's back-facing camera, using a preset that tries to capture at 640x480. This video is captured with the interface being in portrait mode, where the landscape-left-mounted camera needs to have its video frames rotated before display. A custom filter, using code from the file CustomShader.fsh, is then set as the target for the video frames from the camera. These filtered video frames are finally displayed onscreen with the help of a UIView subclass that can present the filtered OpenGL ES texture that results from this pipeline. - -The fill mode of the GPUImageView can be altered by setting its fillMode property, so that if the aspect ratio of the source video is different from that of the view, the video will either be stretched, centered with black bars, or zoomed to fill. - -For blending filters and others that take in more than one image, you can create multiple outputs and add a single filter as a target for both of these outputs. The order with which the outputs are added as targets will affect the order in which the input images are blended or otherwise processed. - -Also, if you wish to enable microphone audio capture for recording to a movie, you'll need to set the audioEncodingTarget of the camera to be your movie writer, like for the following: - - videoCamera.audioEncodingTarget = movieWriter; - - -### Capturing and filtering a still photo ### - -To capture and filter still photos, you can use a process similar to the one for filtering video. Instead of a GPUImageVideoCamera, you use a GPUImageStillCamera: - - stillCamera = [[GPUImageStillCamera alloc] init]; - stillCamera.outputImageOrientation = UIInterfaceOrientationPortrait; - - filter = [[GPUImageGammaFilter alloc] init]; - [stillCamera addTarget:filter]; - GPUImageView *filterView = (GPUImageView *)self.view; - [filter addTarget:filterView]; - - [stillCamera startCameraCapture]; - -This will give you a live, filtered feed of the still camera's preview video. Note that this preview video is only provided on iOS 4.3 and higher, so you may need to set that as your deployment target if you wish to have this functionality. - -Once you want to capture a photo, you use a callback block like the following: - - [stillCamera capturePhotoProcessedUpToFilter:filter withCompletionHandler:^(UIImage *processedImage, NSError *error){ - NSData *dataForJPEGFile = UIImageJPEGRepresentation(processedImage, 0.8); - - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths objectAtIndex:0]; - - NSError *error2 = nil; - if (![dataForJPEGFile writeToFile:[documentsDirectory stringByAppendingPathComponent:@"FilteredPhoto.jpg"] options:NSAtomicWrite error:&error2]) - { - return; - } - }]; - -The above code captures a full-size photo processed by the same filter chain used in the preview view and saves that photo to disk as a JPEG in the application's documents directory. - -Note that the framework currently can't handle images larger than 2048 pixels wide or high on older devices (those before the iPhone 4S, iPad 2, or Retina iPad) due to texture size limitations. This means that the iPhone 4, whose camera outputs still photos larger than this, won't be able to capture photos like this. A tiling mechanism is being implemented to work around this. All other devices should be able to capture and filter photos using this method. - -### Processing a still image ### - -There are a couple of ways to process a still image and create a result. The first way you can do this is by creating a still image source object and manually creating a filter chain: - - UIImage *inputImage = [UIImage imageNamed:@"Lambeau.jpg"]; - - GPUImagePicture *stillImageSource = [[GPUImagePicture alloc] initWithImage:inputImage]; - GPUImageSepiaFilter *stillImageFilter = [[GPUImageSepiaFilter alloc] init]; - - [stillImageSource addTarget:stillImageFilter]; - [stillImageFilter useNextFrameForImageCapture]; - [stillImageSource processImage]; - - UIImage *currentFilteredVideoFrame = [stillImageFilter imageFromCurrentFramebuffer]; - -Note that for a manual capture of an image from a filter, you need to set -useNextFrameForImageCapture in order to tell the filter that you'll be needing to capture from it later. By default, GPUImage reuses framebuffers within filters to conserve memory, so if you need to hold on to a filter's framebuffer for manual image capture, you need to let it know ahead of time. - -For single filters that you wish to apply to an image, you can simply do the following: - - GPUImageSepiaFilter *stillImageFilter2 = [[GPUImageSepiaFilter alloc] init]; - UIImage *quickFilteredImage = [stillImageFilter2 imageByFilteringImage:inputImage]; - - -### Writing a custom filter ### - -One significant advantage of this framework over Core Image on iOS (as of iOS 5.0) is the ability to write your own custom image and video processing filters. These filters are supplied as OpenGL ES 2.0 fragment shaders, written in the C-like OpenGL Shading Language. - -A custom filter is initialized with code like - - GPUImageFilter *customFilter = [[GPUImageFilter alloc] initWithFragmentShaderFromFile:@"CustomShader"]; - -where the extension used for the fragment shader is .fsh. Additionally, you can use the -initWithFragmentShaderFromString: initializer to provide the fragment shader as a string, if you would not like to ship your fragment shaders in your application bundle. - -Fragment shaders perform their calculations for each pixel to be rendered at that filter stage. They do this using the OpenGL Shading Language (GLSL), a C-like language with additions specific to 2-D and 3-D graphics. An example of a fragment shader is the following sepia-tone filter: - - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - lowp vec4 outputColor; - outputColor.r = (textureColor.r * 0.393) + (textureColor.g * 0.769) + (textureColor.b * 0.189); - outputColor.g = (textureColor.r * 0.349) + (textureColor.g * 0.686) + (textureColor.b * 0.168); - outputColor.b = (textureColor.r * 0.272) + (textureColor.g * 0.534) + (textureColor.b * 0.131); - outputColor.a = 1.0; - - gl_FragColor = outputColor; - } - -For an image filter to be usable within the GPUImage framework, the first two lines that take in the textureCoordinate varying (for the current coordinate within the texture, normalized to 1.0) and the inputImageTexture uniform (for the actual input image frame texture) are required. - -The remainder of the shader grabs the color of the pixel at this location in the passed-in texture, manipulates it in such a way as to produce a sepia tone, and writes that pixel color out to be used in the next stage of the processing pipeline. - -One thing to note when adding fragment shaders to your Xcode project is that Xcode thinks they are source code files. To work around this, you'll need to manually move your shader from the Compile Sources build phase to the Copy Bundle Resources one in order to get the shader to be included in your application bundle. - - -### Filtering and re-encoding a movie ### - -Movies can be loaded into the framework via the GPUImageMovie class, filtered, and then written out using a GPUImageMovieWriter. GPUImageMovieWriter is also fast enough to record video in realtime from an iPhone 4's camera at 640x480, so a direct filtered video source can be fed into it. Currently, GPUImageMovieWriter is fast enough to record live 720p video at up to 20 FPS on the iPhone 4, and both 720p and 1080p video at 30 FPS on the iPhone 4S (as well as on the new iPad). - -The following is an example of how you would load a sample movie, pass it through a pixellation filter, then record the result to disk as a 480 x 640 h.264 movie: - - movieFile = [[GPUImageMovie alloc] initWithURL:sampleURL]; - pixellateFilter = [[GPUImagePixellateFilter alloc] init]; - - [movieFile addTarget:pixellateFilter]; - - NSString *pathToMovie = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Movie.m4v"]; - unlink([pathToMovie UTF8String]); - NSURL *movieURL = [NSURL fileURLWithPath:pathToMovie]; - - movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:CGSizeMake(480.0, 640.0)]; - [pixellateFilter addTarget:movieWriter]; - - movieWriter.shouldPassthroughAudio = YES; - movieFile.audioEncodingTarget = movieWriter; - [movieFile enableSynchronizedEncodingUsingMovieWriter:movieWriter]; - - [movieWriter startRecording]; - [movieFile startProcessing]; - -Once recording is finished, you need to remove the movie recorder from the filter chain and close off the recording using code like the following: - - [pixellateFilter removeTarget:movieWriter]; - [movieWriter finishRecording]; - -A movie won't be usable until it has been finished off, so if this is interrupted before this point, the recording will be lost. - -### Interacting with OpenGL ES ### - -GPUImage can both export and import textures from OpenGL ES through the use of its GPUImageTextureOutput and GPUImageTextureInput classes, respectively. This lets you record a movie from an OpenGL ES scene that is rendered to a framebuffer object with a bound texture, or filter video or images and then feed them into OpenGL ES as a texture to be displayed in the scene. - -The one caution with this approach is that the textures used in these processes must be shared between GPUImage's OpenGL ES context and any other context via a share group or something similar. - -## Built-in filters ## - -There are currently 125 built-in filters, divided into the following categories: - -### Color adjustments ### - -- **GPUImageBrightnessFilter**: Adjusts the brightness of the image - - *brightness*: The adjusted brightness (-1.0 - 1.0, with 0.0 as the default) - -- **GPUImageExposureFilter**: Adjusts the exposure of the image - - *exposure*: The adjusted exposure (-10.0 - 10.0, with 0.0 as the default) - -- **GPUImageContrastFilter**: Adjusts the contrast of the image - - *contrast*: The adjusted contrast (0.0 - 4.0, with 1.0 as the default) - -- **GPUImageSaturationFilter**: Adjusts the saturation of an image - - *saturation*: The degree of saturation or desaturation to apply to the image (0.0 - 2.0, with 1.0 as the default) - -- **GPUImageGammaFilter**: Adjusts the gamma of an image - - *gamma*: The gamma adjustment to apply (0.0 - 3.0, with 1.0 as the default) - -- **GPUImageLevelsFilter**: Photoshop-like levels adjustment. The min, max, minOut and maxOut parameters are floats in the range [0, 1]. If you have parameters from Photoshop in the range [0, 255] you must first convert them to be [0, 1]. The gamma/mid parameter is a float >= 0. This matches the value from Photoshop. If you want to apply levels to RGB as well as individual channels you need to use this filter twice - first for the individual channels and then for all channels. - -- **GPUImageColorMatrixFilter**: Transforms the colors of an image by applying a matrix to them - - *colorMatrix*: A 4x4 matrix used to transform each color in an image - - *intensity*: The degree to which the new transformed color replaces the original color for each pixel - -- **GPUImageRGBFilter**: Adjusts the individual RGB channels of an image - - *red*: Normalized values by which each color channel is multiplied. The range is from 0.0 up, with 1.0 as the default. - - *green*: - - *blue*: - -- **GPUImageHueFilter**: Adjusts the hue of an image - - *hue*: The hue angle, in degrees. 90 degrees by default - -- **GPUImageToneCurveFilter**: Adjusts the colors of an image based on spline curves for each color channel. - - *redControlPoints*: - - *greenControlPoints*: - - *blueControlPoints*: - - *rgbCompositeControlPoints*: The tone curve takes in a series of control points that define the spline curve for each color component, or for all three in the composite. These are stored as NSValue-wrapped CGPoints in an NSArray, with normalized X and Y coordinates from 0 - 1. The defaults are (0,0), (0.5,0.5), (1,1). - -- **GPUImageHighlightShadowFilter**: Adjusts the shadows and highlights of an image - - *shadows*: Increase to lighten shadows, from 0.0 to 1.0, with 0.0 as the default. - - *highlights*: Decrease to darken highlights, from 0.0 to 1.0, with 1.0 as the default. - -- **GPUImageLookupFilter**: Uses an RGB color lookup image to remap the colors in an image. First, use your favourite photo editing application to apply a filter to lookup.png from GPUImage/framework/Resources. For this to work properly each pixel color must not depend on other pixels (e.g. blur will not work). If you need a more complex filter you can create as many lookup tables as required. Once ready, use your new lookup.png file as a second input for GPUImageLookupFilter. - -- **GPUImageAmatorkaFilter**: A photo filter based on a Photoshop action by Amatorka: http://amatorka.deviantart.com/art/Amatorka-Action-2-121069631 . If you want to use this effect you have to add lookup_amatorka.png from the GPUImage Resources folder to your application bundle. - -- **GPUImageMissEtikateFilter**: A photo filter based on a Photoshop action by Miss Etikate: http://miss-etikate.deviantart.com/art/Photoshop-Action-15-120151961 . If you want to use this effect you have to add lookup_miss_etikate.png from the GPUImage Resources folder to your application bundle. - -- **GPUImageSoftEleganceFilter**: Another lookup-based color remapping filter. If you want to use this effect you have to add lookup_soft_elegance_1.png and lookup_soft_elegance_2.png from the GPUImage Resources folder to your application bundle. - -- **GPUImageColorInvertFilter**: Inverts the colors of an image - -- **GPUImageGrayscaleFilter**: Converts an image to grayscale (a slightly faster implementation of the saturation filter, without the ability to vary the color contribution) - -- **GPUImageMonochromeFilter**: Converts the image to a single-color version, based on the luminance of each pixel - - *intensity*: The degree to which the specific color replaces the normal image color (0.0 - 1.0, with 1.0 as the default) - - *color*: The color to use as the basis for the effect, with (0.6, 0.45, 0.3, 1.0) as the default. - -- **GPUImageFalseColorFilter**: Uses the luminance of the image to mix between two user-specified colors - - *firstColor*: The first and second colors specify what colors replace the dark and light areas of the image, respectively. The defaults are (0.0, 0.0, 0.5) amd (1.0, 0.0, 0.0). - - *secondColor*: - -- **GPUImageHazeFilter**: Used to add or remove haze (similar to a UV filter) - - *distance*: Strength of the color applied. Default 0. Values between -.3 and .3 are best. - - *slope*: Amount of color change. Default 0. Values between -.3 and .3 are best. - -- **GPUImageSepiaFilter**: Simple sepia tone filter - - *intensity*: The degree to which the sepia tone replaces the normal image color (0.0 - 1.0, with 1.0 as the default) - -- **GPUImageOpacityFilter**: Adjusts the alpha channel of the incoming image - - *opacity*: The value to multiply the incoming alpha channel for each pixel by (0.0 - 1.0, with 1.0 as the default) - -- **GPUImageSolidColorGenerator**: This outputs a generated image with a solid color. You need to define the image size using -forceProcessingAtSize: - - *color*: The color, in a four component format, that is used to fill the image. - -- **GPUImageLuminanceThresholdFilter**: Pixels with a luminance above the threshold will appear white, and those below will be black - - *threshold*: The luminance threshold, from 0.0 to 1.0, with a default of 0.5 - -- **GPUImageAdaptiveThresholdFilter**: Determines the local luminance around a pixel, then turns the pixel black if it is below that local luminance and white if above. This can be useful for picking out text under varying lighting conditions. - - *blurRadiusInPixels*: A multiplier for the background averaging blur radius in pixels, with a default of 4. - -- **GPUImageAverageLuminanceThresholdFilter**: This applies a thresholding operation where the threshold is continually adjusted based on the average luminance of the scene. - - *thresholdMultiplier*: This is a factor that the average luminance will be multiplied by in order to arrive at the final threshold to use. By default, this is 1.0. - -- **GPUImageHistogramFilter**: This analyzes the incoming image and creates an output histogram with the frequency at which each color value occurs. The output of this filter is a 3-pixel-high, 256-pixel-wide image with the center (vertical) pixels containing pixels that correspond to the frequency at which various color values occurred. Each color value occupies one of the 256 width positions, from 0 on the left to 255 on the right. This histogram can be generated for individual color channels (kGPUImageHistogramRed, kGPUImageHistogramGreen, kGPUImageHistogramBlue), the luminance of the image (kGPUImageHistogramLuminance), or for all three color channels at once (kGPUImageHistogramRGB). - - *downsamplingFactor*: Rather than sampling every pixel, this dictates what fraction of the image is sampled. By default, this is 16 with a minimum of 1. This is needed to keep from saturating the histogram, which can only record 256 pixels for each color value before it becomes overloaded. - -- **GPUImageHistogramGenerator**: This is a special filter, in that it's primarily intended to work with the GPUImageHistogramFilter. It generates an output representation of the color histograms generated by GPUImageHistogramFilter, but it could be repurposed to display other kinds of values. It takes in an image and looks at the center (vertical) pixels. It then plots the numerical values of the RGB components in separate colored graphs in an output texture. You may need to force a size for this filter in order to make its output visible. - -- **GPUImageAverageColor**: This processes an input image and determines the average color of the scene, by averaging the RGBA components for each pixel in the image. A reduction process is used to progressively downsample the source image on the GPU, followed by a short averaging calculation on the CPU. The output from this filter is meaningless, but you need to set the colorAverageProcessingFinishedBlock property to a block that takes in four color components and a frame time and does something with them. - -- **GPUImageLuminosity**: Like the GPUImageAverageColor, this reduces an image to its average luminosity. You need to set the luminosityProcessingFinishedBlock to handle the output of this filter, which just returns a luminosity value and a frame time. - -- **GPUImageChromaKeyFilter**: For a given color in the image, sets the alpha channel to 0. This is similar to the GPUImageChromaKeyBlendFilter, only instead of blending in a second image for a matching color this doesn't take in a second image and just turns a given color transparent. - - *thresholdSensitivity*: How close a color match needs to exist to the target color to be replaced (default of 0.4) - - *smoothing*: How smoothly to blend for the color match (default of 0.1) - -### Image processing ### - -- **GPUImageTransformFilter**: This applies an arbitrary 2-D or 3-D transformation to an image - - *affineTransform*: This takes in a CGAffineTransform to adjust an image in 2-D - - *transform3D*: This takes in a CATransform3D to manipulate an image in 3-D - - *ignoreAspectRatio*: By default, the aspect ratio of the transformed image is maintained, but this can be set to YES to make the transformation independent of aspect ratio - -- **GPUImageCropFilter**: This crops an image to a specific region, then passes only that region on to the next stage in the filter - - *cropRegion*: A rectangular area to crop out of the image, normalized to coordinates from 0.0 - 1.0. The (0.0, 0.0) position is in the upper left of the image. - -- **GPUImageLanczosResamplingFilter**: This lets you up- or downsample an image using Lanczos resampling, which results in noticeably better quality than the standard linear or trilinear interpolation. Simply use -forceProcessingAtSize: to set the target output resolution for the filter, and the image will be resampled for that new size. - -- **GPUImageSharpenFilter**: Sharpens the image - - *sharpness*: The sharpness adjustment to apply (-4.0 - 4.0, with 0.0 as the default) - -- **GPUImageUnsharpMaskFilter**: Applies an unsharp mask - - *blurRadiusInPixels*: The blur radius of the underlying Gaussian blur. The default is 4.0. - - *intensity*: The strength of the sharpening, from 0.0 on up, with a default of 1.0 - -- **GPUImageGaussianBlurFilter**: A hardware-optimized, variable-radius Gaussian blur - - *texelSpacingMultiplier*: A multiplier for the spacing between texels, ranging from 0.0 on up, with a default of 1.0. Adjusting this may slightly increase the blur strength, but will introduce artifacts in the result. Highly recommend using other parameters first, before touching this one. - - *blurRadiusInPixels*: A radius in pixels to use for the blur, with a default of 2.0. This adjusts the sigma variable in the Gaussian distribution function. - - *blurRadiusAsFractionOfImageWidth*: - - *blurRadiusAsFractionOfImageHeight*: Setting these properties will allow the blur radius to scale with the size of the image - - *blurPasses*: The number of times to sequentially blur the incoming image. The more passes, the slower the filter. - -- **GPUImageBoxBlurFilter**: A hardware-optimized, variable-radius box blur - - *texelSpacingMultiplier*: A multiplier for the spacing between texels, ranging from 0.0 on up, with a default of 1.0. Adjusting this may slightly increase the blur strength, but will introduce artifacts in the result. Highly recommend using other parameters first, before touching this one. - - *blurRadiusInPixels*: A radius in pixels to use for the blur, with a default of 2.0. This adjusts the sigma variable in the Gaussian distribution function. - - *blurRadiusAsFractionOfImageWidth*: - - *blurRadiusAsFractionOfImageHeight*: Setting these properties will allow the blur radius to scale with the size of the image - - *blurPasses*: The number of times to sequentially blur the incoming image. The more passes, the slower the filter. - -- **GPUImageSingleComponentGaussianBlurFilter**: A modification of the GPUImageGaussianBlurFilter that operates only on the red component - - *texelSpacingMultiplier*: A multiplier for the spacing between texels, ranging from 0.0 on up, with a default of 1.0. Adjusting this may slightly increase the blur strength, but will introduce artifacts in the result. Highly recommend using other parameters first, before touching this one. - - *blurRadiusInPixels*: A radius in pixels to use for the blur, with a default of 2.0. This adjusts the sigma variable in the Gaussian distribution function. - - *blurRadiusAsFractionOfImageWidth*: - - *blurRadiusAsFractionOfImageHeight*: Setting these properties will allow the blur radius to scale with the size of the image - - *blurPasses*: The number of times to sequentially blur the incoming image. The more passes, the slower the filter. - -- **GPUImageGaussianSelectiveBlurFilter**: A Gaussian blur that preserves focus within a circular region - - *blurRadiusInPixels*: A radius in pixels to use for the blur, with a default of 5.0. This adjusts the sigma variable in the Gaussian distribution function. - - *excludeCircleRadius*: The radius of the circular area being excluded from the blur - - *excludeCirclePoint*: The center of the circular area being excluded from the blur - - *excludeBlurSize*: The size of the area between the blurred portion and the clear circle - - *aspectRatio*: The aspect ratio of the image, used to adjust the circularity of the in-focus region. By default, this matches the image aspect ratio, but you can override this value. - -- **GPUImageGaussianBlurPositionFilter**: The inverse of the GPUImageGaussianSelectiveBlurFilter, applying the blur only within a certain circle - - *blurSize*: A multiplier for the size of the blur, ranging from 0.0 on up, with a default of 1.0 - - *blurCenter*: Center for the blur, defaults to 0.5, 0.5 - - *blurRadius*: Radius for the blur, defaults to 1.0 - -- **GPUImageiOSBlurFilter**: An attempt to replicate the background blur used on iOS 7 in places like the control center. - - *blurRadiusInPixels*: A radius in pixels to use for the blur, with a default of 12.0. This adjusts the sigma variable in the Gaussian distribution function. - - *saturation*: Saturation ranges from 0.0 (fully desaturated) to 2.0 (max saturation), with 0.8 as the normal level - - *downsampling*: The degree to which to downsample, then upsample the incoming image to minimize computations within the Gaussian blur, with a default of 4.0. - -- **GPUImageMedianFilter**: Takes the median value of the three color components, over a 3x3 area - -- **GPUImageBilateralFilter**: A bilateral blur, which tries to blur similar color values while preserving sharp edges - - *texelSpacingMultiplier*: A multiplier for the spacing between texel reads, ranging from 0.0 on up, with a default of 4.0 - - *distanceNormalizationFactor*: A normalization factor for the distance between central color and sample color, with a default of 8.0. - -- **GPUImageTiltShiftFilter**: A simulated tilt shift lens effect - - *blurRadiusInPixels*: The radius of the underlying blur, in pixels. This is 7.0 by default. - - *topFocusLevel*: The normalized location of the top of the in-focus area in the image, this value should be lower than bottomFocusLevel, default 0.4 - - *bottomFocusLevel*: The normalized location of the bottom of the in-focus area in the image, this value should be higher than topFocusLevel, default 0.6 - - *focusFallOffRate*: The rate at which the image gets blurry away from the in-focus region, default 0.2 - -- **GPUImage3x3ConvolutionFilter**: Runs a 3x3 convolution kernel against the image - - *convolutionKernel*: The convolution kernel is a 3x3 matrix of values to apply to the pixel and its 8 surrounding pixels. The matrix is specified in row-major order, with the top left pixel being one.one and the bottom right three.three. If the values in the matrix don't add up to 1.0, the image could be brightened or darkened. - -- **GPUImageSobelEdgeDetectionFilter**: Sobel edge detection, with edges highlighted in white - - *texelWidth*: - - *texelHeight*: These parameters affect the visibility of the detected edges - - *edgeStrength*: Adjusts the dynamic range of the filter. Higher values lead to stronger edges, but can saturate the intensity colorspace. Default is 1.0. - -- **GPUImagePrewittEdgeDetectionFilter**: Prewitt edge detection, with edges highlighted in white - - *texelWidth*: - - *texelHeight*: These parameters affect the visibility of the detected edges - - *edgeStrength*: Adjusts the dynamic range of the filter. Higher values lead to stronger edges, but can saturate the intensity colorspace. Default is 1.0. - -- **GPUImageThresholdEdgeDetectionFilter**: Performs Sobel edge detection, but applies a threshold instead of giving gradual strength values - - *texelWidth*: - - *texelHeight*: These parameters affect the visibility of the detected edges - - *edgeStrength*: Adjusts the dynamic range of the filter. Higher values lead to stronger edges, but can saturate the intensity colorspace. Default is 1.0. - - *threshold*: Any edge above this threshold will be black, and anything below white. Ranges from 0.0 to 1.0, with 0.8 as the default - -- **GPUImageCannyEdgeDetectionFilter**: This uses the full Canny process to highlight one-pixel-wide edges - - *texelWidth*: - - *texelHeight*: These parameters affect the visibility of the detected edges - - *blurRadiusInPixels*: The underlying blur radius for the Gaussian blur. Default is 2.0. - - *blurTexelSpacingMultiplier*: The underlying blur texel spacing multiplier. Default is 1.0. - - *upperThreshold*: Any edge with a gradient magnitude above this threshold will pass and show up in the final result. Default is 0.4. - - *lowerThreshold*: Any edge with a gradient magnitude below this threshold will fail and be removed from the final result. Default is 0.1. - -- **GPUImageHarrisCornerDetectionFilter**: Runs the Harris corner detection algorithm on an input image, and produces an image with those corner points as white pixels and everything else black. The cornersDetectedBlock can be set, and you will be provided with a list of corners (in normalized 0..1 X, Y coordinates) within that callback for whatever additional operations you want to perform. - - *blurRadiusInPixels*: The radius of the underlying Gaussian blur. The default is 2.0. - - *sensitivity*: An internal scaling factor applied to adjust the dynamic range of the cornerness maps generated in the filter. The default is 5.0. - - *threshold*: The threshold at which a point is detected as a corner. This can vary significantly based on the size, lighting conditions, and iOS device camera type, so it might take a little experimentation to get right for your cases. Default is 0.20. - -- **GPUImageNobleCornerDetectionFilter**: Runs the Noble variant on the Harris corner detector. It behaves as described above for the Harris detector. - - *blurRadiusInPixels*: The radius of the underlying Gaussian blur. The default is 2.0. - - *sensitivity*: An internal scaling factor applied to adjust the dynamic range of the cornerness maps generated in the filter. The default is 5.0. - - *threshold*: The threshold at which a point is detected as a corner. This can vary significantly based on the size, lighting conditions, and iOS device camera type, so it might take a little experimentation to get right for your cases. Default is 0.2. - -- **GPUImageShiTomasiCornerDetectionFilter**: Runs the Shi-Tomasi feature detector. It behaves as described above for the Harris detector. - - *blurRadiusInPixels*: The radius of the underlying Gaussian blur. The default is 2.0. - - *sensitivity*: An internal scaling factor applied to adjust the dynamic range of the cornerness maps generated in the filter. The default is 1.5. - - *threshold*: The threshold at which a point is detected as a corner. This can vary significantly based on the size, lighting conditions, and iOS device camera type, so it might take a little experimentation to get right for your cases. Default is 0.2. - -- **GPUImageNonMaximumSuppressionFilter**: Currently used only as part of the Harris corner detection filter, this will sample a 1-pixel box around each pixel and determine if the center pixel's red channel is the maximum in that area. If it is, it stays. If not, it is set to 0 for all color components. - -- **GPUImageXYDerivativeFilter**: An internal component within the Harris corner detection filter, this calculates the squared difference between the pixels to the left and right of this one, the squared difference of the pixels above and below this one, and the product of those two differences. - -- **GPUImageCrosshairGenerator**: This draws a series of crosshairs on an image, most often used for identifying machine vision features. It does not take in a standard image like other filters, but a series of points in its -renderCrosshairsFromArray:count: method, which does the actual drawing. You will need to force this filter to render at the particular output size you need. - - *crosshairWidth*: The width, in pixels, of the crosshairs to be drawn onscreen. - -- **GPUImageDilationFilter**: This performs an image dilation operation, where the maximum intensity of the red channel in a rectangular neighborhood is used for the intensity of this pixel. The radius of the rectangular area to sample over is specified on initialization, with a range of 1-4 pixels. This is intended for use with grayscale images, and it expands bright regions. - -- **GPUImageRGBDilationFilter**: This is the same as the GPUImageDilationFilter, except that this acts on all color channels, not just the red channel. - -- **GPUImageErosionFilter**: This performs an image erosion operation, where the minimum intensity of the red channel in a rectangular neighborhood is used for the intensity of this pixel. The radius of the rectangular area to sample over is specified on initialization, with a range of 1-4 pixels. This is intended for use with grayscale images, and it expands dark regions. - -- **GPUImageRGBErosionFilter**: This is the same as the GPUImageErosionFilter, except that this acts on all color channels, not just the red channel. - -- **GPUImageOpeningFilter**: This performs an erosion on the red channel of an image, followed by a dilation of the same radius. The radius is set on initialization, with a range of 1-4 pixels. This filters out smaller bright regions. - -- **GPUImageRGBOpeningFilter**: This is the same as the GPUImageOpeningFilter, except that this acts on all color channels, not just the red channel. - -- **GPUImageClosingFilter**: This performs a dilation on the red channel of an image, followed by an erosion of the same radius. The radius is set on initialization, with a range of 1-4 pixels. This filters out smaller dark regions. - -- **GPUImageRGBClosingFilter**: This is the same as the GPUImageClosingFilter, except that this acts on all color channels, not just the red channel. - -- **GPUImageLocalBinaryPatternFilter**: This performs a comparison of intensity of the red channel of the 8 surrounding pixels and that of the central one, encoding the comparison results in a bit string that becomes this pixel intensity. The least-significant bit is the top-right comparison, going counterclockwise to end at the right comparison as the most significant bit. - -- **GPUImageLowPassFilter**: This applies a low pass filter to incoming video frames. This basically accumulates a weighted rolling average of previous frames with the current ones as they come in. This can be used to denoise video, add motion blur, or be used to create a high pass filter. - - *filterStrength*: This controls the degree by which the previous accumulated frames are blended with the current one. This ranges from 0.0 to 1.0, with a default of 0.5. - -- **GPUImageHighPassFilter**: This applies a high pass filter to incoming video frames. This is the inverse of the low pass filter, showing the difference between the current frame and the weighted rolling average of previous ones. This is most useful for motion detection. - - *filterStrength*: This controls the degree by which the previous accumulated frames are blended and then subtracted from the current one. This ranges from 0.0 to 1.0, with a default of 0.5. - -- **GPUImageMotionDetector**: This is a motion detector based on a high-pass filter. You set the motionDetectionBlock and on every incoming frame it will give you the centroid of any detected movement in the scene (in normalized X,Y coordinates) as well as an intensity of motion for the scene. - - *lowPassFilterStrength*: This controls the strength of the low pass filter used behind the scenes to establish the baseline that incoming frames are compared with. This ranges from 0.0 to 1.0, with a default of 0.5. - -- **GPUImageHoughTransformLineDetector**: Detects lines in the image using a Hough transform into parallel coordinate space. This approach is based entirely on the PC lines process developed by the Graph@FIT research group at the Brno University of Technology and described in their publications: M. Dubská, J. Havel, and A. Herout. Real-Time Detection of Lines using Parallel Coordinates and OpenGL. Proceedings of SCCG 2011, Bratislava, SK, p. 7 (http://medusa.fit.vutbr.cz/public/data/papers/2011-SCCG-Dubska-Real-Time-Line-Detection-Using-PC-and-OpenGL.pdf) and M. Dubská, J. Havel, and A. Herout. PClines — Line detection using parallel coordinates. 2011 IEEE Conference on Computer Vision and Pattern Recognition (CVPR), p. 1489- 1494 (http://medusa.fit.vutbr.cz/public/data/papers/2011-CVPR-Dubska-PClines.pdf). - - *edgeThreshold*: A threshold value for which a point is detected as belonging to an edge for determining lines. Default is 0.9. - - *lineDetectionThreshold*: A threshold value for which a local maximum is detected as belonging to a line in parallel coordinate space. Default is 0.20. - - *linesDetectedBlock*: This block is called on the detection of lines, usually on every processed frame. A C array containing normalized slopes and intercepts in m, b pairs (y=mx+b) is passed in, along with a count of the number of lines detected and the current timestamp of the video frame. - -- **GPUImageLineGenerator**: A helper class that generates lines which can overlay the scene. The color of these lines can be adjusted using -setLineColorRed:green:blue: - - *lineWidth*: The width of the lines, in pixels, with a default of 1.0. - -- **GPUImageMotionBlurFilter**: Applies a directional motion blur to an image - - *blurSize*: A multiplier for the blur size, ranging from 0.0 on up, with a default of 1.0 - - *blurAngle*: The angular direction of the blur, in degrees. 0 degrees by default. - -- **GPUImageZoomBlurFilter**: Applies a directional motion blur to an image - - *blurSize*: A multiplier for the blur size, ranging from 0.0 on up, with a default of 1.0 - - *blurCenter*: The normalized center of the blur. (0.5, 0.5) by default - -### Blending modes ### - -- **GPUImageChromaKeyBlendFilter**: Selectively replaces a color in the first image with the second image - - *thresholdSensitivity*: How close a color match needs to exist to the target color to be replaced (default of 0.4) - - *smoothing*: How smoothly to blend for the color match (default of 0.1) - -- **GPUImageDissolveBlendFilter**: Applies a dissolve blend of two images - - *mix*: The degree with which the second image overrides the first (0.0 - 1.0, with 0.5 as the default) - -- **GPUImageMultiplyBlendFilter**: Applies a multiply blend of two images - -- **GPUImageAddBlendFilter**: Applies an additive blend of two images - -- **GPUImageSubtractBlendFilter**: Applies a subtractive blend of two images - -- **GPUImageDivideBlendFilter**: Applies a division blend of two images - -- **GPUImageOverlayBlendFilter**: Applies an overlay blend of two images - -- **GPUImageDarkenBlendFilter**: Blends two images by taking the minimum value of each color component between the images - -- **GPUImageLightenBlendFilter**: Blends two images by taking the maximum value of each color component between the images - -- **GPUImageColorBurnBlendFilter**: Applies a color burn blend of two images - -- **GPUImageColorDodgeBlendFilter**: Applies a color dodge blend of two images - -- **GPUImageScreenBlendFilter**: Applies a screen blend of two images - -- **GPUImageExclusionBlendFilter**: Applies an exclusion blend of two images - -- **GPUImageDifferenceBlendFilter**: Applies a difference blend of two images - -- **GPUImageHardLightBlendFilter**: Applies a hard light blend of two images - -- **GPUImageSoftLightBlendFilter**: Applies a soft light blend of two images - -- **GPUImageAlphaBlendFilter**: Blends the second image over the first, based on the second's alpha channel - - *mix*: The degree with which the second image overrides the first (0.0 - 1.0, with 1.0 as the default) - -- **GPUImageSourceOverBlendFilter**: Applies a source over blend of two images - -- **GPUImageColorBurnBlendFilter**: Applies a color burn blend of two images - -- **GPUImageColorDodgeBlendFilter**: Applies a color dodge blend of two images - -- **GPUImageNormalBlendFilter**: Applies a normal blend of two images - -- **GPUImageColorBlendFilter**: Applies a color blend of two images - -- **GPUImageHueBlendFilter**: Applies a hue blend of two images - -- **GPUImageSaturationBlendFilter**: Applies a saturation blend of two images - -- **GPUImageLuminosityBlendFilter**: Applies a luminosity blend of two images - -- **GPUImageLinearBurnBlendFilter**: Applies a linear burn blend of two images - -- **GPUImagePoissonBlendFilter**: Applies a Poisson blend of two images - - *mix*: Mix ranges from 0.0 (only image 1) to 1.0 (only image 2 gradients), with 1.0 as the normal level - - *numIterations*: The number of times to propagate the gradients. Crank this up to 100 or even 1000 if you want to get anywhere near convergence. Yes, this will be slow. - -- **GPUImageMaskFilter**: Masks one image using another - -### Visual effects ### - -- **GPUImagePixellateFilter**: Applies a pixellation effect on an image or video - - *fractionalWidthOfAPixel*: How large the pixels are, as a fraction of the width and height of the image (0.0 - 1.0, default 0.05) - -- **GPUImagePolarPixellateFilter**: Applies a pixellation effect on an image or video, based on polar coordinates instead of Cartesian ones - - *center*: The center about which to apply the pixellation, defaulting to (0.5, 0.5) - - *pixelSize*: The fractional pixel size, split into width and height components. The default is (0.05, 0.05) - -- **GPUImagePolkaDotFilter**: Breaks an image up into colored dots within a regular grid - - *fractionalWidthOfAPixel*: How large the dots are, as a fraction of the width and height of the image (0.0 - 1.0, default 0.05) - - *dotScaling*: What fraction of each grid space is taken up by a dot, from 0.0 to 1.0 with a default of 0.9. - -- **GPUImageHalftoneFilter**: Applies a halftone effect to an image, like news print - - *fractionalWidthOfAPixel*: How large the halftone dots are, as a fraction of the width and height of the image (0.0 - 1.0, default 0.05) - -- **GPUImageCrosshatchFilter**: This converts an image into a black-and-white crosshatch pattern - - *crossHatchSpacing*: The fractional width of the image to use as the spacing for the crosshatch. The default is 0.03. - - *lineWidth*: A relative width for the crosshatch lines. The default is 0.003. - -- **GPUImageSketchFilter**: Converts video to look like a sketch. This is just the Sobel edge detection filter with the colors inverted - - *texelWidth*: - - *texelHeight*: These parameters affect the visibility of the detected edges - - *edgeStrength*: Adjusts the dynamic range of the filter. Higher values lead to stronger edges, but can saturate the intensity colorspace. Default is 1.0. - -- **GPUImageThresholdSketchFilter**: Same as the sketch filter, only the edges are thresholded instead of being grayscale - - *texelWidth*: - - *texelHeight*: These parameters affect the visibility of the detected edges - - *edgeStrength*: Adjusts the dynamic range of the filter. Higher values lead to stronger edges, but can saturate the intensity colorspace. Default is 1.0. - - *threshold*: Any edge above this threshold will be black, and anything below white. Ranges from 0.0 to 1.0, with 0.8 as the default - -- **GPUImageToonFilter**: This uses Sobel edge detection to place a black border around objects, and then it quantizes the colors present in the image to give a cartoon-like quality to the image. - - *texelWidth*: - - *texelHeight*: These parameters affect the visibility of the detected edges - - *threshold*: The sensitivity of the edge detection, with lower values being more sensitive. Ranges from 0.0 to 1.0, with 0.2 as the default - - *quantizationLevels*: The number of color levels to represent in the final image. Default is 10.0 - -- **GPUImageSmoothToonFilter**: This uses a similar process as the GPUImageToonFilter, only it precedes the toon effect with a Gaussian blur to smooth out noise. - - *texelWidth*: - - *texelHeight*: These parameters affect the visibility of the detected edges - - *blurRadiusInPixels*: The radius of the underlying Gaussian blur. The default is 2.0. - - *threshold*: The sensitivity of the edge detection, with lower values being more sensitive. Ranges from 0.0 to 1.0, with 0.2 as the default - - *quantizationLevels*: The number of color levels to represent in the final image. Default is 10.0 - -- **GPUImageEmbossFilter**: Applies an embossing effect on the image - - *intensity*: The strength of the embossing, from 0.0 to 4.0, with 1.0 as the normal level - -- **GPUImagePosterizeFilter**: This reduces the color dynamic range into the number of steps specified, leading to a cartoon-like simple shading of the image. - - *colorLevels*: The number of color levels to reduce the image space to. This ranges from 1 to 256, with a default of 10. - -- **GPUImageSwirlFilter**: Creates a swirl distortion on the image - - *radius*: The radius from the center to apply the distortion, with a default of 0.5 - - *center*: The center of the image (in normalized coordinates from 0 - 1.0) about which to twist, with a default of (0.5, 0.5) - - *angle*: The amount of twist to apply to the image, with a default of 1.0 - -- **GPUImageBulgeDistortionFilter**: Creates a bulge distortion on the image - - *radius*: The radius from the center to apply the distortion, with a default of 0.25 - - *center*: The center of the image (in normalized coordinates from 0 - 1.0) about which to distort, with a default of (0.5, 0.5) - - *scale*: The amount of distortion to apply, from -1.0 to 1.0, with a default of 0.5 - -- **GPUImagePinchDistortionFilter**: Creates a pinch distortion of the image - - *radius*: The radius from the center to apply the distortion, with a default of 1.0 - - *center*: The center of the image (in normalized coordinates from 0 - 1.0) about which to distort, with a default of (0.5, 0.5) - - *scale*: The amount of distortion to apply, from -2.0 to 2.0, with a default of 1.0 - -- **GPUImageStretchDistortionFilter**: Creates a stretch distortion of the image - - *center*: The center of the image (in normalized coordinates from 0 - 1.0) about which to distort, with a default of (0.5, 0.5) - -- **GPUImageSphereRefractionFilter**: Simulates the refraction through a glass sphere - - *center*: The center about which to apply the distortion, with a default of (0.5, 0.5) - - *radius*: The radius of the distortion, ranging from 0.0 to 1.0, with a default of 0.25 - - *refractiveIndex*: The index of refraction for the sphere, with a default of 0.71 - -- **GPUImageGlassSphereFilter**: Same as the GPUImageSphereRefractionFilter, only the image is not inverted and there's a little bit of frosting at the edges of the glass - - *center*: The center about which to apply the distortion, with a default of (0.5, 0.5) - - *radius*: The radius of the distortion, ranging from 0.0 to 1.0, with a default of 0.25 - - *refractiveIndex*: The index of refraction for the sphere, with a default of 0.71 - -- **GPUImageVignetteFilter**: Performs a vignetting effect, fading out the image at the edges - - *x*: - - *y*: The directional intensity of the vignetting, with a default of x = 0.75, y = 0.5 - -- **GPUImageKuwaharaFilter**: Kuwahara image abstraction, drawn from the work of Kyprianidis, et. al. in their publication "Anisotropic Kuwahara Filtering on the GPU" within the GPU Pro collection. This produces an oil-painting-like image, but it is extremely computationally expensive, so it can take seconds to render a frame on an iPad 2. This might be best used for still images. - - *radius*: In integer specifying the number of pixels out from the center pixel to test when applying the filter, with a default of 4. A higher value creates a more abstracted image, but at the cost of much greater processing time. - -- **GPUImageKuwaharaRadius3Filter**: A modified version of the Kuwahara filter, optimized to work over just a radius of three pixels - -- **GPUImagePerlinNoiseFilter**: Generates an image full of Perlin noise - - *colorStart*: - - *colorFinish*: The color range for the noise being generated - - *scale*: The scaling of the noise being generated - -- **GPUImageCGAColorspaceFilter**: Simulates the colorspace of a CGA monitor - -- **GPUImageMosaicFilter**: This filter takes an input tileset, the tiles must ascend in luminance. It looks at the input image and replaces each display tile with an input tile according to the luminance of that tile. The idea was to replicate the ASCII video filters seen in other apps, but the tileset can be anything. - - *inputTileSize*: - - *numTiles*: - - *displayTileSize*: - - *colorOn*: - -- **GPUImageJFAVoronoiFilter**: Generates a Voronoi map, for use in a later stage. - - *sizeInPixels*: Size of the individual elements - -- **GPUImageVoronoiConsumerFilter**: Takes in the Voronoi map, and uses that to filter an incoming image. - - *sizeInPixels*: Size of the individual elements - -You can also easily write your own custom filters using the C-like OpenGL Shading Language, as described above. - -## Sample applications ## - -Several sample applications are bundled with the framework source. Most are compatible with both iPhone and iPad-class devices. They attempt to show off various aspects of the framework and should be used as the best examples of the API while the framework is under development. These include: - -### SimpleImageFilter ### - -A bundled JPEG image is loaded into the application at launch, a filter is applied to it, and the result rendered to the screen. Additionally, this sample shows two ways of taking in an image, filtering it, and saving it to disk. - -### SimpleVideoFilter ### - -A pixellate filter is applied to a live video stream, with a UISlider control that lets you adjust the pixel size on the live video. - -### SimpleVideoFileFilter ### - -A movie file is loaded from disk, an unsharp mask filter is applied to it, and the filtered result is re-encoded as another movie. - -### MultiViewFilterExample ### - -From a single camera feed, four views are populated with realtime filters applied to camera. One is just the straight camera video, one is a preprogrammed sepia tone, and two are custom filters based on shader programs. - -### FilterShowcase ### - -This demonstrates every filter supplied with GPUImage. - -### BenchmarkSuite ### - -This is used to test the performance of the overall framework by testing it against CPU-bound routines and Core Image. Benchmarks involving still images and video are run against all three, with results displayed in-application. - -### CubeExample ### - -This demonstrates the ability of GPUImage to interact with OpenGL ES rendering. Frames are captured from the camera, a sepia filter applied to them, and then they are fed into a texture to be applied to the face of a cube you can rotate with your finger. This cube in turn is rendered to a texture-backed framebuffer object, and that texture is fed back into GPUImage to have a pixellation filter applied to it before rendering to screen. - -In other words, the path of this application is camera -> sepia tone filter -> cube -> pixellation filter -> display. - -### ColorObjectTracking ### - -A version of my ColorTracking example from http://www.sunsetlakesoftware.com/2010/10/22/gpu-accelerated-video-processing-mac-and-ios ported across to use GPUImage, this application uses color in a scene to track objects from a live camera feed. The four views you can switch between include the raw camera feed, the camera feed with pixels matching the color threshold in white, the processed video where positions are encoded as colors within the pixels passing the threshold test, and finally the live video feed with a dot that tracks the selected color. Tapping the screen changes the color to track to match the color of the pixels under your finger. Tapping and dragging on the screen makes the color threshold more or less forgiving. This is most obvious on the second, color thresholding view. - -Currently, all processing for the color averaging in the last step is done on the CPU, so this is part is extremely slow. diff --git a/iOS_Tips/Pods/GPUImage/framework/Resources/lookup.png b/iOS_Tips/Pods/GPUImage/framework/Resources/lookup.png deleted file mode 100644 index ed814dfbb648c1f43d737c302f94aa8ca04c27e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2095 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 V#`AB@xp)BF%uFndpBp*f`xj2m*0KNq diff --git a/iOS_Tips/Pods/GPUImage/framework/Resources/lookup_miss_etikate.png b/iOS_Tips/Pods/GPUImage/framework/Resources/lookup_miss_etikate.png deleted file mode 100644 index e1317d7819b051663709c484c7b8c773e95ed6d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 202596 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 z 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 z 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 WB=3q diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GLProgram.h b/iOS_Tips/Pods/GPUImage/framework/Source/GLProgram.h deleted file mode 100755 index cd455e71..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GLProgram.h +++ /dev/null @@ -1,42 +0,0 @@ -// This is Jeff LaMarche's GLProgram OpenGL shader wrapper class from his OpenGL ES 2.0 book. -// A description of this can be found at his page on the topic: -// http://iphonedevelopment.blogspot.com/2010/11/opengl-es-20-for-ios-chapter-4.html -// I've extended this to be able to take programs as NSStrings in addition to files, for baked-in shaders - -#import - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -#import -#import -#else -#import -#import -#endif - -@interface GLProgram : NSObject -{ - NSMutableArray *attributes; - NSMutableArray *uniforms; - GLuint program, - vertShader, - fragShader; -} - -@property(readwrite, nonatomic) BOOL initialized; -@property(readwrite, copy, nonatomic) NSString *vertexShaderLog; -@property(readwrite, copy, nonatomic) NSString *fragmentShaderLog; -@property(readwrite, copy, nonatomic) NSString *programLog; - -- (id)initWithVertexShaderString:(NSString *)vShaderString - fragmentShaderString:(NSString *)fShaderString; -- (id)initWithVertexShaderString:(NSString *)vShaderString - fragmentShaderFilename:(NSString *)fShaderFilename; -- (id)initWithVertexShaderFilename:(NSString *)vShaderFilename - fragmentShaderFilename:(NSString *)fShaderFilename; -- (void)addAttribute:(NSString *)attributeName; -- (GLuint)attributeIndex:(NSString *)attributeName; -- (GLuint)uniformIndex:(NSString *)uniformName; -- (BOOL)link; -- (void)use; -- (void)validate; -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GLProgram.m b/iOS_Tips/Pods/GPUImage/framework/Source/GLProgram.m deleted file mode 100755 index 105d75fe..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GLProgram.m +++ /dev/null @@ -1,236 +0,0 @@ -// This is Jeff LaMarche's GLProgram OpenGL shader wrapper class from his OpenGL ES 2.0 book. -// A description of this can be found at his page on the topic: -// http://iphonedevelopment.blogspot.com/2010/11/opengl-es-20-for-ios-chapter-4.html - - -#import "GLProgram.h" -// START:typedefs -#pragma mark Function Pointer Definitions -typedef void (*GLInfoFunction)(GLuint program, GLenum pname, GLint* params); -typedef void (*GLLogFunction) (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog); -// END:typedefs -#pragma mark - -#pragma mark Private Extension Method Declaration -// START:extension -@interface GLProgram() - -- (BOOL)compileShader:(GLuint *)shader - type:(GLenum)type - string:(NSString *)shaderString; -@end -// END:extension -#pragma mark - - -@implementation GLProgram -// START:init - -@synthesize initialized = _initialized; - -- (id)initWithVertexShaderString:(NSString *)vShaderString - fragmentShaderString:(NSString *)fShaderString; -{ - if ((self = [super init])) - { - _initialized = NO; - - attributes = [[NSMutableArray alloc] init]; - uniforms = [[NSMutableArray alloc] init]; - program = glCreateProgram(); - - if (![self compileShader:&vertShader - type:GL_VERTEX_SHADER - string:vShaderString]) - { - NSLog(@"Failed to compile vertex shader"); - } - - // Create and compile fragment shader - if (![self compileShader:&fragShader - type:GL_FRAGMENT_SHADER - string:fShaderString]) - { - NSLog(@"Failed to compile fragment shader"); - } - - glAttachShader(program, vertShader); - glAttachShader(program, fragShader); - } - - return self; -} - -- (id)initWithVertexShaderString:(NSString *)vShaderString - fragmentShaderFilename:(NSString *)fShaderFilename; -{ - NSString *fragShaderPathname = [[NSBundle mainBundle] pathForResource:fShaderFilename ofType:@"fsh"]; - NSString *fragmentShaderString = [NSString stringWithContentsOfFile:fragShaderPathname encoding:NSUTF8StringEncoding error:nil]; - - if ((self = [self initWithVertexShaderString:vShaderString fragmentShaderString:fragmentShaderString])) - { - } - - return self; -} - -- (id)initWithVertexShaderFilename:(NSString *)vShaderFilename - fragmentShaderFilename:(NSString *)fShaderFilename; -{ - NSString *vertShaderPathname = [[NSBundle mainBundle] pathForResource:vShaderFilename ofType:@"vsh"]; - NSString *vertexShaderString = [NSString stringWithContentsOfFile:vertShaderPathname encoding:NSUTF8StringEncoding error:nil]; - - NSString *fragShaderPathname = [[NSBundle mainBundle] pathForResource:fShaderFilename ofType:@"fsh"]; - NSString *fragmentShaderString = [NSString stringWithContentsOfFile:fragShaderPathname encoding:NSUTF8StringEncoding error:nil]; - - if ((self = [self initWithVertexShaderString:vertexShaderString fragmentShaderString:fragmentShaderString])) - { - } - - return self; -} -// END:init -// START:compile -- (BOOL)compileShader:(GLuint *)shader - type:(GLenum)type - string:(NSString *)shaderString -{ -// CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); - - GLint status; - const GLchar *source; - - source = - (GLchar *)[shaderString UTF8String]; - if (!source) - { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - - if (status != GL_TRUE) - { - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) - { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - if (shader == &vertShader) - { - self.vertexShaderLog = [NSString stringWithFormat:@"%s", log]; - } - else - { - self.fragmentShaderLog = [NSString stringWithFormat:@"%s", log]; - } - - free(log); - } - } - -// CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime); -// NSLog(@"Compiled in %f ms", linkTime * 1000.0); - - return status == GL_TRUE; -} -// END:compile -#pragma mark - -// START:addattribute -- (void)addAttribute:(NSString *)attributeName -{ - if (![attributes containsObject:attributeName]) - { - [attributes addObject:attributeName]; - glBindAttribLocation(program, - (GLuint)[attributes indexOfObject:attributeName], - [attributeName UTF8String]); - } -} -// END:addattribute -// START:indexmethods -- (GLuint)attributeIndex:(NSString *)attributeName -{ - return (GLuint)[attributes indexOfObject:attributeName]; -} -- (GLuint)uniformIndex:(NSString *)uniformName -{ - return glGetUniformLocation(program, [uniformName UTF8String]); -} -// END:indexmethods -#pragma mark - -// START:link -- (BOOL)link -{ -// CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); - - GLint status; - - glLinkProgram(program); - - glGetProgramiv(program, GL_LINK_STATUS, &status); - if (status == GL_FALSE) - return NO; - - if (vertShader) - { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) - { - glDeleteShader(fragShader); - fragShader = 0; - } - - self.initialized = YES; - -// CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime); -// NSLog(@"Linked in %f ms", linkTime * 1000.0); - - return YES; -} -// END:link -// START:use -- (void)use -{ - glUseProgram(program); -} -// END:use -#pragma mark - - -- (void)validate; -{ - GLint logLength; - - glValidateProgram(program); - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) - { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(program, logLength, &logLength, log); - self.programLog = [NSString stringWithFormat:@"%s", log]; - free(log); - } -} - -#pragma mark - -// START:dealloc -- (void)dealloc -{ - if (vertShader) - glDeleteShader(vertShader); - - if (fragShader) - glDeleteShader(fragShader); - - if (program) - glDeleteProgram(program); - -} -// END:dealloc -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImage.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImage.h deleted file mode 100755 index f7e96b36..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImage.h +++ /dev/null @@ -1,164 +0,0 @@ -#import "GLProgram.h" - -// Base classes -#import "GPUImageContext.h" -#import "GPUImageOutput.h" -#import "GPUImageView.h" -#import "GPUImageVideoCamera.h" -#import "GPUImageStillCamera.h" -#import "GPUImageMovie.h" -#import "GPUImagePicture.h" -#import "GPUImageRawDataInput.h" -#import "GPUImageRawDataOutput.h" -#import "GPUImageMovieWriter.h" -#import "GPUImageFilterPipeline.h" -#import "GPUImageTextureOutput.h" -#import "GPUImageFilterGroup.h" -#import "GPUImageTextureInput.h" -#import "GPUImageUIElement.h" -#import "GPUImageBuffer.h" -#import "GPUImageFramebuffer.h" -#import "GPUImageFramebufferCache.h" - -// Filters -#import "GPUImageFilter.h" -#import "GPUImageTwoInputFilter.h" -#import "GPUImagePixellateFilter.h" -#import "GPUImagePixellatePositionFilter.h" -#import "GPUImageSepiaFilter.h" -#import "GPUImageColorInvertFilter.h" -#import "GPUImageSaturationFilter.h" -#import "GPUImageContrastFilter.h" -#import "GPUImageExposureFilter.h" -#import "GPUImageBrightnessFilter.h" -#import "GPUImageLevelsFilter.h" -#import "GPUImageSharpenFilter.h" -#import "GPUImageGammaFilter.h" -#import "GPUImageSobelEdgeDetectionFilter.h" -#import "GPUImageSketchFilter.h" -#import "GPUImageToonFilter.h" -#import "GPUImageSmoothToonFilter.h" -#import "GPUImageMultiplyBlendFilter.h" -#import "GPUImageDissolveBlendFilter.h" -#import "GPUImageKuwaharaFilter.h" -#import "GPUImageKuwaharaRadius3Filter.h" -#import "GPUImageVignetteFilter.h" -#import "GPUImageGaussianBlurFilter.h" -#import "GPUImageGaussianBlurPositionFilter.h" -#import "GPUImageGaussianSelectiveBlurFilter.h" -#import "GPUImageOverlayBlendFilter.h" -#import "GPUImageDarkenBlendFilter.h" -#import "GPUImageLightenBlendFilter.h" -#import "GPUImageSwirlFilter.h" -#import "GPUImageSourceOverBlendFilter.h" -#import "GPUImageColorBurnBlendFilter.h" -#import "GPUImageColorDodgeBlendFilter.h" -#import "GPUImageScreenBlendFilter.h" -#import "GPUImageExclusionBlendFilter.h" -#import "GPUImageDifferenceBlendFilter.h" -#import "GPUImageSubtractBlendFilter.h" -#import "GPUImageHardLightBlendFilter.h" -#import "GPUImageSoftLightBlendFilter.h" -#import "GPUImageColorBlendFilter.h" -#import "GPUImageHueBlendFilter.h" -#import "GPUImageSaturationBlendFilter.h" -#import "GPUImageLuminosityBlendFilter.h" -#import "GPUImageCropFilter.h" -#import "GPUImageGrayscaleFilter.h" -#import "GPUImageTransformFilter.h" -#import "GPUImageChromaKeyBlendFilter.h" -#import "GPUImageHazeFilter.h" -#import "GPUImageLuminanceThresholdFilter.h" -#import "GPUImagePosterizeFilter.h" -#import "GPUImageBoxBlurFilter.h" -#import "GPUImageAdaptiveThresholdFilter.h" -#import "GPUImageUnsharpMaskFilter.h" -#import "GPUImageBulgeDistortionFilter.h" -#import "GPUImagePinchDistortionFilter.h" -#import "GPUImageCrosshatchFilter.h" -#import "GPUImageCGAColorspaceFilter.h" -#import "GPUImagePolarPixellateFilter.h" -#import "GPUImageStretchDistortionFilter.h" -#import "GPUImagePerlinNoiseFilter.h" -#import "GPUImageJFAVoronoiFilter.h" -#import "GPUImageVoronoiConsumerFilter.h" -#import "GPUImageMosaicFilter.h" -#import "GPUImageTiltShiftFilter.h" -#import "GPUImage3x3ConvolutionFilter.h" -#import "GPUImageEmbossFilter.h" -#import "GPUImageCannyEdgeDetectionFilter.h" -#import "GPUImageThresholdEdgeDetectionFilter.h" -#import "GPUImageMaskFilter.h" -#import "GPUImageHistogramFilter.h" -#import "GPUImageHistogramGenerator.h" -#import "GPUImageHistogramEqualizationFilter.h" -#import "GPUImagePrewittEdgeDetectionFilter.h" -#import "GPUImageXYDerivativeFilter.h" -#import "GPUImageHarrisCornerDetectionFilter.h" -#import "GPUImageAlphaBlendFilter.h" -#import "GPUImageNormalBlendFilter.h" -#import "GPUImageNonMaximumSuppressionFilter.h" -#import "GPUImageRGBFilter.h" -#import "GPUImageMedianFilter.h" -#import "GPUImageBilateralFilter.h" -#import "GPUImageCrosshairGenerator.h" -#import "GPUImageToneCurveFilter.h" -#import "GPUImageNobleCornerDetectionFilter.h" -#import "GPUImageShiTomasiFeatureDetectionFilter.h" -#import "GPUImageErosionFilter.h" -#import "GPUImageRGBErosionFilter.h" -#import "GPUImageDilationFilter.h" -#import "GPUImageRGBDilationFilter.h" -#import "GPUImageOpeningFilter.h" -#import "GPUImageRGBOpeningFilter.h" -#import "GPUImageClosingFilter.h" -#import "GPUImageRGBClosingFilter.h" -#import "GPUImageColorPackingFilter.h" -#import "GPUImageSphereRefractionFilter.h" -#import "GPUImageMonochromeFilter.h" -#import "GPUImageOpacityFilter.h" -#import "GPUImageHighlightShadowFilter.h" -#import "GPUImageFalseColorFilter.h" -#import "GPUImageHSBFilter.h" -#import "GPUImageHueFilter.h" -#import "GPUImageGlassSphereFilter.h" -#import "GPUImageLookupFilter.h" -#import "GPUImageAmatorkaFilter.h" -#import "GPUImageMissEtikateFilter.h" -#import "GPUImageSoftEleganceFilter.h" -#import "GPUImageAddBlendFilter.h" -#import "GPUImageDivideBlendFilter.h" -#import "GPUImagePolkaDotFilter.h" -#import "GPUImageLocalBinaryPatternFilter.h" -#import "GPUImageLanczosResamplingFilter.h" -#import "GPUImageAverageColor.h" -#import "GPUImageSolidColorGenerator.h" -#import "GPUImageLuminosity.h" -#import "GPUImageAverageLuminanceThresholdFilter.h" -#import "GPUImageWhiteBalanceFilter.h" -#import "GPUImageChromaKeyFilter.h" -#import "GPUImageLowPassFilter.h" -#import "GPUImageHighPassFilter.h" -#import "GPUImageMotionDetector.h" -#import "GPUImageHalftoneFilter.h" -#import "GPUImageThresholdedNonMaximumSuppressionFilter.h" -#import "GPUImageHoughTransformLineDetector.h" -#import "GPUImageParallelCoordinateLineTransformFilter.h" -#import "GPUImageThresholdSketchFilter.h" -#import "GPUImageLineGenerator.h" -#import "GPUImageLinearBurnBlendFilter.h" -#import "GPUImageGaussianBlurPositionFilter.h" -#import "GPUImagePixellatePositionFilter.h" -#import "GPUImageTwoInputCrossTextureSamplingFilter.h" -#import "GPUImagePoissonBlendFilter.h" -#import "GPUImageMotionBlurFilter.h" -#import "GPUImageZoomBlurFilter.h" -#import "GPUImageLaplacianFilter.h" -#import "GPUImageiOSBlurFilter.h" -#import "GPUImageLuminanceRangeFilter.h" -#import "GPUImageDirectionalNonMaximumSuppressionFilter.h" -#import "GPUImageDirectionalSobelEdgeDetectionFilter.h" -#import "GPUImageSingleComponentGaussianBlurFilter.h" -#import "GPUImageThreeInputFilter.h" -#import "GPUImageWeakPixelInclusionFilter.h" - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImage3x3ConvolutionFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImage3x3ConvolutionFilter.h deleted file mode 100755 index 67e68def..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImage3x3ConvolutionFilter.h +++ /dev/null @@ -1,18 +0,0 @@ -#import "GPUImage3x3TextureSamplingFilter.h" - -/** Runs a 3x3 convolution kernel against the image - */ -@interface GPUImage3x3ConvolutionFilter : GPUImage3x3TextureSamplingFilter -{ - GLint convolutionMatrixUniform; -} - -/** Convolution kernel to run against the image - - The convolution kernel is a 3x3 matrix of values to apply to the pixel and its 8 surrounding pixels. - The matrix is specified in row-major order, with the top left pixel being one.one and the bottom right three.three - If the values in the matrix don't add up to 1.0, the image could be brightened or darkened. - */ -@property(readwrite, nonatomic) GPUMatrix3x3 convolutionKernel; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImage3x3ConvolutionFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImage3x3ConvolutionFilter.m deleted file mode 100755 index c623ac67..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImage3x3ConvolutionFilter.m +++ /dev/null @@ -1,128 +0,0 @@ -#import "GPUImage3x3ConvolutionFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImage3x3ConvolutionFragmentShaderString = SHADER_STRING -( - precision highp float; - - uniform sampler2D inputImageTexture; - - uniform mediump mat3 convolutionMatrix; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - void main() - { - mediump vec3 bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate).rgb; - mediump vec3 bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate).rgb; - mediump vec3 bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate).rgb; - mediump vec4 centerColor = texture2D(inputImageTexture, textureCoordinate); - mediump vec3 leftColor = texture2D(inputImageTexture, leftTextureCoordinate).rgb; - mediump vec3 rightColor = texture2D(inputImageTexture, rightTextureCoordinate).rgb; - mediump vec3 topColor = texture2D(inputImageTexture, topTextureCoordinate).rgb; - mediump vec3 topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate).rgb; - mediump vec3 topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate).rgb; - - mediump vec3 resultColor = topLeftColor * convolutionMatrix[0][0] + topColor * convolutionMatrix[0][1] + topRightColor * convolutionMatrix[0][2]; - resultColor += leftColor * convolutionMatrix[1][0] + centerColor.rgb * convolutionMatrix[1][1] + rightColor * convolutionMatrix[1][2]; - resultColor += bottomLeftColor * convolutionMatrix[2][0] + bottomColor * convolutionMatrix[2][1] + bottomRightColor * convolutionMatrix[2][2]; - - gl_FragColor = vec4(resultColor, centerColor.a); - } -); -#else -NSString *const kGPUImage3x3ConvolutionFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - - uniform mat3 convolutionMatrix; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - void main() - { - vec3 bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate).rgb; - vec3 bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate).rgb; - vec3 bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate).rgb; - vec4 centerColor = texture2D(inputImageTexture, textureCoordinate); - vec3 leftColor = texture2D(inputImageTexture, leftTextureCoordinate).rgb; - vec3 rightColor = texture2D(inputImageTexture, rightTextureCoordinate).rgb; - vec3 topColor = texture2D(inputImageTexture, topTextureCoordinate).rgb; - vec3 topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate).rgb; - vec3 topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate).rgb; - - vec3 resultColor = topLeftColor * convolutionMatrix[0][0] + topColor * convolutionMatrix[0][1] + topRightColor * convolutionMatrix[0][2]; - resultColor += leftColor * convolutionMatrix[1][0] + centerColor.rgb * convolutionMatrix[1][1] + rightColor * convolutionMatrix[1][2]; - resultColor += bottomLeftColor * convolutionMatrix[2][0] + bottomColor * convolutionMatrix[2][1] + bottomRightColor * convolutionMatrix[2][2]; - - gl_FragColor = vec4(resultColor, centerColor.a); - } -); -#endif - -@implementation GPUImage3x3ConvolutionFilter - -@synthesize convolutionKernel = _convolutionKernel; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [self initWithFragmentShaderFromString:kGPUImage3x3ConvolutionFragmentShaderString])) - { - return nil; - } - - self.convolutionKernel = (GPUMatrix3x3){ - {0.f, 0.f, 0.f}, - {0.f, 1.f, 0.f}, - {0.f, 0.f, 0.f} - }; - - return self; -} - -- (id)initWithFragmentShaderFromString:(NSString *)fragmentShaderString; -{ - if (!(self = [super initWithFragmentShaderFromString:fragmentShaderString])) - { - return nil; - } - - convolutionMatrixUniform = [filterProgram uniformIndex:@"convolutionMatrix"]; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setConvolutionKernel:(GPUMatrix3x3)newValue; -{ - _convolutionKernel = newValue; - - [self setMatrix3f:_convolutionKernel forUniform:convolutionMatrixUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImage3x3TextureSamplingFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImage3x3TextureSamplingFilter.h deleted file mode 100644 index 5599e156..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImage3x3TextureSamplingFilter.h +++ /dev/null @@ -1,18 +0,0 @@ -#import "GPUImageFilter.h" - -extern NSString *const kGPUImageNearbyTexelSamplingVertexShaderString; - -@interface GPUImage3x3TextureSamplingFilter : GPUImageFilter -{ - GLint texelWidthUniform, texelHeightUniform; - - CGFloat texelWidth, texelHeight; - BOOL hasOverriddenImageSizeFactor; -} - -// The texel width and height determines how far out to sample from this texel. By default, this is the normalized width of a pixel, but this can be overridden for different effects. -@property(readwrite, nonatomic) CGFloat texelWidth; -@property(readwrite, nonatomic) CGFloat texelHeight; - - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImage3x3TextureSamplingFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImage3x3TextureSamplingFilter.m deleted file mode 100644 index 05c4d50c..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImage3x3TextureSamplingFilter.m +++ /dev/null @@ -1,121 +0,0 @@ -#import "GPUImage3x3TextureSamplingFilter.h" - -// Override vertex shader to remove dependent texture reads -NSString *const kGPUImageNearbyTexelSamplingVertexShaderString = SHADER_STRING -( - attribute vec4 position; - attribute vec4 inputTextureCoordinate; - - uniform float texelWidth; - uniform float texelHeight; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - void main() - { - gl_Position = position; - - vec2 widthStep = vec2(texelWidth, 0.0); - vec2 heightStep = vec2(0.0, texelHeight); - vec2 widthHeightStep = vec2(texelWidth, texelHeight); - vec2 widthNegativeHeightStep = vec2(texelWidth, -texelHeight); - - textureCoordinate = inputTextureCoordinate.xy; - leftTextureCoordinate = inputTextureCoordinate.xy - widthStep; - rightTextureCoordinate = inputTextureCoordinate.xy + widthStep; - - topTextureCoordinate = inputTextureCoordinate.xy - heightStep; - topLeftTextureCoordinate = inputTextureCoordinate.xy - widthHeightStep; - topRightTextureCoordinate = inputTextureCoordinate.xy + widthNegativeHeightStep; - - bottomTextureCoordinate = inputTextureCoordinate.xy + heightStep; - bottomLeftTextureCoordinate = inputTextureCoordinate.xy - widthNegativeHeightStep; - bottomRightTextureCoordinate = inputTextureCoordinate.xy + widthHeightStep; - } -); - - -@implementation GPUImage3x3TextureSamplingFilter - -@synthesize texelWidth = _texelWidth; -@synthesize texelHeight = _texelHeight; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithVertexShaderFromString:(NSString *)vertexShaderString fragmentShaderFromString:(NSString *)fragmentShaderString; -{ - if (!(self = [super initWithVertexShaderFromString:vertexShaderString fragmentShaderFromString:fragmentShaderString])) - { - return nil; - } - - texelWidthUniform = [filterProgram uniformIndex:@"texelWidth"]; - texelHeightUniform = [filterProgram uniformIndex:@"texelHeight"]; - - return self; -} - -- (id)initWithFragmentShaderFromString:(NSString *)fragmentShaderString; -{ - if (!(self = [self initWithVertexShaderFromString:kGPUImageNearbyTexelSamplingVertexShaderString fragmentShaderFromString:fragmentShaderString])) - { - return nil; - } - - return self; -} - -- (void)setupFilterForSize:(CGSize)filterFrameSize; -{ - if (!hasOverriddenImageSizeFactor) - { - _texelWidth = 1.0 / filterFrameSize.width; - _texelHeight = 1.0 / filterFrameSize.height; - - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext setActiveShaderProgram:filterProgram]; - if (GPUImageRotationSwapsWidthAndHeight(inputRotation)) - { - glUniform1f(texelWidthUniform, _texelHeight); - glUniform1f(texelHeightUniform, _texelWidth); - } - else - { - glUniform1f(texelWidthUniform, _texelWidth); - glUniform1f(texelHeightUniform, _texelHeight); - } - }); - } -} - -#pragma mark - -#pragma mark Accessors - -- (void)setTexelWidth:(CGFloat)newValue; -{ - hasOverriddenImageSizeFactor = YES; - _texelWidth = newValue; - - [self setFloat:_texelWidth forUniform:texelWidthUniform program:filterProgram]; -} - -- (void)setTexelHeight:(CGFloat)newValue; -{ - hasOverriddenImageSizeFactor = YES; - _texelHeight = newValue; - - [self setFloat:_texelHeight forUniform:texelHeightUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAdaptiveThresholdFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAdaptiveThresholdFilter.h deleted file mode 100755 index 32785560..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAdaptiveThresholdFilter.h +++ /dev/null @@ -1,9 +0,0 @@ -#import "GPUImageFilterGroup.h" - -@interface GPUImageAdaptiveThresholdFilter : GPUImageFilterGroup - -/** A multiplier for the background averaging blur radius in pixels, with a default of 4 - */ -@property(readwrite, nonatomic) CGFloat blurRadiusInPixels; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAdaptiveThresholdFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAdaptiveThresholdFilter.m deleted file mode 100755 index 71fa6abf..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAdaptiveThresholdFilter.m +++ /dev/null @@ -1,100 +0,0 @@ -#import "GPUImageAdaptiveThresholdFilter.h" -#import "GPUImageFilter.h" -#import "GPUImageTwoInputFilter.h" -#import "GPUImageGrayscaleFilter.h" -#import "GPUImageBoxBlurFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageAdaptiveThresholdFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - highp float blurredInput = texture2D(inputImageTexture, textureCoordinate).r; - highp float localLuminance = texture2D(inputImageTexture2, textureCoordinate2).r; - highp float thresholdResult = step(blurredInput - 0.05, localLuminance); - - gl_FragColor = vec4(vec3(thresholdResult), 1.0); - } -); -#else -NSString *const kGPUImageAdaptiveThresholdFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - float blurredInput = texture2D(inputImageTexture, textureCoordinate).r; - float localLuminance = texture2D(inputImageTexture2, textureCoordinate2).r; - float thresholdResult = step(blurredInput - 0.05, localLuminance); - - gl_FragColor = vec4(vec3(thresholdResult), 1.0); - } -); -#endif - -@interface GPUImageAdaptiveThresholdFilter() -{ - GPUImageBoxBlurFilter *boxBlurFilter; -} -@end - -@implementation GPUImageAdaptiveThresholdFilter - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super init])) - { - return nil; - } - - // First pass: reduce to luminance - GPUImageGrayscaleFilter *luminanceFilter = [[GPUImageGrayscaleFilter alloc] init]; - [self addFilter:luminanceFilter]; - - // Second pass: perform a box blur - boxBlurFilter = [[GPUImageBoxBlurFilter alloc] init]; - [self addFilter:boxBlurFilter]; - - // Third pass: compare the blurred background luminance to the local value - GPUImageFilter *adaptiveThresholdFilter = [[GPUImageTwoInputFilter alloc] initWithFragmentShaderFromString:kGPUImageAdaptiveThresholdFragmentShaderString]; - [self addFilter:adaptiveThresholdFilter]; - - [luminanceFilter addTarget:boxBlurFilter]; - - [boxBlurFilter addTarget:adaptiveThresholdFilter]; - // To prevent double updating of this filter, disable updates from the sharp luminance image side - [luminanceFilter addTarget:adaptiveThresholdFilter]; - - self.initialFilters = [NSArray arrayWithObject:luminanceFilter]; - self.terminalFilter = adaptiveThresholdFilter; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setBlurRadiusInPixels:(CGFloat)newValue; -{ - boxBlurFilter.blurRadiusInPixels = newValue; -} - -- (CGFloat)blurRadiusInPixels; -{ - return boxBlurFilter.blurRadiusInPixels; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAddBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAddBlendFilter.h deleted file mode 100644 index b14c60c6..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAddBlendFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageAddBlendFilter : GPUImageTwoInputFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAddBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAddBlendFilter.m deleted file mode 100644 index c89054a8..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAddBlendFilter.m +++ /dev/null @@ -1,100 +0,0 @@ -#import "GPUImageAddBlendFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageAddBlendFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - lowp vec4 base = texture2D(inputImageTexture, textureCoordinate); - lowp vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2); - - mediump float r; - if (overlay.r * base.a + base.r * overlay.a >= overlay.a * base.a) { - r = overlay.a * base.a + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a); - } else { - r = overlay.r + base.r; - } - - mediump float g; - if (overlay.g * base.a + base.g * overlay.a >= overlay.a * base.a) { - g = overlay.a * base.a + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a); - } else { - g = overlay.g + base.g; - } - - mediump float b; - if (overlay.b * base.a + base.b * overlay.a >= overlay.a * base.a) { - b = overlay.a * base.a + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a); - } else { - b = overlay.b + base.b; - } - - mediump float a = overlay.a + base.a - overlay.a * base.a; - - gl_FragColor = vec4(r, g, b, a); - } -); -#else -NSString *const kGPUImageAddBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 base = texture2D(inputImageTexture, textureCoordinate); - vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2); - - float r; - if (overlay.r * base.a + base.r * overlay.a >= overlay.a * base.a) { - r = overlay.a * base.a + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a); - } else { - r = overlay.r + base.r; - } - - float g; - if (overlay.g * base.a + base.g * overlay.a >= overlay.a * base.a) { - g = overlay.a * base.a + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a); - } else { - g = overlay.g + base.g; - } - - float b; - if (overlay.b * base.a + base.b * overlay.a >= overlay.a * base.a) { - b = overlay.a * base.a + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a); - } else { - b = overlay.b + base.b; - } - - float a = overlay.a + base.a - overlay.a * base.a; - - gl_FragColor = vec4(r, g, b, a); - } -); -#endif - - - -@implementation GPUImageAddBlendFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageAddBlendFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAlphaBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAlphaBlendFilter.h deleted file mode 100755 index c4d75759..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAlphaBlendFilter.h +++ /dev/null @@ -1,11 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageAlphaBlendFilter : GPUImageTwoInputFilter -{ - GLint mixUniform; -} - -// Mix ranges from 0.0 (only image 1) to 1.0 (only image 2), with 1.0 as the normal level -@property(readwrite, nonatomic) CGFloat mix; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAlphaBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAlphaBlendFilter.m deleted file mode 100755 index 077df790..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAlphaBlendFilter.m +++ /dev/null @@ -1,72 +0,0 @@ -#import "GPUImageAlphaBlendFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageAlphaBlendFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - uniform lowp float mixturePercent; - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - lowp vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2); - - gl_FragColor = vec4(mix(textureColor.rgb, textureColor2.rgb, textureColor2.a * mixturePercent), textureColor.a); - } -); -#else -NSString *const kGPUImageAlphaBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - uniform float mixturePercent; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2); - - gl_FragColor = vec4(mix(textureColor.rgb, textureColor2.rgb, textureColor2.a * mixturePercent), textureColor.a); - } -); -#endif - -@implementation GPUImageAlphaBlendFilter - -@synthesize mix = _mix; - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageAlphaBlendFragmentShaderString])) - { - return nil; - } - - mixUniform = [filterProgram uniformIndex:@"mixturePercent"]; - self.mix = 0.5; - - return self; -} - - -#pragma mark - -#pragma mark Accessors - -- (void)setMix:(CGFloat)newValue; -{ - _mix = newValue; - - [self setFloat:_mix forUniform:mixUniform program:filterProgram]; -} - - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAmatorkaFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAmatorkaFilter.h deleted file mode 100755 index 1dbe096d..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAmatorkaFilter.h +++ /dev/null @@ -1,17 +0,0 @@ -#import "GPUImageFilterGroup.h" - -@class GPUImagePicture; - -/** A photo filter based on Photoshop action by Amatorka - http://amatorka.deviantart.com/art/Amatorka-Action-2-121069631 - */ - -// Note: If you want to use this effect you have to add lookup_amatorka.png -// from Resources folder to your application bundle. - -@interface GPUImageAmatorkaFilter : GPUImageFilterGroup -{ - GPUImagePicture *lookupImageSource; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAmatorkaFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAmatorkaFilter.m deleted file mode 100755 index 1ab3ec4e..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAmatorkaFilter.m +++ /dev/null @@ -1,38 +0,0 @@ -#import "GPUImageAmatorkaFilter.h" -#import "GPUImagePicture.h" -#import "GPUImageLookupFilter.h" - -@implementation GPUImageAmatorkaFilter - -- (id)init; -{ - if (!(self = [super init])) - { - return nil; - } - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - UIImage *image = [UIImage imageNamed:@"lookup_amatorka.png"]; -#else - NSImage *image = [NSImage imageNamed:@"lookup_amatorka.png"]; -#endif - - NSAssert(image, @"To use GPUImageAmatorkaFilter you need to add lookup_amatorka.png from GPUImage/framework/Resources to your application bundle."); - - lookupImageSource = [[GPUImagePicture alloc] initWithImage:image]; - GPUImageLookupFilter *lookupFilter = [[GPUImageLookupFilter alloc] init]; - [self addFilter:lookupFilter]; - - [lookupImageSource addTarget:lookupFilter atTextureLocation:1]; - [lookupImageSource processImage]; - - self.initialFilters = [NSArray arrayWithObjects:lookupFilter, nil]; - self.terminalFilter = lookupFilter; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAverageColor.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAverageColor.h deleted file mode 100644 index e3d957d0..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAverageColor.h +++ /dev/null @@ -1,20 +0,0 @@ -#import "GPUImageFilter.h" - -extern NSString *const kGPUImageColorAveragingVertexShaderString; - -@interface GPUImageAverageColor : GPUImageFilter -{ - GLint texelWidthUniform, texelHeightUniform; - - NSUInteger numberOfStages; - - GLubyte *rawImagePixels; - CGSize finalStageSize; -} - -// This block is called on the completion of color averaging for a frame -@property(nonatomic, copy) void(^colorAverageProcessingFinishedBlock)(CGFloat redComponent, CGFloat greenComponent, CGFloat blueComponent, CGFloat alphaComponent, CMTime frameTime); - -- (void)extractAverageColorAtFrameTime:(CMTime)frameTime; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAverageColor.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAverageColor.m deleted file mode 100644 index a768ecb3..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAverageColor.m +++ /dev/null @@ -1,210 +0,0 @@ -#import "GPUImageAverageColor.h" - -NSString *const kGPUImageColorAveragingVertexShaderString = SHADER_STRING -( - attribute vec4 position; - attribute vec4 inputTextureCoordinate; - - uniform float texelWidth; - uniform float texelHeight; - - varying vec2 upperLeftInputTextureCoordinate; - varying vec2 upperRightInputTextureCoordinate; - varying vec2 lowerLeftInputTextureCoordinate; - varying vec2 lowerRightInputTextureCoordinate; - - void main() - { - gl_Position = position; - - upperLeftInputTextureCoordinate = inputTextureCoordinate.xy + vec2(-texelWidth, -texelHeight); - upperRightInputTextureCoordinate = inputTextureCoordinate.xy + vec2(texelWidth, -texelHeight); - lowerLeftInputTextureCoordinate = inputTextureCoordinate.xy + vec2(-texelWidth, texelHeight); - lowerRightInputTextureCoordinate = inputTextureCoordinate.xy + vec2(texelWidth, texelHeight); - } - ); - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageColorAveragingFragmentShaderString = SHADER_STRING -( - precision highp float; - - uniform sampler2D inputImageTexture; - - varying highp vec2 outputTextureCoordinate; - - varying highp vec2 upperLeftInputTextureCoordinate; - varying highp vec2 upperRightInputTextureCoordinate; - varying highp vec2 lowerLeftInputTextureCoordinate; - varying highp vec2 lowerRightInputTextureCoordinate; - - void main() - { - highp vec4 upperLeftColor = texture2D(inputImageTexture, upperLeftInputTextureCoordinate); - highp vec4 upperRightColor = texture2D(inputImageTexture, upperRightInputTextureCoordinate); - highp vec4 lowerLeftColor = texture2D(inputImageTexture, lowerLeftInputTextureCoordinate); - highp vec4 lowerRightColor = texture2D(inputImageTexture, lowerRightInputTextureCoordinate); - - gl_FragColor = 0.25 * (upperLeftColor + upperRightColor + lowerLeftColor + lowerRightColor); - } -); -#else -NSString *const kGPUImageColorAveragingFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - - varying vec2 outputTextureCoordinate; - - varying vec2 upperLeftInputTextureCoordinate; - varying vec2 upperRightInputTextureCoordinate; - varying vec2 lowerLeftInputTextureCoordinate; - varying vec2 lowerRightInputTextureCoordinate; - - void main() - { - vec4 upperLeftColor = texture2D(inputImageTexture, upperLeftInputTextureCoordinate); - vec4 upperRightColor = texture2D(inputImageTexture, upperRightInputTextureCoordinate); - vec4 lowerLeftColor = texture2D(inputImageTexture, lowerLeftInputTextureCoordinate); - vec4 lowerRightColor = texture2D(inputImageTexture, lowerRightInputTextureCoordinate); - - gl_FragColor = 0.25 * (upperLeftColor + upperRightColor + lowerLeftColor + lowerRightColor); - } -); -#endif - -@implementation GPUImageAverageColor - -@synthesize colorAverageProcessingFinishedBlock = _colorAverageProcessingFinishedBlock; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithVertexShaderFromString:kGPUImageColorAveragingVertexShaderString fragmentShaderFromString:kGPUImageColorAveragingFragmentShaderString])) - { - return nil; - } - - texelWidthUniform = [filterProgram uniformIndex:@"texelWidth"]; - texelHeightUniform = [filterProgram uniformIndex:@"texelHeight"]; - finalStageSize = CGSizeMake(1.0, 1.0); - - __unsafe_unretained GPUImageAverageColor *weakSelf = self; - [self setFrameProcessingCompletionBlock:^(GPUImageOutput *filter, CMTime frameTime) { - [weakSelf extractAverageColorAtFrameTime:frameTime]; - }]; - - return self; -} - -- (void)dealloc; -{ - if (rawImagePixels != NULL) - { - free(rawImagePixels); - } -} - -#pragma mark - -#pragma mark Managing the display FBOs - -- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates; -{ - if (self.preventRendering) - { - [firstInputFramebuffer unlock]; - return; - } - - outputFramebuffer = nil; - [GPUImageContext setActiveShaderProgram:filterProgram]; - - glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, vertices); - glVertexAttribPointer(filterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates); - - GLuint currentTexture = [firstInputFramebuffer texture]; - - NSUInteger numberOfReductionsInX = floor(log(inputTextureSize.width) / log(4.0)); - NSUInteger numberOfReductionsInY = floor(log(inputTextureSize.height) / log(4.0)); - NSUInteger reductionsToHitSideLimit = MIN(numberOfReductionsInX, numberOfReductionsInY); - for (NSUInteger currentReduction = 0; currentReduction < reductionsToHitSideLimit; currentReduction++) - { - CGSize currentStageSize = CGSizeMake(floor(inputTextureSize.width / pow(4.0, currentReduction + 1.0)), floor(inputTextureSize.height / pow(4.0, currentReduction + 1.0))); - if ( (currentStageSize.height < 2.0) || (currentStageSize.width < 2.0) ) - { - // A really small last stage seems to cause significant errors in the average, so I abort and leave the rest to the CPU at this point - break; - // currentStageSize.height = 2.0; // TODO: Rotate the image to account for this case, which causes FBO construction to fail - } - - [outputFramebuffer unlock]; - outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:currentStageSize textureOptions:self.outputTextureOptions onlyTexture:NO]; - [outputFramebuffer activateFramebuffer]; - - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, currentTexture); - - glUniform1i(filterInputTextureUniform, 2); - - glUniform1f(texelWidthUniform, 0.5 / currentStageSize.width); - glUniform1f(texelHeightUniform, 0.5 / currentStageSize.height); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - currentTexture = [outputFramebuffer texture]; - finalStageSize = currentStageSize; - } - - [firstInputFramebuffer unlock]; -} - -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -{ - inputRotation = kGPUImageNoRotation; -} - -- (void)extractAverageColorAtFrameTime:(CMTime)frameTime; -{ - runSynchronouslyOnVideoProcessingQueue(^{ - // we need a normal color texture for averaging the color values - NSAssert(self.outputTextureOptions.internalFormat == GL_RGBA, @"The output texture internal format for this filter must be GL_RGBA."); - NSAssert(self.outputTextureOptions.type == GL_UNSIGNED_BYTE, @"The type of the output texture of this filter must be GL_UNSIGNED_BYTE."); - - NSUInteger totalNumberOfPixels = round(finalStageSize.width * finalStageSize.height); - - if (rawImagePixels == NULL) - { - rawImagePixels = (GLubyte *)malloc(totalNumberOfPixels * 4); - } - - [GPUImageContext useImageProcessingContext]; - [outputFramebuffer activateFramebuffer]; - glReadPixels(0, 0, (int)finalStageSize.width, (int)finalStageSize.height, GL_RGBA, GL_UNSIGNED_BYTE, rawImagePixels); - - NSUInteger redTotal = 0, greenTotal = 0, blueTotal = 0, alphaTotal = 0; - NSUInteger byteIndex = 0; - for (NSUInteger currentPixel = 0; currentPixel < totalNumberOfPixels; currentPixel++) - { - redTotal += rawImagePixels[byteIndex++]; - greenTotal += rawImagePixels[byteIndex++]; - blueTotal += rawImagePixels[byteIndex++]; - alphaTotal += rawImagePixels[byteIndex++]; - } - - CGFloat normalizedRedTotal = (CGFloat)redTotal / (CGFloat)totalNumberOfPixels / 255.0; - CGFloat normalizedGreenTotal = (CGFloat)greenTotal / (CGFloat)totalNumberOfPixels / 255.0; - CGFloat normalizedBlueTotal = (CGFloat)blueTotal / (CGFloat)totalNumberOfPixels / 255.0; - CGFloat normalizedAlphaTotal = (CGFloat)alphaTotal / (CGFloat)totalNumberOfPixels / 255.0; - - if (_colorAverageProcessingFinishedBlock != NULL) - { - _colorAverageProcessingFinishedBlock(normalizedRedTotal, normalizedGreenTotal, normalizedBlueTotal, normalizedAlphaTotal, frameTime); - } - }); -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAverageLuminanceThresholdFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAverageLuminanceThresholdFilter.h deleted file mode 100644 index 7f1ae464..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAverageLuminanceThresholdFilter.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "GPUImageFilterGroup.h" - -@interface GPUImageAverageLuminanceThresholdFilter : GPUImageFilterGroup - -// This is multiplied by the continually calculated average image luminosity to arrive at the final threshold. Default is 1.0. -@property(readwrite, nonatomic) CGFloat thresholdMultiplier; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAverageLuminanceThresholdFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAverageLuminanceThresholdFilter.m deleted file mode 100644 index eb2796f4..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageAverageLuminanceThresholdFilter.m +++ /dev/null @@ -1,47 +0,0 @@ -#import "GPUImageAverageLuminanceThresholdFilter.h" -#import "GPUImageLuminosity.h" -#import "GPUImageLuminanceThresholdFilter.h" - -@interface GPUImageAverageLuminanceThresholdFilter() -{ - GPUImageLuminosity *luminosityFilter; - GPUImageLuminanceThresholdFilter *luminanceThresholdFilter; -} -@end - -@implementation GPUImageAverageLuminanceThresholdFilter - -@synthesize thresholdMultiplier = _thresholdMultiplier; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super init])) - { - return nil; - } - - self.thresholdMultiplier = 1.0; - - luminosityFilter = [[GPUImageLuminosity alloc] init]; - [self addFilter:luminosityFilter]; - - luminanceThresholdFilter = [[GPUImageLuminanceThresholdFilter alloc] init]; - [self addFilter:luminanceThresholdFilter]; - - __unsafe_unretained GPUImageAverageLuminanceThresholdFilter *weakSelf = self; - __unsafe_unretained GPUImageLuminanceThresholdFilter *weakThreshold = luminanceThresholdFilter; - - [luminosityFilter setLuminosityProcessingFinishedBlock:^(CGFloat luminosity, CMTime frameTime) { - weakThreshold.threshold = luminosity * weakSelf.thresholdMultiplier; - }]; - - self.initialFilters = [NSArray arrayWithObjects:luminosityFilter, luminanceThresholdFilter, nil]; - self.terminalFilter = luminanceThresholdFilter; - - return self; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBilateralFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBilateralFilter.h deleted file mode 100644 index 6b736ccf..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBilateralFilter.h +++ /dev/null @@ -1,10 +0,0 @@ -#import "GPUImageGaussianBlurFilter.h" - -@interface GPUImageBilateralFilter : GPUImageGaussianBlurFilter -{ - CGFloat firstDistanceNormalizationFactorUniform; - CGFloat secondDistanceNormalizationFactorUniform; -} -// A normalization factor for the distance between central color and sample color. -@property(nonatomic, readwrite) CGFloat distanceNormalizationFactor; -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBilateralFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBilateralFilter.m deleted file mode 100644 index c2a8c867..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBilateralFilter.m +++ /dev/null @@ -1,231 +0,0 @@ -#import "GPUImageBilateralFilter.h" - -NSString *const kGPUImageBilateralBlurVertexShaderString = SHADER_STRING -( - attribute vec4 position; - attribute vec4 inputTextureCoordinate; - - const int GAUSSIAN_SAMPLES = 9; - - uniform float texelWidthOffset; - uniform float texelHeightOffset; - - varying vec2 textureCoordinate; - varying vec2 blurCoordinates[GAUSSIAN_SAMPLES]; - - void main() - { - gl_Position = position; - textureCoordinate = inputTextureCoordinate.xy; - - // Calculate the positions for the blur - int multiplier = 0; - vec2 blurStep; - vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset); - - for (int i = 0; i < GAUSSIAN_SAMPLES; i++) - { - multiplier = (i - ((GAUSSIAN_SAMPLES - 1) / 2)); - // Blur in x (horizontal) - blurStep = float(multiplier) * singleStepOffset; - blurCoordinates[i] = inputTextureCoordinate.xy + blurStep; - } - } -); - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageBilateralFilterFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - - const lowp int GAUSSIAN_SAMPLES = 9; - - varying highp vec2 textureCoordinate; - varying highp vec2 blurCoordinates[GAUSSIAN_SAMPLES]; - - uniform mediump float distanceNormalizationFactor; - - void main() - { - lowp vec4 centralColor; - lowp float gaussianWeightTotal; - lowp vec4 sum; - lowp vec4 sampleColor; - lowp float distanceFromCentralColor; - lowp float gaussianWeight; - - centralColor = texture2D(inputImageTexture, blurCoordinates[4]); - gaussianWeightTotal = 0.18; - sum = centralColor * 0.18; - - sampleColor = texture2D(inputImageTexture, blurCoordinates[0]); - distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); - gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor); - gaussianWeightTotal += gaussianWeight; - sum += sampleColor * gaussianWeight; - - sampleColor = texture2D(inputImageTexture, blurCoordinates[1]); - distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); - gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor); - gaussianWeightTotal += gaussianWeight; - sum += sampleColor * gaussianWeight; - - sampleColor = texture2D(inputImageTexture, blurCoordinates[2]); - distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); - gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor); - gaussianWeightTotal += gaussianWeight; - sum += sampleColor * gaussianWeight; - - sampleColor = texture2D(inputImageTexture, blurCoordinates[3]); - distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); - gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor); - gaussianWeightTotal += gaussianWeight; - sum += sampleColor * gaussianWeight; - - sampleColor = texture2D(inputImageTexture, blurCoordinates[5]); - distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); - gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor); - gaussianWeightTotal += gaussianWeight; - sum += sampleColor * gaussianWeight; - - sampleColor = texture2D(inputImageTexture, blurCoordinates[6]); - distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); - gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor); - gaussianWeightTotal += gaussianWeight; - sum += sampleColor * gaussianWeight; - - sampleColor = texture2D(inputImageTexture, blurCoordinates[7]); - distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); - gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor); - gaussianWeightTotal += gaussianWeight; - sum += sampleColor * gaussianWeight; - - sampleColor = texture2D(inputImageTexture, blurCoordinates[8]); - distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); - gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor); - gaussianWeightTotal += gaussianWeight; - sum += sampleColor * gaussianWeight; - - gl_FragColor = sum / gaussianWeightTotal; - } -); -#else -NSString *const kGPUImageBilateralFilterFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - - const int GAUSSIAN_SAMPLES = 9; - - varying vec2 textureCoordinate; - varying vec2 blurCoordinates[GAUSSIAN_SAMPLES]; - - uniform float distanceNormalizationFactor; - - void main() - { - vec4 centralColor; - float gaussianWeightTotal; - vec4 sum; - vec4 sampleColor; - float distanceFromCentralColor; - float gaussianWeight; - - centralColor = texture2D(inputImageTexture, blurCoordinates[4]); - gaussianWeightTotal = 0.18; - sum = centralColor * 0.18; - - sampleColor = texture2D(inputImageTexture, blurCoordinates[0]); - distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); - gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor); - gaussianWeightTotal += gaussianWeight; - sum += sampleColor * gaussianWeight; - - sampleColor = texture2D(inputImageTexture, blurCoordinates[1]); - distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); - gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor); - gaussianWeightTotal += gaussianWeight; - sum += sampleColor * gaussianWeight; - - sampleColor = texture2D(inputImageTexture, blurCoordinates[2]); - distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); - gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor); - gaussianWeightTotal += gaussianWeight; - sum += sampleColor * gaussianWeight; - - sampleColor = texture2D(inputImageTexture, blurCoordinates[3]); - distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); - gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor); - gaussianWeightTotal += gaussianWeight; - sum += sampleColor * gaussianWeight; - - sampleColor = texture2D(inputImageTexture, blurCoordinates[5]); - distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); - gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor); - gaussianWeightTotal += gaussianWeight; - sum += sampleColor * gaussianWeight; - - sampleColor = texture2D(inputImageTexture, blurCoordinates[6]); - distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); - gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor); - gaussianWeightTotal += gaussianWeight; - sum += sampleColor * gaussianWeight; - - sampleColor = texture2D(inputImageTexture, blurCoordinates[7]); - distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); - gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor); - gaussianWeightTotal += gaussianWeight; - sum += sampleColor * gaussianWeight; - - sampleColor = texture2D(inputImageTexture, blurCoordinates[8]); - distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); - gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor); - gaussianWeightTotal += gaussianWeight; - sum += sampleColor * gaussianWeight; - - gl_FragColor = sum / gaussianWeightTotal; - } -); -#endif - -@implementation GPUImageBilateralFilter - -@synthesize distanceNormalizationFactor = _distanceNormalizationFactor; - -- (id)init; -{ - - if (!(self = [super initWithFirstStageVertexShaderFromString:kGPUImageBilateralBlurVertexShaderString - firstStageFragmentShaderFromString:kGPUImageBilateralFilterFragmentShaderString - secondStageVertexShaderFromString:kGPUImageBilateralBlurVertexShaderString - secondStageFragmentShaderFromString:kGPUImageBilateralFilterFragmentShaderString])) { - return nil; - } - - firstDistanceNormalizationFactorUniform = [filterProgram uniformIndex:@"distanceNormalizationFactor"]; - secondDistanceNormalizationFactorUniform = [filterProgram uniformIndex:@"distanceNormalizationFactor"]; - - self.texelSpacingMultiplier = 4.0; - self.distanceNormalizationFactor = 8.0; - - - return self; -} - - -#pragma mark - -#pragma mark Accessors - -- (void)setDistanceNormalizationFactor:(CGFloat)newValue -{ - _distanceNormalizationFactor = newValue; - - [self setFloat:newValue - forUniform:firstDistanceNormalizationFactorUniform - program:filterProgram]; - - [self setFloat:newValue - forUniform:secondDistanceNormalizationFactorUniform - program:secondFilterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBoxBlurFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBoxBlurFilter.h deleted file mode 100755 index 3fd880bf..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBoxBlurFilter.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "GPUImageGaussianBlurFilter.h" - -/** A hardware-accelerated box blur of an image - */ -@interface GPUImageBoxBlurFilter : GPUImageGaussianBlurFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBoxBlurFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBoxBlurFilter.m deleted file mode 100755 index 5a49385b..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBoxBlurFilter.m +++ /dev/null @@ -1,178 +0,0 @@ -#import "GPUImageBoxBlurFilter.h" - - -@implementation GPUImageBoxBlurFilter - -+ (NSString *)vertexShaderForOptimizedBlurOfRadius:(NSUInteger)blurRadius sigma:(CGFloat)sigma; -{ - if (blurRadius < 1) - { - return kGPUImageVertexShaderString; - } - - // From these weights we calculate the offsets to read interpolated values from - NSUInteger numberOfOptimizedOffsets = MIN(blurRadius / 2 + (blurRadius % 2), 7); - - NSMutableString *shaderString = [[NSMutableString alloc] init]; - // Header - [shaderString appendFormat:@"\ - attribute vec4 position;\n\ - attribute vec4 inputTextureCoordinate;\n\ - \n\ - uniform float texelWidthOffset;\n\ - uniform float texelHeightOffset;\n\ - \n\ - varying vec2 blurCoordinates[%lu];\n\ - \n\ - void main()\n\ - {\n\ - gl_Position = position;\n\ - \n\ - vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset);\n", (unsigned long)(1 + (numberOfOptimizedOffsets * 2))]; - - // Inner offset loop - [shaderString appendString:@"blurCoordinates[0] = inputTextureCoordinate.xy;\n"]; - for (NSUInteger currentOptimizedOffset = 0; currentOptimizedOffset < numberOfOptimizedOffsets; currentOptimizedOffset++) - { - GLfloat optimizedOffset = (GLfloat)(currentOptimizedOffset * 2) + 1.5; - - [shaderString appendFormat:@"\ - blurCoordinates[%lu] = inputTextureCoordinate.xy + singleStepOffset * %f;\n\ - blurCoordinates[%lu] = inputTextureCoordinate.xy - singleStepOffset * %f;\n", (unsigned long)((currentOptimizedOffset * 2) + 1), optimizedOffset, (unsigned long)((currentOptimizedOffset * 2) + 2), optimizedOffset]; - } - - // Footer - [shaderString appendString:@"}\n"]; - - return shaderString; -} - -+ (NSString *)fragmentShaderForOptimizedBlurOfRadius:(NSUInteger)blurRadius sigma:(CGFloat)sigma; -{ - if (blurRadius < 1) - { - return kGPUImagePassthroughFragmentShaderString; - } - - NSUInteger numberOfOptimizedOffsets = MIN(blurRadius / 2 + (blurRadius % 2), 7); - NSUInteger trueNumberOfOptimizedOffsets = blurRadius / 2 + (blurRadius % 2); - - NSMutableString *shaderString = [[NSMutableString alloc] init]; - - // Header -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - [shaderString appendFormat:@"\ - uniform sampler2D inputImageTexture;\n\ - uniform highp float texelWidthOffset;\n\ - uniform highp float texelHeightOffset;\n\ - \n\ - varying highp vec2 blurCoordinates[%lu];\n\ - \n\ - void main()\n\ - {\n\ - lowp vec4 sum = vec4(0.0);\n", (unsigned long)(1 + (numberOfOptimizedOffsets * 2)) ]; -#else - [shaderString appendFormat:@"\ - uniform sampler2D inputImageTexture;\n\ - uniform float texelWidthOffset;\n\ - uniform float texelHeightOffset;\n\ - \n\ - varying vec2 blurCoordinates[%lu];\n\ - \n\ - void main()\n\ - {\n\ - vec4 sum = vec4(0.0);\n", 1 + (numberOfOptimizedOffsets * 2) ]; -#endif - - GLfloat boxWeight = 1.0 / (GLfloat)((blurRadius * 2) + 1); - - // Inner texture loop - [shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[0]) * %f;\n", boxWeight]; - - for (NSUInteger currentBlurCoordinateIndex = 0; currentBlurCoordinateIndex < numberOfOptimizedOffsets; currentBlurCoordinateIndex++) - { - [shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[%lu]) * %f;\n", (unsigned long)((currentBlurCoordinateIndex * 2) + 1), boxWeight * 2.0]; - [shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[%lu]) * %f;\n", (unsigned long)((currentBlurCoordinateIndex * 2) + 2), boxWeight * 2.0]; - } - - // If the number of required samples exceeds the amount we can pass in via varyings, we have to do dependent texture reads in the fragment shader - if (trueNumberOfOptimizedOffsets > numberOfOptimizedOffsets) - { -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - [shaderString appendString:@"highp vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset);\n"]; -#else - [shaderString appendString:@"vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset);\n"]; -#endif - - for (NSUInteger currentOverlowTextureRead = numberOfOptimizedOffsets; currentOverlowTextureRead < trueNumberOfOptimizedOffsets; currentOverlowTextureRead++) - { - GLfloat optimizedOffset = (GLfloat)(currentOverlowTextureRead * 2) + 1.5; - - [shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[0] + singleStepOffset * %f) * %f;\n", optimizedOffset, boxWeight * 2.0]; - [shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[0] - singleStepOffset * %f) * %f;\n", optimizedOffset, boxWeight * 2.0]; - } - } - - // Footer - [shaderString appendString:@"\ - gl_FragColor = sum;\n\ - }\n"]; - - return shaderString; -} - -- (void)setupFilterForSize:(CGSize)filterFrameSize; -{ - [super setupFilterForSize:filterFrameSize]; - - if (shouldResizeBlurRadiusWithImageSize == YES) - { - - } -} - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - // NSString *currentGaussianBlurVertexShader = [GPUImageGaussianBlurFilter vertexShaderForStandardGaussianOfRadius:4 sigma:2.0]; - // NSString *currentGaussianBlurFragmentShader = [GPUImageGaussianBlurFilter fragmentShaderForStandardGaussianOfRadius:4 sigma:2.0]; - - NSString *currentBoxBlurVertexShader = [[self class] vertexShaderForOptimizedBlurOfRadius:4 sigma:0.0]; - NSString *currentBoxBlurFragmentShader = [[self class] fragmentShaderForOptimizedBlurOfRadius:4 sigma:0.0]; - - if (!(self = [super initWithFirstStageVertexShaderFromString:currentBoxBlurVertexShader firstStageFragmentShaderFromString:currentBoxBlurFragmentShader secondStageVertexShaderFromString:currentBoxBlurVertexShader secondStageFragmentShaderFromString:currentBoxBlurFragmentShader])) - { - return nil; - } - - _blurRadiusInPixels = 4.0; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setBlurRadiusInPixels:(CGFloat)newValue; -{ - CGFloat newBlurRadius = round(round(newValue / 2.0) * 2.0); // For now, only do even radii - - if (newBlurRadius != _blurRadiusInPixels) - { - _blurRadiusInPixels = newBlurRadius; - - NSString *newGaussianBlurVertexShader = [[self class] vertexShaderForOptimizedBlurOfRadius:_blurRadiusInPixels sigma:0.0]; - NSString *newGaussianBlurFragmentShader = [[self class] fragmentShaderForOptimizedBlurOfRadius:_blurRadiusInPixels sigma:0.0]; - - // NSLog(@"Optimized vertex shader: \n%@", newGaussianBlurVertexShader); - // NSLog(@"Optimized fragment shader: \n%@", newGaussianBlurFragmentShader); - // - [self switchToVertexShader:newGaussianBlurVertexShader fragmentShader:newGaussianBlurFragmentShader]; - } - shouldResizeBlurRadiusWithImageSize = NO; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBrightnessFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBrightnessFilter.h deleted file mode 100755 index 046473b9..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBrightnessFilter.h +++ /dev/null @@ -1,11 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageBrightnessFilter : GPUImageFilter -{ - GLint brightnessUniform; -} - -// Brightness ranges from -1.0 to 1.0, with 0.0 as the normal level -@property(readwrite, nonatomic) CGFloat brightness; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBrightnessFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBrightnessFilter.m deleted file mode 100755 index 7e526d85..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBrightnessFilter.m +++ /dev/null @@ -1,66 +0,0 @@ -#import "GPUImageBrightnessFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageBrightnessFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform lowp float brightness; - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - gl_FragColor = vec4((textureColor.rgb + vec3(brightness)), textureColor.w); - } -); -#else -NSString *const kGPUImageBrightnessFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float brightness; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - gl_FragColor = vec4((textureColor.rgb + vec3(brightness)), textureColor.w); - } - ); -#endif - -@implementation GPUImageBrightnessFilter - -@synthesize brightness = _brightness; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageBrightnessFragmentShaderString])) - { - return nil; - } - - brightnessUniform = [filterProgram uniformIndex:@"brightness"]; - self.brightness = 0.0; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setBrightness:(CGFloat)newValue; -{ - _brightness = newValue; - - [self setFloat:_brightness forUniform:brightnessUniform program:filterProgram]; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBuffer.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBuffer.h deleted file mode 100644 index caf09c8d..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBuffer.h +++ /dev/null @@ -1,10 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageBuffer : GPUImageFilter -{ - NSMutableArray *bufferedFramebuffers; -} - -@property(readwrite, nonatomic) NSUInteger bufferSize; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBuffer.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBuffer.m deleted file mode 100644 index c90d020a..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBuffer.m +++ /dev/null @@ -1,112 +0,0 @@ -#import "GPUImageBuffer.h" - -@interface GPUImageBuffer() - -@end - -@implementation GPUImageBuffer - -@synthesize bufferSize = _bufferSize; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [self initWithFragmentShaderFromString:kGPUImagePassthroughFragmentShaderString])) - { - return nil; - } - - bufferedFramebuffers = [[NSMutableArray alloc] init]; -// [bufferedTextures addObject:[NSNumber numberWithInt:outputTexture]]; - _bufferSize = 1; - - return self; -} - -- (void)dealloc -{ - for (GPUImageFramebuffer *currentFramebuffer in bufferedFramebuffers) - { - [currentFramebuffer unlock]; - } -} - -#pragma mark - -#pragma mark GPUImageInput - -- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex; -{ - if ([bufferedFramebuffers count] >= _bufferSize) - { - outputFramebuffer = [bufferedFramebuffers objectAtIndex:0]; - [bufferedFramebuffers removeObjectAtIndex:0]; - } - else - { - // Nothing yet in the buffer, so don't process further until the buffer is full - outputFramebuffer = firstInputFramebuffer; - [firstInputFramebuffer lock]; - } - - [bufferedFramebuffers addObject:firstInputFramebuffer]; - - // Need to pass along rotation information, as we're just holding on to buffered framebuffers and not rotating them ourselves - for (id currentTarget in targets) - { - if (currentTarget != self.targetToIgnoreForUpdates) - { - NSInteger indexOfObject = [targets indexOfObject:currentTarget]; - NSInteger textureIndex = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; - - [currentTarget setInputRotation:inputRotation atIndex:textureIndex]; - } - } - - // Let the downstream video elements see the previous frame from the buffer before rendering a new one into place - [self informTargetsAboutNewFrameAtTime:frameTime]; - -// [self renderToTextureWithVertices:imageVertices textureCoordinates:[[self class] textureCoordinatesForRotation:inputRotation]]; -} - -- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates; -{ - // No need to render to another texture anymore, since we'll be hanging on to the textures in our buffer -} - -#pragma mark - -#pragma mark Accessors - -- (void)setBufferSize:(NSUInteger)newValue; -{ - if ( (newValue == _bufferSize) || (newValue < 1) ) - { - return; - } - - if (newValue > _bufferSize) - { - NSUInteger texturesToAdd = newValue - _bufferSize; - for (NSUInteger currentTextureIndex = 0; currentTextureIndex < texturesToAdd; currentTextureIndex++) - { - // TODO: Deal with the growth of the size of the buffer by rotating framebuffers, no textures - } - } - else - { - NSUInteger texturesToRemove = _bufferSize - newValue; - for (NSUInteger currentTextureIndex = 0; currentTextureIndex < texturesToRemove; currentTextureIndex++) - { - GPUImageFramebuffer *lastFramebuffer = [bufferedFramebuffers lastObject]; - [bufferedFramebuffers removeObjectAtIndex:([bufferedFramebuffers count] - 1)]; - - [lastFramebuffer unlock]; - lastFramebuffer = nil; - } - } - - _bufferSize = newValue; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBulgeDistortionFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBulgeDistortionFilter.h deleted file mode 100755 index d416e536..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBulgeDistortionFilter.h +++ /dev/null @@ -1,16 +0,0 @@ -#import "GPUImageFilter.h" - -/// Creates a bulge distortion on the image -@interface GPUImageBulgeDistortionFilter : GPUImageFilter -{ - GLint aspectRatioUniform, radiusUniform, centerUniform, scaleUniform; -} - -/// The center about which to apply the distortion, with a default of (0.5, 0.5) -@property(readwrite, nonatomic) CGPoint center; -/// The radius of the distortion, ranging from 0.0 to 1.0, with a default of 0.25 -@property(readwrite, nonatomic) CGFloat radius; -/// The amount of distortion to apply, from -1.0 to 1.0, with a default of 0.5 -@property(readwrite, nonatomic) CGFloat scale; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBulgeDistortionFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBulgeDistortionFilter.m deleted file mode 100755 index 1f778ada..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageBulgeDistortionFilter.m +++ /dev/null @@ -1,174 +0,0 @@ -#import "GPUImageBulgeDistortionFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageBulgeDistortionFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform highp float aspectRatio; - uniform highp vec2 center; - uniform highp float radius; - uniform highp float scale; - - void main() - { - highp vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); - highp float dist = distance(center, textureCoordinateToUse); - textureCoordinateToUse = textureCoordinate; - - if (dist < radius) - { - textureCoordinateToUse -= center; - highp float percent = 1.0 - ((radius - dist) / radius) * scale; - percent = percent * percent; - - textureCoordinateToUse = textureCoordinateToUse * percent; - textureCoordinateToUse += center; - } - - gl_FragColor = texture2D(inputImageTexture, textureCoordinateToUse ); - } -); -#else -NSString *const kGPUImageBulgeDistortionFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform float aspectRatio; - uniform vec2 center; - uniform float radius; - uniform float scale; - - void main() - { - vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); - float dist = distance(center, textureCoordinateToUse); - textureCoordinateToUse = textureCoordinate; - - if (dist < radius) - { - textureCoordinateToUse -= center; - float percent = 1.0 - ((radius - dist) / radius) * scale; - percent = percent * percent; - - textureCoordinateToUse = textureCoordinateToUse * percent; - textureCoordinateToUse += center; - } - - gl_FragColor = texture2D(inputImageTexture, textureCoordinateToUse ); - } -); -#endif - - -@interface GPUImageBulgeDistortionFilter () - -- (void)adjustAspectRatio; - -@property (readwrite, nonatomic) CGFloat aspectRatio; - -@end - -@implementation GPUImageBulgeDistortionFilter - -@synthesize aspectRatio = _aspectRatio; -@synthesize center = _center; -@synthesize radius = _radius; -@synthesize scale = _scale; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageBulgeDistortionFragmentShaderString])) - { - return nil; - } - - aspectRatioUniform = [filterProgram uniformIndex:@"aspectRatio"]; - radiusUniform = [filterProgram uniformIndex:@"radius"]; - scaleUniform = [filterProgram uniformIndex:@"scale"]; - centerUniform = [filterProgram uniformIndex:@"center"]; - - self.radius = 0.25; - self.scale = 0.5; - self.center = CGPointMake(0.5, 0.5); - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)adjustAspectRatio; -{ - if (GPUImageRotationSwapsWidthAndHeight(inputRotation)) - { - [self setAspectRatio:(inputTextureSize.width / inputTextureSize.height)]; - } - else - { - [self setAspectRatio:(inputTextureSize.height / inputTextureSize.width)]; - } -} - -- (void)forceProcessingAtSize:(CGSize)frameSize; -{ - [super forceProcessingAtSize:frameSize]; - [self adjustAspectRatio]; -} - -- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex; -{ - CGSize oldInputSize = inputTextureSize; - [super setInputSize:newSize atIndex:textureIndex]; - - if ( (!CGSizeEqualToSize(oldInputSize, inputTextureSize)) && (!CGSizeEqualToSize(newSize, CGSizeZero)) ) - { - [self adjustAspectRatio]; - } -} - -- (void)setAspectRatio:(CGFloat)newValue; -{ - _aspectRatio = newValue; - - [self setFloat:_aspectRatio forUniform:aspectRatioUniform program:filterProgram]; -} - -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -{ - [super setInputRotation:newInputRotation atIndex:textureIndex]; - [self setCenter:self.center]; - [self adjustAspectRatio]; -} - -- (void)setRadius:(CGFloat)newValue; -{ - _radius = newValue; - - [self setFloat:_radius forUniform:radiusUniform program:filterProgram]; -} - -- (void)setScale:(CGFloat)newValue; -{ - _scale = newValue; - - [self setFloat:_scale forUniform:scaleUniform program:filterProgram]; -} - -- (void)setCenter:(CGPoint)newValue; -{ - _center = newValue; - - CGPoint rotatedPoint = [self rotatedPoint:_center forRotation:inputRotation]; - - [self setPoint:rotatedPoint forUniform:centerUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCGAColorspaceFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCGAColorspaceFilter.h deleted file mode 100755 index 4f97804b..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCGAColorspaceFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageCGAColorspaceFilter : GPUImageFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCGAColorspaceFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCGAColorspaceFilter.m deleted file mode 100755 index eee939a0..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCGAColorspaceFilter.m +++ /dev/null @@ -1,113 +0,0 @@ -// -// GPUImageCGAColorspaceFilter.m -// - -#import "GPUImageCGAColorspaceFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageCGAColorspaceFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - highp vec2 sampleDivisor = vec2(1.0 / 200.0, 1.0 / 320.0); - //highp vec4 colorDivisor = vec4(colorDepth); - - highp vec2 samplePos = textureCoordinate - mod(textureCoordinate, sampleDivisor); - highp vec4 color = texture2D(inputImageTexture, samplePos ); - - //gl_FragColor = texture2D(inputImageTexture, samplePos ); - mediump vec4 colorCyan = vec4(85.0 / 255.0, 1.0, 1.0, 1.0); - mediump vec4 colorMagenta = vec4(1.0, 85.0 / 255.0, 1.0, 1.0); - mediump vec4 colorWhite = vec4(1.0, 1.0, 1.0, 1.0); - mediump vec4 colorBlack = vec4(0.0, 0.0, 0.0, 1.0); - - mediump vec4 endColor; - highp float blackDistance = distance(color, colorBlack); - highp float whiteDistance = distance(color, colorWhite); - highp float magentaDistance = distance(color, colorMagenta); - highp float cyanDistance = distance(color, colorCyan); - - mediump vec4 finalColor; - - highp float colorDistance = min(magentaDistance, cyanDistance); - colorDistance = min(colorDistance, whiteDistance); - colorDistance = min(colorDistance, blackDistance); - - if (colorDistance == blackDistance) { - finalColor = colorBlack; - } else if (colorDistance == whiteDistance) { - finalColor = colorWhite; - } else if (colorDistance == cyanDistance) { - finalColor = colorCyan; - } else { - finalColor = colorMagenta; - } - - gl_FragColor = finalColor; - } -); -#else -NSString *const kGPUImageCGAColorspaceFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - vec2 sampleDivisor = vec2(1.0 / 200.0, 1.0 / 320.0); - //highp vec4 colorDivisor = vec4(colorDepth); - - vec2 samplePos = textureCoordinate - mod(textureCoordinate, sampleDivisor); - vec4 color = texture2D(inputImageTexture, samplePos ); - - //gl_FragColor = texture2D(inputImageTexture, samplePos ); - vec4 colorCyan = vec4(85.0 / 255.0, 1.0, 1.0, 1.0); - vec4 colorMagenta = vec4(1.0, 85.0 / 255.0, 1.0, 1.0); - vec4 colorWhite = vec4(1.0, 1.0, 1.0, 1.0); - vec4 colorBlack = vec4(0.0, 0.0, 0.0, 1.0); - - vec4 endColor; - float blackDistance = distance(color, colorBlack); - float whiteDistance = distance(color, colorWhite); - float magentaDistance = distance(color, colorMagenta); - float cyanDistance = distance(color, colorCyan); - - vec4 finalColor; - - float colorDistance = min(magentaDistance, cyanDistance); - colorDistance = min(colorDistance, whiteDistance); - colorDistance = min(colorDistance, blackDistance); - - if (colorDistance == blackDistance) { - finalColor = colorBlack; - } else if (colorDistance == whiteDistance) { - finalColor = colorWhite; - } else if (colorDistance == cyanDistance) { - finalColor = colorCyan; - } else { - finalColor = colorMagenta; - } - - gl_FragColor = finalColor; - } -); -#endif - -@implementation GPUImageCGAColorspaceFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageCGAColorspaceFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCannyEdgeDetectionFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCannyEdgeDetectionFilter.h deleted file mode 100755 index 53c58502..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCannyEdgeDetectionFilter.h +++ /dev/null @@ -1,62 +0,0 @@ -#import "GPUImageFilterGroup.h" - -@class GPUImageGrayscaleFilter; -@class GPUImageSingleComponentGaussianBlurFilter; -@class GPUImageDirectionalSobelEdgeDetectionFilter; -@class GPUImageDirectionalNonMaximumSuppressionFilter; -@class GPUImageWeakPixelInclusionFilter; - -/** This applies the edge detection process described by John Canny in - - Canny, J., A Computational Approach To Edge Detection, IEEE Trans. Pattern Analysis and Machine Intelligence, 8(6):679–698, 1986. - - and implemented in OpenGL ES by - - A. Ensor, S. Hall. GPU-based Image Analysis on Mobile Devices. Proceedings of Image and Vision Computing New Zealand 2011. - - It starts with a conversion to luminance, followed by an accelerated 9-hit Gaussian blur. A Sobel operator is applied to obtain the overall - gradient strength in the blurred image, as well as the direction (in texture sampling steps) of the gradient. A non-maximum suppression filter - acts along the direction of the gradient, highlighting strong edges that pass the threshold and completely removing those that fail the lower - threshold. Finally, pixels from in-between these thresholds are either included in edges or rejected based on neighboring pixels. - */ -@interface GPUImageCannyEdgeDetectionFilter : GPUImageFilterGroup -{ - GPUImageGrayscaleFilter *luminanceFilter; - GPUImageSingleComponentGaussianBlurFilter *blurFilter; - GPUImageDirectionalSobelEdgeDetectionFilter *edgeDetectionFilter; - GPUImageDirectionalNonMaximumSuppressionFilter *nonMaximumSuppressionFilter; - GPUImageWeakPixelInclusionFilter *weakPixelInclusionFilter; -} - -/** The image width and height factors tweak the appearance of the edges. - - These parameters affect the visibility of the detected edges - - By default, they match the inverse of the filter size in pixels - */ -@property(readwrite, nonatomic) CGFloat texelWidth; -/** The image width and height factors tweak the appearance of the edges. - - These parameters affect the visibility of the detected edges - - By default, they match the inverse of the filter size in pixels - */ -@property(readwrite, nonatomic) CGFloat texelHeight; - -/** The underlying blur radius for the Gaussian blur. Default is 2.0. - */ -@property (readwrite, nonatomic) CGFloat blurRadiusInPixels; - -/** The underlying blur texel spacing multiplier. Default is 1.0. - */ -@property (readwrite, nonatomic) CGFloat blurTexelSpacingMultiplier; - -/** Any edge with a gradient magnitude above this threshold will pass and show up in the final result. - */ -@property(readwrite, nonatomic) CGFloat upperThreshold; - -/** Any edge with a gradient magnitude below this threshold will fail and be removed from the final result. - */ -@property(readwrite, nonatomic) CGFloat lowerThreshold; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCannyEdgeDetectionFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCannyEdgeDetectionFilter.m deleted file mode 100755 index 7327d532..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCannyEdgeDetectionFilter.m +++ /dev/null @@ -1,125 +0,0 @@ -#import "GPUImageCannyEdgeDetectionFilter.h" - -#import "GPUImageGrayscaleFilter.h" -#import "GPUImageDirectionalSobelEdgeDetectionFilter.h" -#import "GPUImageDirectionalNonMaximumSuppressionFilter.h" -#import "GPUImageWeakPixelInclusionFilter.h" -#import "GPUImageSingleComponentGaussianBlurFilter.h" - -@implementation GPUImageCannyEdgeDetectionFilter - -@synthesize upperThreshold; -@synthesize lowerThreshold; -@synthesize blurRadiusInPixels; -@synthesize blurTexelSpacingMultiplier; -@synthesize texelWidth; -@synthesize texelHeight; - -- (id)init; -{ - if (!(self = [super init])) - { - return nil; - } - - // First pass: convert image to luminance - luminanceFilter = [[GPUImageGrayscaleFilter alloc] init]; - [self addFilter:luminanceFilter]; - - // Second pass: apply a variable Gaussian blur - blurFilter = [[GPUImageSingleComponentGaussianBlurFilter alloc] init]; - [self addFilter:blurFilter]; - - // Third pass: run the Sobel edge detection, with calculated gradient directions, on this blurred image - edgeDetectionFilter = [[GPUImageDirectionalSobelEdgeDetectionFilter alloc] init]; - [self addFilter:edgeDetectionFilter]; - - // Fourth pass: apply non-maximum suppression - nonMaximumSuppressionFilter = [[GPUImageDirectionalNonMaximumSuppressionFilter alloc] init]; - [self addFilter:nonMaximumSuppressionFilter]; - - // Fifth pass: include weak pixels to complete edges - weakPixelInclusionFilter = [[GPUImageWeakPixelInclusionFilter alloc] init]; - [self addFilter:weakPixelInclusionFilter]; - - [luminanceFilter addTarget:blurFilter]; - [blurFilter addTarget:edgeDetectionFilter]; - [edgeDetectionFilter addTarget:nonMaximumSuppressionFilter]; - [nonMaximumSuppressionFilter addTarget:weakPixelInclusionFilter]; - - self.initialFilters = [NSArray arrayWithObject:luminanceFilter]; -// self.terminalFilter = nonMaximumSuppressionFilter; - self.terminalFilter = weakPixelInclusionFilter; - - self.blurRadiusInPixels = 2.0; - self.blurTexelSpacingMultiplier = 1.0; - self.upperThreshold = 0.4; - self.lowerThreshold = 0.1; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setBlurRadiusInPixels:(CGFloat)newValue; -{ - blurFilter.blurRadiusInPixels = newValue; -} - -- (CGFloat)blurRadiusInPixels; -{ - return blurFilter.blurRadiusInPixels; -} - -- (void)setBlurTexelSpacingMultiplier:(CGFloat)newValue; -{ - blurFilter.texelSpacingMultiplier = newValue; -} - -- (CGFloat)blurTexelSpacingMultiplier; -{ - return blurFilter.texelSpacingMultiplier; -} - -- (void)setTexelWidth:(CGFloat)newValue; -{ - edgeDetectionFilter.texelWidth = newValue; -} - -- (CGFloat)texelWidth; -{ - return edgeDetectionFilter.texelWidth; -} - -- (void)setTexelHeight:(CGFloat)newValue; -{ - edgeDetectionFilter.texelHeight = newValue; -} - -- (CGFloat)texelHeight; -{ - return edgeDetectionFilter.texelHeight; -} - -- (void)setUpperThreshold:(CGFloat)newValue; -{ - nonMaximumSuppressionFilter.upperThreshold = newValue; -} - -- (CGFloat)upperThreshold; -{ - return nonMaximumSuppressionFilter.upperThreshold; -} - -- (void)setLowerThreshold:(CGFloat)newValue; -{ - nonMaximumSuppressionFilter.lowerThreshold = newValue; -} - -- (CGFloat)lowerThreshold; -{ - return nonMaximumSuppressionFilter.lowerThreshold; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageChromaKeyBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageChromaKeyBlendFilter.h deleted file mode 100755 index 00a5aed7..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageChromaKeyBlendFilter.h +++ /dev/null @@ -1,32 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -/** Selectively replaces a color in the first image with the second image - */ -@interface GPUImageChromaKeyBlendFilter : GPUImageTwoInputFilter -{ - GLint colorToReplaceUniform, thresholdSensitivityUniform, smoothingUniform; -} - -/** The threshold sensitivity controls how similar pixels need to be colored to be replaced - - The default value is 0.3 - */ -@property(readwrite, nonatomic) CGFloat thresholdSensitivity; - -/** The degree of smoothing controls how gradually similar colors are replaced in the image - - The default value is 0.1 - */ -@property(readwrite, nonatomic) CGFloat smoothing; - -/** The color to be replaced is specified using individual red, green, and blue components (normalized to 1.0). - - The default is green: (0.0, 1.0, 0.0). - - @param redComponent Red component of color to be replaced - @param greenComponent Green component of color to be replaced - @param blueComponent Blue component of color to be replaced - */ -- (void)setColorToReplaceRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageChromaKeyBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageChromaKeyBlendFilter.m deleted file mode 100755 index 4e6b4661..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageChromaKeyBlendFilter.m +++ /dev/null @@ -1,117 +0,0 @@ -#import "GPUImageChromaKeyBlendFilter.h" - -// Shader code based on Apple's CIChromaKeyFilter example: https://developer.apple.com/library/mac/#samplecode/CIChromaKeyFilter/Introduction/Intro.html - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageChromaKeyBlendFragmentShaderString = SHADER_STRING -( - precision highp float; - - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform float thresholdSensitivity; - uniform float smoothing; - uniform vec3 colorToReplace; - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2); - - float maskY = 0.2989 * colorToReplace.r + 0.5866 * colorToReplace.g + 0.1145 * colorToReplace.b; - float maskCr = 0.7132 * (colorToReplace.r - maskY); - float maskCb = 0.5647 * (colorToReplace.b - maskY); - - float Y = 0.2989 * textureColor.r + 0.5866 * textureColor.g + 0.1145 * textureColor.b; - float Cr = 0.7132 * (textureColor.r - Y); - float Cb = 0.5647 * (textureColor.b - Y); - -// float blendValue = 1.0 - smoothstep(thresholdSensitivity - smoothing, thresholdSensitivity , abs(Cr - maskCr) + abs(Cb - maskCb)); - float blendValue = 1.0 - smoothstep(thresholdSensitivity, thresholdSensitivity + smoothing, distance(vec2(Cr, Cb), vec2(maskCr, maskCb))); - gl_FragColor = mix(textureColor, textureColor2, blendValue); - } -); -#else -NSString *const kGPUImageChromaKeyBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform float thresholdSensitivity; - uniform float smoothing; - uniform vec3 colorToReplace; - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2); - - float maskY = 0.2989 * colorToReplace.r + 0.5866 * colorToReplace.g + 0.1145 * colorToReplace.b; - float maskCr = 0.7132 * (colorToReplace.r - maskY); - float maskCb = 0.5647 * (colorToReplace.b - maskY); - - float Y = 0.2989 * textureColor.r + 0.5866 * textureColor.g + 0.1145 * textureColor.b; - float Cr = 0.7132 * (textureColor.r - Y); - float Cb = 0.5647 * (textureColor.b - Y); - - // float blendValue = 1.0 - smoothstep(thresholdSensitivity - smoothing, thresholdSensitivity , abs(Cr - maskCr) + abs(Cb - maskCb)); - float blendValue = 1.0 - smoothstep(thresholdSensitivity, thresholdSensitivity + smoothing, distance(vec2(Cr, Cb), vec2(maskCr, maskCb))); - gl_FragColor = mix(textureColor, textureColor2, blendValue); - } -); -#endif - -@implementation GPUImageChromaKeyBlendFilter - -@synthesize thresholdSensitivity = _thresholdSensitivity; -@synthesize smoothing = _smoothing; - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageChromaKeyBlendFragmentShaderString])) - { - return nil; - } - - thresholdSensitivityUniform = [filterProgram uniformIndex:@"thresholdSensitivity"]; - smoothingUniform = [filterProgram uniformIndex:@"smoothing"]; - colorToReplaceUniform = [filterProgram uniformIndex:@"colorToReplace"]; - - self.thresholdSensitivity = 0.4; - self.smoothing = 0.1; - [self setColorToReplaceRed:0.0 green:1.0 blue:0.0]; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setColorToReplaceRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent; -{ - GPUVector3 colorToReplace = {redComponent, greenComponent, blueComponent}; - - [self setVec3:colorToReplace forUniform:colorToReplaceUniform program:filterProgram]; -} - -- (void)setThresholdSensitivity:(CGFloat)newValue; -{ - _thresholdSensitivity = newValue; - - [self setFloat:(GLfloat)_thresholdSensitivity forUniform:thresholdSensitivityUniform program:filterProgram]; -} - -- (void)setSmoothing:(CGFloat)newValue; -{ - _smoothing = newValue; - - [self setFloat:(GLfloat)_smoothing forUniform:smoothingUniform program:filterProgram]; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageChromaKeyFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageChromaKeyFilter.h deleted file mode 100644 index 5ee7e498..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageChromaKeyFilter.h +++ /dev/null @@ -1,30 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageChromaKeyFilter : GPUImageFilter -{ - GLint colorToReplaceUniform, thresholdSensitivityUniform, smoothingUniform; -} - -/** The threshold sensitivity controls how similar pixels need to be colored to be replaced - - The default value is 0.3 - */ -@property(readwrite, nonatomic) CGFloat thresholdSensitivity; - -/** The degree of smoothing controls how gradually similar colors are replaced in the image - - The default value is 0.1 - */ -@property(readwrite, nonatomic) CGFloat smoothing; - -/** The color to be replaced is specified using individual red, green, and blue components (normalized to 1.0). - - The default is green: (0.0, 1.0, 0.0). - - @param redComponent Red component of color to be replaced - @param greenComponent Green component of color to be replaced - @param blueComponent Blue component of color to be replaced - */ -- (void)setColorToReplaceRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageChromaKeyFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageChromaKeyFilter.m deleted file mode 100644 index c70ef61d..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageChromaKeyFilter.m +++ /dev/null @@ -1,113 +0,0 @@ -#import "GPUImageChromaKeyFilter.h" - -// Shader code based on Apple's CIChromaKeyFilter example: https://developer.apple.com/library/mac/#samplecode/CIChromaKeyFilter/Introduction/Intro.html - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageChromaKeyFragmentShaderString = SHADER_STRING -( - precision highp float; - - varying highp vec2 textureCoordinate; - - uniform float thresholdSensitivity; - uniform float smoothing; - uniform vec3 colorToReplace; - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - float maskY = 0.2989 * colorToReplace.r + 0.5866 * colorToReplace.g + 0.1145 * colorToReplace.b; - float maskCr = 0.7132 * (colorToReplace.r - maskY); - float maskCb = 0.5647 * (colorToReplace.b - maskY); - - float Y = 0.2989 * textureColor.r + 0.5866 * textureColor.g + 0.1145 * textureColor.b; - float Cr = 0.7132 * (textureColor.r - Y); - float Cb = 0.5647 * (textureColor.b - Y); - - // float blendValue = 1.0 - smoothstep(thresholdSensitivity - smoothing, thresholdSensitivity , abs(Cr - maskCr) + abs(Cb - maskCb)); - float blendValue = smoothstep(thresholdSensitivity, thresholdSensitivity + smoothing, distance(vec2(Cr, Cb), vec2(maskCr, maskCb))); - gl_FragColor = vec4(textureColor.rgb, textureColor.a * blendValue); - } -); -#else -NSString *const kGPUImageChromaKeyFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform float thresholdSensitivity; - uniform float smoothing; - uniform vec3 colorToReplace; - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - float maskY = 0.2989 * colorToReplace.r + 0.5866 * colorToReplace.g + 0.1145 * colorToReplace.b; - float maskCr = 0.7132 * (colorToReplace.r - maskY); - float maskCb = 0.5647 * (colorToReplace.b - maskY); - - float Y = 0.2989 * textureColor.r + 0.5866 * textureColor.g + 0.1145 * textureColor.b; - float Cr = 0.7132 * (textureColor.r - Y); - float Cb = 0.5647 * (textureColor.b - Y); - - // float blendValue = 1.0 - smoothstep(thresholdSensitivity - smoothing, thresholdSensitivity , abs(Cr - maskCr) + abs(Cb - maskCb)); - float blendValue = smoothstep(thresholdSensitivity, thresholdSensitivity + smoothing, distance(vec2(Cr, Cb), vec2(maskCr, maskCb))); - gl_FragColor = vec4(textureColor.rgb, textureColor.a * blendValue); - } - ); -#endif - -@implementation GPUImageChromaKeyFilter - -@synthesize thresholdSensitivity = _thresholdSensitivity; -@synthesize smoothing = _smoothing; - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageChromaKeyFragmentShaderString])) - { - return nil; - } - - thresholdSensitivityUniform = [filterProgram uniformIndex:@"thresholdSensitivity"]; - smoothingUniform = [filterProgram uniformIndex:@"smoothing"]; - colorToReplaceUniform = [filterProgram uniformIndex:@"colorToReplace"]; - - self.thresholdSensitivity = 0.4; - self.smoothing = 0.1; - [self setColorToReplaceRed:0.0 green:1.0 blue:0.0]; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setColorToReplaceRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent; -{ - GPUVector3 colorToReplace = {redComponent, greenComponent, blueComponent}; - - [self setVec3:colorToReplace forUniform:colorToReplaceUniform program:filterProgram]; -} - -- (void)setThresholdSensitivity:(CGFloat)newValue; -{ - _thresholdSensitivity = newValue; - - [self setFloat:(GLfloat)_thresholdSensitivity forUniform:thresholdSensitivityUniform program:filterProgram]; -} - -- (void)setSmoothing:(CGFloat)newValue; -{ - _smoothing = newValue; - - [self setFloat:(GLfloat)_smoothing forUniform:smoothingUniform program:filterProgram]; -} - - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageClosingFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageClosingFilter.h deleted file mode 100644 index 61e34c41..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageClosingFilter.h +++ /dev/null @@ -1,19 +0,0 @@ -#import "GPUImageFilterGroup.h" - -@class GPUImageErosionFilter; -@class GPUImageDilationFilter; - -// A filter that first performs a dilation on the red channel of an image, followed by an erosion of the same radius. -// This helps to filter out smaller dark elements. - -@interface GPUImageClosingFilter : GPUImageFilterGroup -{ - GPUImageErosionFilter *erosionFilter; - GPUImageDilationFilter *dilationFilter; -} - -@property(readwrite, nonatomic) CGFloat verticalTexelSpacing, horizontalTexelSpacing; - -- (id)initWithRadius:(NSUInteger)radius; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageClosingFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageClosingFilter.m deleted file mode 100644 index 01e9b29b..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageClosingFilter.m +++ /dev/null @@ -1,57 +0,0 @@ -#import "GPUImageClosingFilter.h" -#import "GPUImageErosionFilter.h" -#import "GPUImageDilationFilter.h" - -@implementation GPUImageClosingFilter - -@synthesize verticalTexelSpacing = _verticalTexelSpacing; -@synthesize horizontalTexelSpacing = _horizontalTexelSpacing; - -- (id)init; -{ - if (!(self = [self initWithRadius:1])) - { - return nil; - } - - return self; -} - -- (id)initWithRadius:(NSUInteger)radius; -{ - if (!(self = [super init])) - { - return nil; - } - - // First pass: dilation - dilationFilter = [[GPUImageDilationFilter alloc] initWithRadius:radius]; - [self addFilter:dilationFilter]; - - // Second pass: erosion - erosionFilter = [[GPUImageErosionFilter alloc] initWithRadius:radius]; - [self addFilter:erosionFilter]; - - [dilationFilter addTarget:erosionFilter]; - - self.initialFilters = [NSArray arrayWithObjects:dilationFilter, nil]; - self.terminalFilter = erosionFilter; - - return self; -} - -- (void)setVerticalTexelSpacing:(CGFloat)newValue; -{ - _verticalTexelSpacing = newValue; - erosionFilter.verticalTexelSpacing = newValue; - dilationFilter.verticalTexelSpacing = newValue; -} - -- (void)setHorizontalTexelSpacing:(CGFloat)newValue; -{ - _horizontalTexelSpacing = newValue; - erosionFilter.horizontalTexelSpacing = newValue; - dilationFilter.horizontalTexelSpacing = newValue; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorBlendFilter.h deleted file mode 100644 index 302a16c6..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorBlendFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageColorBlendFilter : GPUImageTwoInputFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorBlendFilter.m deleted file mode 100644 index ced1cb8e..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorBlendFilter.m +++ /dev/null @@ -1,113 +0,0 @@ -#import "GPUImageColorBlendFilter.h" - -/** - * Color blend mode based upon pseudo code from the PDF specification. - */ -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageColorBlendFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - highp float lum(lowp vec3 c) { - return dot(c, vec3(0.3, 0.59, 0.11)); - } - - lowp vec3 clipcolor(lowp vec3 c) { - highp float l = lum(c); - lowp float n = min(min(c.r, c.g), c.b); - lowp float x = max(max(c.r, c.g), c.b); - - if (n < 0.0) { - c.r = l + ((c.r - l) * l) / (l - n); - c.g = l + ((c.g - l) * l) / (l - n); - c.b = l + ((c.b - l) * l) / (l - n); - } - if (x > 1.0) { - c.r = l + ((c.r - l) * (1.0 - l)) / (x - l); - c.g = l + ((c.g - l) * (1.0 - l)) / (x - l); - c.b = l + ((c.b - l) * (1.0 - l)) / (x - l); - } - - return c; - } - - lowp vec3 setlum(lowp vec3 c, highp float l) { - highp float d = l - lum(c); - c = c + vec3(d); - return clipcolor(c); - } - - void main() - { - highp vec4 baseColor = texture2D(inputImageTexture, textureCoordinate); - highp vec4 overlayColor = texture2D(inputImageTexture2, textureCoordinate2); - - gl_FragColor = vec4(baseColor.rgb * (1.0 - overlayColor.a) + setlum(overlayColor.rgb, lum(baseColor.rgb)) * overlayColor.a, baseColor.a); - } -); -#else -NSString *const kGPUImageColorBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - float lum(vec3 c) { - return dot(c, vec3(0.3, 0.59, 0.11)); - } - - vec3 clipcolor(vec3 c) { - float l = lum(c); - float n = min(min(c.r, c.g), c.b); - float x = max(max(c.r, c.g), c.b); - - if (n < 0.0) { - c.r = l + ((c.r - l) * l) / (l - n); - c.g = l + ((c.g - l) * l) / (l - n); - c.b = l + ((c.b - l) * l) / (l - n); - } - if (x > 1.0) { - c.r = l + ((c.r - l) * (1.0 - l)) / (x - l); - c.g = l + ((c.g - l) * (1.0 - l)) / (x - l); - c.b = l + ((c.b - l) * (1.0 - l)) / (x - l); - } - - return c; - } - - vec3 setlum(vec3 c, float l) { - float d = l - lum(c); - c = c + vec3(d); - return clipcolor(c); - } - - void main() - { - vec4 baseColor = texture2D(inputImageTexture, textureCoordinate); - vec4 overlayColor = texture2D(inputImageTexture2, textureCoordinate2); - - gl_FragColor = vec4(baseColor.rgb * (1.0 - overlayColor.a) + setlum(overlayColor.rgb, lum(baseColor.rgb)) * overlayColor.a, baseColor.a); - } -); -#endif - - -@implementation GPUImageColorBlendFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageColorBlendFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end \ No newline at end of file diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorBurnBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorBurnBlendFilter.h deleted file mode 100755 index 50ebb3f4..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorBurnBlendFilter.h +++ /dev/null @@ -1,9 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -/** Applies a color burn blend of two images - */ -@interface GPUImageColorBurnBlendFilter : GPUImageTwoInputFilter -{ -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorBurnBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorBurnBlendFilter.m deleted file mode 100755 index 5d6ff60d..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorBurnBlendFilter.m +++ /dev/null @@ -1,52 +0,0 @@ -#import "GPUImageColorBurnBlendFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageColorBurnBlendFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - mediump vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - mediump vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2); - mediump vec4 whiteColor = vec4(1.0); - gl_FragColor = whiteColor - (whiteColor - textureColor) / textureColor2; - } -); -#else -NSString *const kGPUImageColorBurnBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2); - vec4 whiteColor = vec4(1.0); - gl_FragColor = whiteColor - (whiteColor - textureColor) / textureColor2; - } -); -#endif - -@implementation GPUImageColorBurnBlendFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageColorBurnBlendFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorDodgeBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorDodgeBlendFilter.h deleted file mode 100755 index 0f541c42..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorDodgeBlendFilter.h +++ /dev/null @@ -1,9 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -/** Applies a color dodge blend of two images - */ -@interface GPUImageColorDodgeBlendFilter : GPUImageTwoInputFilter -{ -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorDodgeBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorDodgeBlendFilter.m deleted file mode 100755 index 6a38827c..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorDodgeBlendFilter.m +++ /dev/null @@ -1,75 +0,0 @@ -#import "GPUImageColorDodgeBlendFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageColorDodgeBlendFragmentShaderString = SHADER_STRING -( - - precision mediump float; - - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 base = texture2D(inputImageTexture, textureCoordinate); - vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2); - - vec3 baseOverlayAlphaProduct = vec3(overlay.a * base.a); - vec3 rightHandProduct = overlay.rgb * (1.0 - base.a) + base.rgb * (1.0 - overlay.a); - - vec3 firstBlendColor = baseOverlayAlphaProduct + rightHandProduct; - vec3 overlayRGB = clamp((overlay.rgb / clamp(overlay.a, 0.01, 1.0)) * step(0.0, overlay.a), 0.0, 0.99); - - vec3 secondBlendColor = (base.rgb * overlay.a) / (1.0 - overlayRGB) + rightHandProduct; - - vec3 colorChoice = step((overlay.rgb * base.a + base.rgb * overlay.a), baseOverlayAlphaProduct); - - gl_FragColor = vec4(mix(firstBlendColor, secondBlendColor, colorChoice), 1.0); - } -); -#else -NSString *const kGPUImageColorDodgeBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 base = texture2D(inputImageTexture, textureCoordinate); - vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2); - - vec3 baseOverlayAlphaProduct = vec3(overlay.a * base.a); - vec3 rightHandProduct = overlay.rgb * (1.0 - base.a) + base.rgb * (1.0 - overlay.a); - - vec3 firstBlendColor = baseOverlayAlphaProduct + rightHandProduct; - vec3 overlayRGB = clamp((overlay.rgb / clamp(overlay.a, 0.01, 1.0)) * step(0.0, overlay.a), 0.0, 0.99); - - vec3 secondBlendColor = (base.rgb * overlay.a) / (1.0 - overlayRGB) + rightHandProduct; - - vec3 colorChoice = step((overlay.rgb * base.a + base.rgb * overlay.a), baseOverlayAlphaProduct); - - gl_FragColor = vec4(mix(firstBlendColor, secondBlendColor, colorChoice), 1.0); - } -); -#endif - -@implementation GPUImageColorDodgeBlendFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageColorDodgeBlendFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorInvertFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorInvertFilter.h deleted file mode 100755 index aaeec438..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorInvertFilter.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageColorInvertFilter : GPUImageFilter -{ -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorInvertFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorInvertFilter.m deleted file mode 100755 index 0a8798b1..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorInvertFilter.m +++ /dev/null @@ -1,46 +0,0 @@ -#import "GPUImageColorInvertFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageInvertFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - gl_FragColor = vec4((1.0 - textureColor.rgb), textureColor.w); - } -); -#else -NSString *const kGPUImageInvertFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - gl_FragColor = vec4((1.0 - textureColor.rgb), textureColor.w); - } - ); -#endif - -@implementation GPUImageColorInvertFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageInvertFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorMatrixFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorMatrixFilter.h deleted file mode 100755 index 75887276..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorMatrixFilter.h +++ /dev/null @@ -1,19 +0,0 @@ -#import "GPUImageFilter.h" - -/** Transforms the colors of an image by applying a matrix to them - */ -@interface GPUImageColorMatrixFilter : GPUImageFilter -{ - GLint colorMatrixUniform; - GLint intensityUniform; -} - -/** A 4x4 matrix used to transform each color in an image - */ -@property(readwrite, nonatomic) GPUMatrix4x4 colorMatrix; - -/** The degree to which the new transformed color replaces the original color for each pixel - */ -@property(readwrite, nonatomic) CGFloat intensity; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorMatrixFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorMatrixFilter.m deleted file mode 100755 index 0e21c7e8..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorMatrixFilter.m +++ /dev/null @@ -1,87 +0,0 @@ -#import "GPUImageColorMatrixFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageColorMatrixFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform lowp mat4 colorMatrix; - uniform lowp float intensity; - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - lowp vec4 outputColor = textureColor * colorMatrix; - - gl_FragColor = (intensity * outputColor) + ((1.0 - intensity) * textureColor); - } -); -#else -NSString *const kGPUImageColorMatrixFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform mat4 colorMatrix; - uniform float intensity; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - vec4 outputColor = textureColor * colorMatrix; - - gl_FragColor = (intensity * outputColor) + ((1.0 - intensity) * textureColor); - } -); -#endif - -@implementation GPUImageColorMatrixFilter - -@synthesize intensity = _intensity; -@synthesize colorMatrix = _colorMatrix; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageColorMatrixFragmentShaderString])) - { - return nil; - } - - colorMatrixUniform = [filterProgram uniformIndex:@"colorMatrix"]; - intensityUniform = [filterProgram uniformIndex:@"intensity"]; - - self.intensity = 1.f; - self.colorMatrix = (GPUMatrix4x4){ - {1.f, 0.f, 0.f, 0.f}, - {0.f, 1.f, 0.f, 0.f}, - {0.f, 0.f, 1.f, 0.f}, - {0.f, 0.f, 0.f, 1.f} - }; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setIntensity:(CGFloat)newIntensity; -{ - _intensity = newIntensity; - - [self setFloat:_intensity forUniform:intensityUniform program:filterProgram]; -} - -- (void)setColorMatrix:(GPUMatrix4x4)newColorMatrix; -{ - _colorMatrix = newColorMatrix; - - [self setMatrix4f:_colorMatrix forUniform:colorMatrixUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorPackingFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorPackingFilter.h deleted file mode 100644 index c2edca51..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorPackingFilter.h +++ /dev/null @@ -1,10 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageColorPackingFilter : GPUImageFilter -{ - GLint texelWidthUniform, texelHeightUniform; - - CGFloat texelWidth, texelHeight; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorPackingFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorPackingFilter.m deleted file mode 100644 index 1a087ca8..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageColorPackingFilter.m +++ /dev/null @@ -1,139 +0,0 @@ -#import "GPUImageColorPackingFilter.h" - -NSString *const kGPUImageColorPackingVertexShaderString = SHADER_STRING -( - attribute vec4 position; - attribute vec4 inputTextureCoordinate; - - uniform float texelWidth; - uniform float texelHeight; - - varying vec2 upperLeftInputTextureCoordinate; - varying vec2 upperRightInputTextureCoordinate; - varying vec2 lowerLeftInputTextureCoordinate; - varying vec2 lowerRightInputTextureCoordinate; - - void main() - { - gl_Position = position; - - upperLeftInputTextureCoordinate = inputTextureCoordinate.xy + vec2(-texelWidth, -texelHeight); - upperRightInputTextureCoordinate = inputTextureCoordinate.xy + vec2(texelWidth, -texelHeight); - lowerLeftInputTextureCoordinate = inputTextureCoordinate.xy + vec2(-texelWidth, texelHeight); - lowerRightInputTextureCoordinate = inputTextureCoordinate.xy + vec2(texelWidth, texelHeight); - } -); - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageColorPackingFragmentShaderString = SHADER_STRING -( - precision lowp float; - - uniform sampler2D inputImageTexture; - - uniform mediump mat3 convolutionMatrix; - - varying highp vec2 outputTextureCoordinate; - - varying highp vec2 upperLeftInputTextureCoordinate; - varying highp vec2 upperRightInputTextureCoordinate; - varying highp vec2 lowerLeftInputTextureCoordinate; - varying highp vec2 lowerRightInputTextureCoordinate; - - void main() - { - float upperLeftIntensity = texture2D(inputImageTexture, upperLeftInputTextureCoordinate).r; - float upperRightIntensity = texture2D(inputImageTexture, upperRightInputTextureCoordinate).r; - float lowerLeftIntensity = texture2D(inputImageTexture, lowerLeftInputTextureCoordinate).r; - float lowerRightIntensity = texture2D(inputImageTexture, lowerRightInputTextureCoordinate).r; - - gl_FragColor = vec4(upperLeftIntensity, upperRightIntensity, lowerLeftIntensity, lowerRightIntensity); - } -); -#else -NSString *const kGPUImageColorPackingFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - - uniform mat3 convolutionMatrix; - - varying vec2 outputTextureCoordinate; - - varying vec2 upperLeftInputTextureCoordinate; - varying vec2 upperRightInputTextureCoordinate; - varying vec2 lowerLeftInputTextureCoordinate; - varying vec2 lowerRightInputTextureCoordinate; - - void main() - { - float upperLeftIntensity = texture2D(inputImageTexture, upperLeftInputTextureCoordinate).r; - float upperRightIntensity = texture2D(inputImageTexture, upperRightInputTextureCoordinate).r; - float lowerLeftIntensity = texture2D(inputImageTexture, lowerLeftInputTextureCoordinate).r; - float lowerRightIntensity = texture2D(inputImageTexture, lowerRightInputTextureCoordinate).r; - - gl_FragColor = vec4(upperLeftIntensity, upperRightIntensity, lowerLeftIntensity, lowerRightIntensity); - } -); -#endif - -@implementation GPUImageColorPackingFilter - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithVertexShaderFromString:kGPUImageColorPackingVertexShaderString fragmentShaderFromString:kGPUImageColorPackingFragmentShaderString])) - { - return nil; - } - - texelWidthUniform = [filterProgram uniformIndex:@"texelWidth"]; - texelHeightUniform = [filterProgram uniformIndex:@"texelHeight"]; - - return self; -} - -- (void)setupFilterForSize:(CGSize)filterFrameSize; -{ - texelWidth = 0.5 / inputTextureSize.width; - texelHeight = 0.5 / inputTextureSize.height; - - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext setActiveShaderProgram:filterProgram]; - glUniform1f(texelWidthUniform, texelWidth); - glUniform1f(texelHeightUniform, texelHeight); - }); -} - -#pragma mark - -#pragma mark Managing the display FBOs - -- (CGSize)sizeOfFBO; -{ - CGSize outputSize = [self maximumOutputSize]; - if ( (CGSizeEqualToSize(outputSize, CGSizeZero)) || (inputTextureSize.width < outputSize.width) ) - { - CGSize quarterSize; - quarterSize.width = inputTextureSize.width / 2.0; - quarterSize.height = inputTextureSize.height / 2.0; - return quarterSize; - } - else - { - return outputSize; - } -} - -#pragma mark - -#pragma mark Rendering - -- (CGSize)outputFrameSize; -{ - CGSize quarterSize; - quarterSize.width = inputTextureSize.width / 2.0; - quarterSize.height = inputTextureSize.height / 2.0; - return quarterSize; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageContrastFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageContrastFilter.h deleted file mode 100755 index e09e6dc4..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageContrastFilter.h +++ /dev/null @@ -1,14 +0,0 @@ -#import "GPUImageFilter.h" - -/** Adjusts the contrast of the image - */ -@interface GPUImageContrastFilter : GPUImageFilter -{ - GLint contrastUniform; -} - -/** Contrast ranges from 0.0 to 4.0 (max contrast), with 1.0 as the normal level - */ -@property(readwrite, nonatomic) CGFloat contrast; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageContrastFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageContrastFilter.m deleted file mode 100755 index 5ed1e22f..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageContrastFilter.m +++ /dev/null @@ -1,66 +0,0 @@ -#import "GPUImageContrastFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageContrastFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform lowp float contrast; - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - gl_FragColor = vec4(((textureColor.rgb - vec3(0.5)) * contrast + vec3(0.5)), textureColor.w); - } -); -#else -NSString *const kGPUImageContrastFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float contrast; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - gl_FragColor = vec4(((textureColor.rgb - vec3(0.5)) * contrast + vec3(0.5)), textureColor.w); - } - ); -#endif - -@implementation GPUImageContrastFilter - -@synthesize contrast = _contrast; - -#pragma mark - -#pragma mark Initialization - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageContrastFragmentShaderString])) - { - return nil; - } - - contrastUniform = [filterProgram uniformIndex:@"contrast"]; - self.contrast = 1.0; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setContrast:(CGFloat)newValue; -{ - _contrast = newValue; - - [self setFloat:_contrast forUniform:contrastUniform program:filterProgram]; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCropFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCropFilter.h deleted file mode 100755 index 641fb7bf..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCropFilter.h +++ /dev/null @@ -1,14 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageCropFilter : GPUImageFilter -{ - GLfloat cropTextureCoordinates[8]; -} - -// The crop region is the rectangle within the image to crop. It is normalized to a coordinate space from 0.0 to 1.0, with 0.0, 0.0 being the upper left corner of the image -@property(readwrite, nonatomic) CGRect cropRegion; - -// Initialization and teardown -- (id)initWithCropRegion:(CGRect)newCropRegion; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCropFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCropFilter.m deleted file mode 100755 index 22e33c17..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCropFilter.m +++ /dev/null @@ -1,274 +0,0 @@ -#import "GPUImageCropFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageCropFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - gl_FragColor = texture2D(inputImageTexture, textureCoordinate); - } -); -#else -NSString *const kGPUImageCropFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - gl_FragColor = texture2D(inputImageTexture, textureCoordinate); - } -); -#endif - -@interface GPUImageCropFilter () - -- (void)calculateCropTextureCoordinates; - -@end - -@interface GPUImageCropFilter() -{ - CGSize originallySuppliedInputSize; -} - -@end - -@implementation GPUImageCropFilter - -@synthesize cropRegion = _cropRegion; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithCropRegion:(CGRect)newCropRegion; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageCropFragmentShaderString])) - { - return nil; - } - - self.cropRegion = newCropRegion; - - return self; -} - -- (id)init; -{ - if (!(self = [self initWithCropRegion:CGRectMake(0.0, 0.0, 1.0, 1.0)])) - { - return nil; - } - - return self; -} - -#pragma mark - -#pragma mark Rendering - -- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex; -{ - if (self.preventRendering) - { - return; - } - -// if (overrideInputSize) -// { -// if (CGSizeEqualToSize(forcedMaximumSize, CGSizeZero)) -// { -// return; -// } -// else -// { -// CGRect insetRect = AVMakeRectWithAspectRatioInsideRect(newSize, CGRectMake(0.0, 0.0, forcedMaximumSize.width, forcedMaximumSize.height)); -// inputTextureSize = insetRect.size; -// return; -// } -// } - - CGSize rotatedSize = [self rotatedSize:newSize forIndex:textureIndex]; - originallySuppliedInputSize = rotatedSize; - - CGSize scaledSize; - scaledSize.width = rotatedSize.width * _cropRegion.size.width; - scaledSize.height = rotatedSize.height * _cropRegion.size.height; - - - if (CGSizeEqualToSize(scaledSize, CGSizeZero)) - { - inputTextureSize = scaledSize; - } - else if (!CGSizeEqualToSize(inputTextureSize, scaledSize)) - { - inputTextureSize = scaledSize; - } -} - -#pragma mark - -#pragma mark GPUImageInput - -- (void)calculateCropTextureCoordinates; -{ - CGFloat minX = _cropRegion.origin.x; - CGFloat minY = _cropRegion.origin.y; - CGFloat maxX = CGRectGetMaxX(_cropRegion); - CGFloat maxY = CGRectGetMaxY(_cropRegion); - - switch(inputRotation) - { - case kGPUImageNoRotation: // Works - { - cropTextureCoordinates[0] = minX; // 0,0 - cropTextureCoordinates[1] = minY; - - cropTextureCoordinates[2] = maxX; // 1,0 - cropTextureCoordinates[3] = minY; - - cropTextureCoordinates[4] = minX; // 0,1 - cropTextureCoordinates[5] = maxY; - - cropTextureCoordinates[6] = maxX; // 1,1 - cropTextureCoordinates[7] = maxY; - }; break; - case kGPUImageRotateLeft: // Fixed - { - cropTextureCoordinates[0] = maxY; // 1,0 - cropTextureCoordinates[1] = 1.0 - maxX; - - cropTextureCoordinates[2] = maxY; // 1,1 - cropTextureCoordinates[3] = 1.0 - minX; - - cropTextureCoordinates[4] = minY; // 0,0 - cropTextureCoordinates[5] = 1.0 - maxX; - - cropTextureCoordinates[6] = minY; // 0,1 - cropTextureCoordinates[7] = 1.0 - minX; - }; break; - case kGPUImageRotateRight: // Fixed - { - cropTextureCoordinates[0] = minY; // 0,1 - cropTextureCoordinates[1] = 1.0 - minX; - - cropTextureCoordinates[2] = minY; // 0,0 - cropTextureCoordinates[3] = 1.0 - maxX; - - cropTextureCoordinates[4] = maxY; // 1,1 - cropTextureCoordinates[5] = 1.0 - minX; - - cropTextureCoordinates[6] = maxY; // 1,0 - cropTextureCoordinates[7] = 1.0 - maxX; - }; break; - case kGPUImageFlipVertical: // Works for me - { - cropTextureCoordinates[0] = minX; // 0,1 - cropTextureCoordinates[1] = maxY; - - cropTextureCoordinates[2] = maxX; // 1,1 - cropTextureCoordinates[3] = maxY; - - cropTextureCoordinates[4] = minX; // 0,0 - cropTextureCoordinates[5] = minY; - - cropTextureCoordinates[6] = maxX; // 1,0 - cropTextureCoordinates[7] = minY; - }; break; - case kGPUImageFlipHorizonal: // Works for me - { - cropTextureCoordinates[0] = maxX; // 1,0 - cropTextureCoordinates[1] = minY; - - cropTextureCoordinates[2] = minX; // 0,0 - cropTextureCoordinates[3] = minY; - - cropTextureCoordinates[4] = maxX; // 1,1 - cropTextureCoordinates[5] = maxY; - - cropTextureCoordinates[6] = minX; // 0,1 - cropTextureCoordinates[7] = maxY; - }; break; - case kGPUImageRotate180: // Fixed - { - cropTextureCoordinates[0] = maxX; // 1,1 - cropTextureCoordinates[1] = maxY; - - cropTextureCoordinates[2] = minX; // 0,1 - cropTextureCoordinates[3] = maxY; - - cropTextureCoordinates[4] = maxX; // 1,0 - cropTextureCoordinates[5] = minY; - - cropTextureCoordinates[6] = minX; // 0,0 - cropTextureCoordinates[7] = minY; - }; break; - case kGPUImageRotateRightFlipVertical: // Fixed - { - cropTextureCoordinates[0] = minY; // 0,0 - cropTextureCoordinates[1] = 1.0 - maxX; - - cropTextureCoordinates[2] = minY; // 0,1 - cropTextureCoordinates[3] = 1.0 - minX; - - cropTextureCoordinates[4] = maxY; // 1,0 - cropTextureCoordinates[5] = 1.0 - maxX; - - cropTextureCoordinates[6] = maxY; // 1,1 - cropTextureCoordinates[7] = 1.0 - minX; - }; break; - case kGPUImageRotateRightFlipHorizontal: // Fixed - { - cropTextureCoordinates[0] = maxY; // 1,1 - cropTextureCoordinates[1] = 1.0 - minX; - - cropTextureCoordinates[2] = maxY; // 1,0 - cropTextureCoordinates[3] = 1.0 - maxX; - - cropTextureCoordinates[4] = minY; // 0,1 - cropTextureCoordinates[5] = 1.0 - minX; - - cropTextureCoordinates[6] = minY; // 0,0 - cropTextureCoordinates[7] = 1.0 - maxX; - }; break; - } -} - -- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex; -{ - static const GLfloat cropSquareVertices[] = { - -1.0f, -1.0f, - 1.0f, -1.0f, - -1.0f, 1.0f, - 1.0f, 1.0f, - }; - - [self renderToTextureWithVertices:cropSquareVertices textureCoordinates:cropTextureCoordinates]; - - [self informTargetsAboutNewFrameAtTime:frameTime]; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setCropRegion:(CGRect)newValue; -{ - NSParameterAssert(newValue.origin.x >= 0 && newValue.origin.x <= 1 && - newValue.origin.y >= 0 && newValue.origin.y <= 1 && - newValue.size.width >= 0 && newValue.size.width <= 1 && - newValue.size.height >= 0 && newValue.size.height <= 1); - - _cropRegion = newValue; - [self calculateCropTextureCoordinates]; -} - -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -{ - [super setInputRotation:newInputRotation atIndex:textureIndex]; - [self calculateCropTextureCoordinates]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCrosshairGenerator.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCrosshairGenerator.h deleted file mode 100644 index 569774f5..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCrosshairGenerator.h +++ /dev/null @@ -1,17 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageCrosshairGenerator : GPUImageFilter -{ - GLint crosshairWidthUniform, crosshairColorUniform; -} - -// The width of the displayed crosshairs, in pixels. Currently this only works well for odd widths. The default is 5. -@property(readwrite, nonatomic) CGFloat crosshairWidth; - -// The color of the crosshairs is specified using individual red, green, and blue components (normalized to 1.0). The default is green: (0.0, 1.0, 0.0). -- (void)setCrosshairColorRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent; - -// Rendering -- (void)renderCrosshairsFromArray:(GLfloat *)crosshairCoordinates count:(NSUInteger)numberOfCrosshairs frameTime:(CMTime)frameTime; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCrosshairGenerator.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCrosshairGenerator.m deleted file mode 100644 index 9e2a29a2..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCrosshairGenerator.m +++ /dev/null @@ -1,139 +0,0 @@ -#import "GPUImageCrosshairGenerator.h" - -NSString *const kGPUImageCrosshairVertexShaderString = SHADER_STRING -( - attribute vec4 position; - - uniform float crosshairWidth; - - varying vec2 centerLocation; - varying float pointSpacing; - - void main() - { - gl_Position = vec4(((position.xy * 2.0) - 1.0), 0.0, 1.0); - gl_PointSize = crosshairWidth + 1.0; - pointSpacing = 1.0 / crosshairWidth; - centerLocation = vec2(pointSpacing * ceil(crosshairWidth / 2.0), pointSpacing * ceil(crosshairWidth / 2.0)); - } -); - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageCrosshairFragmentShaderString = SHADER_STRING -( - uniform lowp vec3 crosshairColor; - - varying highp vec2 centerLocation; - varying highp float pointSpacing; - - void main() - { - lowp vec2 distanceFromCenter = abs(centerLocation - gl_PointCoord.xy); - lowp float axisTest = step(pointSpacing, gl_PointCoord.y) * step(distanceFromCenter.x, 0.09) + step(pointSpacing, gl_PointCoord.x) * step(distanceFromCenter.y, 0.09); - - gl_FragColor = vec4(crosshairColor * axisTest, axisTest); -// gl_FragColor = vec4(distanceFromCenterInX, distanceFromCenterInY, 0.0, 1.0); - } -); -#else -NSString *const kGPUImageCrosshairFragmentShaderString = SHADER_STRING -( - GPUImageEscapedHashIdentifier(version 120)\n - - uniform vec3 crosshairColor; - - varying vec2 centerLocation; - varying float pointSpacing; - - void main() - { - vec2 distanceFromCenter = abs(centerLocation - gl_PointCoord.xy); - float axisTest = step(pointSpacing, gl_PointCoord.y) * step(distanceFromCenter.x, 0.09) + step(pointSpacing, gl_PointCoord.x) * step(distanceFromCenter.y, 0.09); - - gl_FragColor = vec4(crosshairColor * axisTest, axisTest); - // gl_FragColor = vec4(distanceFromCenterInX, distanceFromCenterInY, 0.0, 1.0); - } -); -#endif - -@implementation GPUImageCrosshairGenerator - -@synthesize crosshairWidth = _crosshairWidth; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithVertexShaderFromString:kGPUImageCrosshairVertexShaderString fragmentShaderFromString:kGPUImageCrosshairFragmentShaderString])) - { - return nil; - } - - runSynchronouslyOnVideoProcessingQueue(^{ - crosshairWidthUniform = [filterProgram uniformIndex:@"crosshairWidth"]; - crosshairColorUniform = [filterProgram uniformIndex:@"crosshairColor"]; - - self.crosshairWidth = 5.0; - [self setCrosshairColorRed:0.0 green:1.0 blue:0.0]; - }); - - return self; -} - -#pragma mark - -#pragma mark Rendering - -- (void)renderCrosshairsFromArray:(GLfloat *)crosshairCoordinates count:(NSUInteger)numberOfCrosshairs frameTime:(CMTime)frameTime; -{ - if (self.preventRendering) - { - return; - } - - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext setActiveShaderProgram:filterProgram]; - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -#else - glEnable(GL_POINT_SPRITE); - glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); -#endif - - outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:[self sizeOfFBO] textureOptions:self.outputTextureOptions onlyTexture:NO]; - [outputFramebuffer activateFramebuffer]; - - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - - glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, crosshairCoordinates); - - glDrawArrays(GL_POINTS, 0, (GLsizei)numberOfCrosshairs); - - [self informTargetsAboutNewFrameAtTime:frameTime]; - }); -} - -- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates; -{ - // Prevent rendering of the frame by normal means -} - -#pragma mark - -#pragma mark Accessors - -- (void)setCrosshairWidth:(CGFloat)newValue; -{ - _crosshairWidth = newValue; - - [self setFloat:_crosshairWidth forUniform:crosshairWidthUniform program:filterProgram]; -} - -- (void)setCrosshairColorRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent; -{ - GPUVector3 crosshairColor = {redComponent, greenComponent, blueComponent}; - - [self setVec3:crosshairColor forUniform:crosshairColorUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCrosshatchFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCrosshatchFilter.h deleted file mode 100755 index dab18967..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCrosshatchFilter.h +++ /dev/null @@ -1,13 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageCrosshatchFilter : GPUImageFilter -{ - GLint crossHatchSpacingUniform, lineWidthUniform; -} -// The fractional width of the image to use as the spacing for the crosshatch. The default is 0.03. -@property(readwrite, nonatomic) CGFloat crossHatchSpacing; - -// A relative width for the crosshatch lines. The default is 0.003. -@property(readwrite, nonatomic) CGFloat lineWidth; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCrosshatchFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCrosshatchFilter.m deleted file mode 100755 index 51dbd592..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageCrosshatchFilter.m +++ /dev/null @@ -1,163 +0,0 @@ -#import "GPUImageCrosshatchFilter.h" - -// Shader code based on http://machinesdontcare.wordpress.com/ - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageCrosshatchFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform highp float crossHatchSpacing; - uniform highp float lineWidth; - - const highp vec3 W = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - highp float luminance = dot(texture2D(inputImageTexture, textureCoordinate).rgb, W); - - lowp vec4 colorToDisplay = vec4(1.0, 1.0, 1.0, 1.0); - if (luminance < 1.00) - { - if (mod(textureCoordinate.x + textureCoordinate.y, crossHatchSpacing) <= lineWidth) - { - colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0); - } - } - if (luminance < 0.75) - { - if (mod(textureCoordinate.x - textureCoordinate.y, crossHatchSpacing) <= lineWidth) - { - colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0); - } - } - if (luminance < 0.50) - { - if (mod(textureCoordinate.x + textureCoordinate.y - (crossHatchSpacing / 2.0), crossHatchSpacing) <= lineWidth) - { - colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0); - } - } - if (luminance < 0.3) - { - if (mod(textureCoordinate.x - textureCoordinate.y - (crossHatchSpacing / 2.0), crossHatchSpacing) <= lineWidth) - { - colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0); - } - } - - gl_FragColor = colorToDisplay; - } -); -#else -NSString *const kGPUImageCrosshatchFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform float crossHatchSpacing; - uniform float lineWidth; - - const vec3 W = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - float luminance = dot(texture2D(inputImageTexture, textureCoordinate).rgb, W); - - vec4 colorToDisplay = vec4(1.0, 1.0, 1.0, 1.0); - if (luminance < 1.00) - { - if (mod(textureCoordinate.x + textureCoordinate.y, crossHatchSpacing) <= lineWidth) - { - colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0); - } - } - if (luminance < 0.75) - { - if (mod(textureCoordinate.x - textureCoordinate.y, crossHatchSpacing) <= lineWidth) - { - colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0); - } - } - if (luminance < 0.50) - { - if (mod(textureCoordinate.x + textureCoordinate.y - (crossHatchSpacing / 2.0), crossHatchSpacing) <= lineWidth) - { - colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0); - } - } - if (luminance < 0.3) - { - if (mod(textureCoordinate.x - textureCoordinate.y - (crossHatchSpacing / 2.0), crossHatchSpacing) <= lineWidth) - { - colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0); - } - } - - gl_FragColor = colorToDisplay; - } -); -#endif - -@implementation GPUImageCrosshatchFilter - -@synthesize crossHatchSpacing = _crossHatchSpacing; -@synthesize lineWidth = _lineWidth; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageCrosshatchFragmentShaderString])) - { - return nil; - } - - crossHatchSpacingUniform = [filterProgram uniformIndex:@"crossHatchSpacing"]; - lineWidthUniform = [filterProgram uniformIndex:@"lineWidth"]; - - self.crossHatchSpacing = 0.03; - self.lineWidth = 0.003; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setCrossHatchSpacing:(CGFloat)newValue; -{ - CGFloat singlePixelSpacing; - if (inputTextureSize.width != 0.0) - { - singlePixelSpacing = 1.0 / inputTextureSize.width; - } - else - { - singlePixelSpacing = 1.0 / 2048.0; - } - - if (newValue < singlePixelSpacing) - { - _crossHatchSpacing = singlePixelSpacing; - } - else - { - _crossHatchSpacing = newValue; - } - - [self setFloat:_crossHatchSpacing forUniform:crossHatchSpacingUniform program:filterProgram]; -} - -- (void)setLineWidth:(CGFloat)newValue; -{ - _lineWidth = newValue; - - [self setFloat:_lineWidth forUniform:lineWidthUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDarkenBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDarkenBlendFilter.h deleted file mode 100755 index 5dfe3405..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDarkenBlendFilter.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageDarkenBlendFilter : GPUImageTwoInputFilter -{ -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDarkenBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDarkenBlendFilter.m deleted file mode 100644 index 85ec9e8a..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDarkenBlendFilter.m +++ /dev/null @@ -1,52 +0,0 @@ -#import "GPUImageDarkenBlendFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageDarkenBlendFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - lowp vec4 base = texture2D(inputImageTexture, textureCoordinate); - lowp vec4 overlayer = texture2D(inputImageTexture2, textureCoordinate2); - - gl_FragColor = vec4(min(overlayer.rgb * base.a, base.rgb * overlayer.a) + overlayer.rgb * (1.0 - base.a) + base.rgb * (1.0 - overlayer.a), 1.0); - } -); -#else -NSString *const kGPUImageDarkenBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 base = texture2D(inputImageTexture, textureCoordinate); - vec4 overlayer = texture2D(inputImageTexture2, textureCoordinate2); - - gl_FragColor = vec4(min(overlayer.rgb * base.a, base.rgb * overlayer.a) + overlayer.rgb * (1.0 - base.a) + base.rgb * (1.0 - overlayer.a), 1.0); - } - ); -#endif - -@implementation GPUImageDarkenBlendFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageDarkenBlendFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDifferenceBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDifferenceBlendFilter.h deleted file mode 100755 index 7c7dfc23..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDifferenceBlendFilter.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageDifferenceBlendFilter : GPUImageTwoInputFilter -{ -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDifferenceBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDifferenceBlendFilter.m deleted file mode 100755 index 01bf09b2..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDifferenceBlendFilter.m +++ /dev/null @@ -1,50 +0,0 @@ -#import "GPUImageDifferenceBlendFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageDifferenceBlendFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - mediump vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - mediump vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2); - gl_FragColor = vec4(abs(textureColor2.rgb - textureColor.rgb), textureColor.a); - } -); -#else -NSString *const kGPUImageDifferenceBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2); - gl_FragColor = vec4(abs(textureColor2.rgb - textureColor.rgb), textureColor.a); - } -); -#endif - -@implementation GPUImageDifferenceBlendFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageDifferenceBlendFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDilationFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDilationFilter.h deleted file mode 100644 index 59423a37..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDilationFilter.h +++ /dev/null @@ -1,16 +0,0 @@ -#import "GPUImageTwoPassTextureSamplingFilter.h" - -// For each pixel, this sets it to the maximum value of the red channel in a rectangular neighborhood extending out dilationRadius pixels from the center. -// This extends out bright features, and is most commonly used with black-and-white thresholded images. - -extern NSString *const kGPUImageDilationRadiusOneVertexShaderString; -extern NSString *const kGPUImageDilationRadiusTwoVertexShaderString; -extern NSString *const kGPUImageDilationRadiusThreeVertexShaderString; -extern NSString *const kGPUImageDilationRadiusFourVertexShaderString; - -@interface GPUImageDilationFilter : GPUImageTwoPassTextureSamplingFilter - -// Acceptable values for dilationRadius, which sets the distance in pixels to sample out from the center, are 1, 2, 3, and 4. -- (id)initWithRadius:(NSUInteger)dilationRadius; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDilationFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDilationFilter.m deleted file mode 100644 index df065185..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDilationFilter.m +++ /dev/null @@ -1,431 +0,0 @@ -#import "GPUImageDilationFilter.h" - -@implementation GPUImageDilationFilter - -NSString *const kGPUImageDilationRadiusOneVertexShaderString = SHADER_STRING -( - attribute vec4 position; - attribute vec2 inputTextureCoordinate; - - uniform float texelWidthOffset; - uniform float texelHeightOffset; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - - void main() - { - gl_Position = position; - - vec2 offset = vec2(texelWidthOffset, texelHeightOffset); - - centerTextureCoordinate = inputTextureCoordinate; - oneStepNegativeTextureCoordinate = inputTextureCoordinate - offset; - oneStepPositiveTextureCoordinate = inputTextureCoordinate + offset; - } -); - -NSString *const kGPUImageDilationRadiusTwoVertexShaderString = SHADER_STRING -( - attribute vec4 position; - attribute vec2 inputTextureCoordinate; - - uniform float texelWidthOffset; - uniform float texelHeightOffset; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - - void main() - { - gl_Position = position; - - vec2 offset = vec2(texelWidthOffset, texelHeightOffset); - - centerTextureCoordinate = inputTextureCoordinate; - oneStepNegativeTextureCoordinate = inputTextureCoordinate - offset; - oneStepPositiveTextureCoordinate = inputTextureCoordinate + offset; - twoStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 2.0); - twoStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 2.0); - } -); - -NSString *const kGPUImageDilationRadiusThreeVertexShaderString = SHADER_STRING -( - attribute vec4 position; - attribute vec2 inputTextureCoordinate; - - uniform float texelWidthOffset; - uniform float texelHeightOffset; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - varying vec2 threeStepsPositiveTextureCoordinate; - varying vec2 threeStepsNegativeTextureCoordinate; - - void main() - { - gl_Position = position; - - vec2 offset = vec2(texelWidthOffset, texelHeightOffset); - - centerTextureCoordinate = inputTextureCoordinate; - oneStepNegativeTextureCoordinate = inputTextureCoordinate - offset; - oneStepPositiveTextureCoordinate = inputTextureCoordinate + offset; - twoStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 2.0); - twoStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 2.0); - threeStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 3.0); - threeStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 3.0); - } -); - -NSString *const kGPUImageDilationRadiusFourVertexShaderString = SHADER_STRING -( - attribute vec4 position; - attribute vec2 inputTextureCoordinate; - - uniform float texelWidthOffset; - uniform float texelHeightOffset; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - varying vec2 threeStepsPositiveTextureCoordinate; - varying vec2 threeStepsNegativeTextureCoordinate; - varying vec2 fourStepsPositiveTextureCoordinate; - varying vec2 fourStepsNegativeTextureCoordinate; - - void main() - { - gl_Position = position; - - vec2 offset = vec2(texelWidthOffset, texelHeightOffset); - - centerTextureCoordinate = inputTextureCoordinate; - oneStepNegativeTextureCoordinate = inputTextureCoordinate - offset; - oneStepPositiveTextureCoordinate = inputTextureCoordinate + offset; - twoStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 2.0); - twoStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 2.0); - threeStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 3.0); - threeStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 3.0); - fourStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 4.0); - fourStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 4.0); - } -); - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageDilationRadiusOneFragmentShaderString = SHADER_STRING -( - precision lowp float; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r; - float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r; - float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r; - - lowp float maxValue = max(centerIntensity, oneStepPositiveIntensity); - maxValue = max(maxValue, oneStepNegativeIntensity); - - gl_FragColor = vec4(vec3(maxValue), 1.0); - } -); - -NSString *const kGPUImageDilationRadiusTwoFragmentShaderString = SHADER_STRING -( - precision lowp float; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r; - float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r; - float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r; - float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r; - float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r; - - lowp float maxValue = max(centerIntensity, oneStepPositiveIntensity); - maxValue = max(maxValue, oneStepNegativeIntensity); - maxValue = max(maxValue, twoStepsPositiveIntensity); - maxValue = max(maxValue, twoStepsNegativeIntensity); - - gl_FragColor = vec4(vec3(maxValue), 1.0); - } -); - -NSString *const kGPUImageDilationRadiusThreeFragmentShaderString = SHADER_STRING -( - precision lowp float; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - varying vec2 threeStepsPositiveTextureCoordinate; - varying vec2 threeStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r; - float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r; - float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r; - float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r; - float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r; - float threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate).r; - float threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate).r; - - lowp float maxValue = max(centerIntensity, oneStepPositiveIntensity); - maxValue = max(maxValue, oneStepNegativeIntensity); - maxValue = max(maxValue, twoStepsPositiveIntensity); - maxValue = max(maxValue, twoStepsNegativeIntensity); - maxValue = max(maxValue, threeStepsPositiveIntensity); - maxValue = max(maxValue, threeStepsNegativeIntensity); - - gl_FragColor = vec4(vec3(maxValue), 1.0); - } -); - -NSString *const kGPUImageDilationRadiusFourFragmentShaderString = SHADER_STRING -( - precision lowp float; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - varying vec2 threeStepsPositiveTextureCoordinate; - varying vec2 threeStepsNegativeTextureCoordinate; - varying vec2 fourStepsPositiveTextureCoordinate; - varying vec2 fourStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r; - float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r; - float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r; - float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r; - float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r; - float threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate).r; - float threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate).r; - float fourStepsPositiveIntensity = texture2D(inputImageTexture, fourStepsPositiveTextureCoordinate).r; - float fourStepsNegativeIntensity = texture2D(inputImageTexture, fourStepsNegativeTextureCoordinate).r; - - lowp float maxValue = max(centerIntensity, oneStepPositiveIntensity); - maxValue = max(maxValue, oneStepNegativeIntensity); - maxValue = max(maxValue, twoStepsPositiveIntensity); - maxValue = max(maxValue, twoStepsNegativeIntensity); - maxValue = max(maxValue, threeStepsPositiveIntensity); - maxValue = max(maxValue, threeStepsNegativeIntensity); - maxValue = max(maxValue, fourStepsPositiveIntensity); - maxValue = max(maxValue, fourStepsNegativeIntensity); - - gl_FragColor = vec4(vec3(maxValue), 1.0); - } -); -#else -NSString *const kGPUImageDilationRadiusOneFragmentShaderString = SHADER_STRING -( - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r; - float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r; - float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r; - - float maxValue = max(centerIntensity, oneStepPositiveIntensity); - maxValue = max(maxValue, oneStepNegativeIntensity); - - gl_FragColor = vec4(vec3(maxValue), 1.0); - } -); - -NSString *const kGPUImageDilationRadiusTwoFragmentShaderString = SHADER_STRING -( - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r; - float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r; - float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r; - float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r; - float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r; - - float maxValue = max(centerIntensity, oneStepPositiveIntensity); - maxValue = max(maxValue, oneStepNegativeIntensity); - maxValue = max(maxValue, twoStepsPositiveIntensity); - maxValue = max(maxValue, twoStepsNegativeIntensity); - - gl_FragColor = vec4(vec3(maxValue), 1.0); - } -); - -NSString *const kGPUImageDilationRadiusThreeFragmentShaderString = SHADER_STRING -( - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - varying vec2 threeStepsPositiveTextureCoordinate; - varying vec2 threeStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r; - float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r; - float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r; - float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r; - float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r; - float threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate).r; - float threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate).r; - - float maxValue = max(centerIntensity, oneStepPositiveIntensity); - maxValue = max(maxValue, oneStepNegativeIntensity); - maxValue = max(maxValue, twoStepsPositiveIntensity); - maxValue = max(maxValue, twoStepsNegativeIntensity); - maxValue = max(maxValue, threeStepsPositiveIntensity); - maxValue = max(maxValue, threeStepsNegativeIntensity); - - gl_FragColor = vec4(vec3(maxValue), 1.0); - } -); - -NSString *const kGPUImageDilationRadiusFourFragmentShaderString = SHADER_STRING -( - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - varying vec2 threeStepsPositiveTextureCoordinate; - varying vec2 threeStepsNegativeTextureCoordinate; - varying vec2 fourStepsPositiveTextureCoordinate; - varying vec2 fourStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r; - float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r; - float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r; - float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r; - float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r; - float threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate).r; - float threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate).r; - float fourStepsPositiveIntensity = texture2D(inputImageTexture, fourStepsPositiveTextureCoordinate).r; - float fourStepsNegativeIntensity = texture2D(inputImageTexture, fourStepsNegativeTextureCoordinate).r; - - float maxValue = max(centerIntensity, oneStepPositiveIntensity); - maxValue = max(maxValue, oneStepNegativeIntensity); - maxValue = max(maxValue, twoStepsPositiveIntensity); - maxValue = max(maxValue, twoStepsNegativeIntensity); - maxValue = max(maxValue, threeStepsPositiveIntensity); - maxValue = max(maxValue, threeStepsNegativeIntensity); - maxValue = max(maxValue, fourStepsPositiveIntensity); - maxValue = max(maxValue, fourStepsNegativeIntensity); - - gl_FragColor = vec4(vec3(maxValue), 1.0); - } -); -#endif - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithRadius:(NSUInteger)dilationRadius; -{ - NSString *fragmentShaderForThisRadius = nil; - NSString *vertexShaderForThisRadius = nil; - - switch (dilationRadius) - { - case 0: - case 1: - { - vertexShaderForThisRadius = kGPUImageDilationRadiusOneVertexShaderString; - fragmentShaderForThisRadius = kGPUImageDilationRadiusOneFragmentShaderString; - }; break; - case 2: - { - vertexShaderForThisRadius = kGPUImageDilationRadiusTwoVertexShaderString; - fragmentShaderForThisRadius = kGPUImageDilationRadiusTwoFragmentShaderString; - }; break; - case 3: - { - vertexShaderForThisRadius = kGPUImageDilationRadiusThreeVertexShaderString; - fragmentShaderForThisRadius = kGPUImageDilationRadiusThreeFragmentShaderString; - }; break; - case 4: - { - vertexShaderForThisRadius = kGPUImageDilationRadiusFourVertexShaderString; - fragmentShaderForThisRadius = kGPUImageDilationRadiusFourFragmentShaderString; - }; break; - default: - { - vertexShaderForThisRadius = kGPUImageDilationRadiusFourVertexShaderString; - fragmentShaderForThisRadius = kGPUImageDilationRadiusFourFragmentShaderString; - }; break; - } - - if (!(self = [super initWithFirstStageVertexShaderFromString:vertexShaderForThisRadius firstStageFragmentShaderFromString:fragmentShaderForThisRadius secondStageVertexShaderFromString:vertexShaderForThisRadius secondStageFragmentShaderFromString:fragmentShaderForThisRadius])) - { - return nil; - } - - return self; -} - -- (id)init; -{ - if (!(self = [self initWithRadius:1])) - { - return nil; - } - - return self; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDirectionalNonMaximumSuppressionFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDirectionalNonMaximumSuppressionFilter.h deleted file mode 100644 index fdffb9fb..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDirectionalNonMaximumSuppressionFilter.h +++ /dev/null @@ -1,19 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageDirectionalNonMaximumSuppressionFilter : GPUImageFilter -{ - GLint texelWidthUniform, texelHeightUniform; - GLint upperThresholdUniform, lowerThresholdUniform; - - BOOL hasOverriddenImageSizeFactor; -} - -// The texel width and height determines how far out to sample from this texel. By default, this is the normalized width of a pixel, but this can be overridden for different effects. -@property(readwrite, nonatomic) CGFloat texelWidth; -@property(readwrite, nonatomic) CGFloat texelHeight; - -// These thresholds set cutoffs for the intensities that definitely get registered (upper threshold) and those that definitely don't (lower threshold) -@property(readwrite, nonatomic) CGFloat upperThreshold; -@property(readwrite, nonatomic) CGFloat lowerThreshold; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDirectionalNonMaximumSuppressionFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDirectionalNonMaximumSuppressionFilter.m deleted file mode 100644 index b442f3aa..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDirectionalNonMaximumSuppressionFilter.m +++ /dev/null @@ -1,141 +0,0 @@ -#import "GPUImageDirectionalNonMaximumSuppressionFilter.h" - -@implementation GPUImageDirectionalNonMaximumSuppressionFilter - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageDirectionalNonmaximumSuppressionFragmentShaderString = SHADER_STRING -( - precision mediump float; - - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform highp float texelWidth; - uniform highp float texelHeight; - uniform mediump float upperThreshold; - uniform mediump float lowerThreshold; - - void main() - { - vec3 currentGradientAndDirection = texture2D(inputImageTexture, textureCoordinate).rgb; - vec2 gradientDirection = ((currentGradientAndDirection.gb * 2.0) - 1.0) * vec2(texelWidth, texelHeight); - - float firstSampledGradientMagnitude = texture2D(inputImageTexture, textureCoordinate + gradientDirection).r; - float secondSampledGradientMagnitude = texture2D(inputImageTexture, textureCoordinate - gradientDirection).r; - - float multiplier = step(firstSampledGradientMagnitude, currentGradientAndDirection.r); - multiplier = multiplier * step(secondSampledGradientMagnitude, currentGradientAndDirection.r); - - float thresholdCompliance = smoothstep(lowerThreshold, upperThreshold, currentGradientAndDirection.r); - multiplier = multiplier * thresholdCompliance; - - gl_FragColor = vec4(multiplier, multiplier, multiplier, 1.0); - } -); -#else -NSString *const kGPUImageDirectionalNonmaximumSuppressionFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float texelWidth; - uniform float texelHeight; - uniform float upperThreshold; - uniform float lowerThreshold; - - void main() - { - vec3 currentGradientAndDirection = texture2D(inputImageTexture, textureCoordinate).rgb; - vec2 gradientDirection = ((currentGradientAndDirection.gb * 2.0) - 1.0) * vec2(texelWidth, texelHeight); - - float firstSampledGradientMagnitude = texture2D(inputImageTexture, textureCoordinate + gradientDirection).r; - float secondSampledGradientMagnitude = texture2D(inputImageTexture, textureCoordinate - gradientDirection).r; - - float multiplier = step(firstSampledGradientMagnitude, currentGradientAndDirection.r); - multiplier = multiplier * step(secondSampledGradientMagnitude, currentGradientAndDirection.r); - - float thresholdCompliance = smoothstep(lowerThreshold, upperThreshold, currentGradientAndDirection.r); - multiplier = multiplier * thresholdCompliance; - - gl_FragColor = vec4(multiplier, multiplier, multiplier, 1.0); - } -); -#endif - -@synthesize texelWidth = _texelWidth; -@synthesize texelHeight = _texelHeight; -@synthesize upperThreshold = _upperThreshold; -@synthesize lowerThreshold = _lowerThreshold; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageDirectionalNonmaximumSuppressionFragmentShaderString])) - { - return nil; - } - - texelWidthUniform = [filterProgram uniformIndex:@"texelWidth"]; - texelHeightUniform = [filterProgram uniformIndex:@"texelHeight"]; - upperThresholdUniform = [filterProgram uniformIndex:@"upperThreshold"]; - lowerThresholdUniform = [filterProgram uniformIndex:@"lowerThreshold"]; - - self.upperThreshold = 0.5; - self.lowerThreshold = 0.1; - - return self; -} - -- (void)setupFilterForSize:(CGSize)filterFrameSize; -{ - if (!hasOverriddenImageSizeFactor) - { - _texelWidth = 1.0 / filterFrameSize.width; - _texelHeight = 1.0 / filterFrameSize.height; - - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext setActiveShaderProgram:filterProgram]; - glUniform1f(texelWidthUniform, _texelWidth); - glUniform1f(texelHeightUniform, _texelHeight); - }); - } -} - -#pragma mark - -#pragma mark Accessors - -- (void)setTexelWidth:(CGFloat)newValue; -{ - hasOverriddenImageSizeFactor = YES; - _texelWidth = newValue; - - [self setFloat:_texelWidth forUniform:texelWidthUniform program:filterProgram]; -} - -- (void)setTexelHeight:(CGFloat)newValue; -{ - hasOverriddenImageSizeFactor = YES; - _texelHeight = newValue; - - [self setFloat:_texelHeight forUniform:texelHeightUniform program:filterProgram]; -} - -- (void)setLowerThreshold:(CGFloat)newValue; -{ - _lowerThreshold = newValue; - - [self setFloat:_lowerThreshold forUniform:lowerThresholdUniform program:filterProgram]; -} - -- (void)setUpperThreshold:(CGFloat)newValue; -{ - _upperThreshold = newValue; - - [self setFloat:_upperThreshold forUniform:upperThresholdUniform program:filterProgram]; -} - - - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDirectionalSobelEdgeDetectionFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDirectionalSobelEdgeDetectionFilter.h deleted file mode 100644 index cfccc897..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDirectionalSobelEdgeDetectionFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImage3x3TextureSamplingFilter.h" - -@interface GPUImageDirectionalSobelEdgeDetectionFilter : GPUImage3x3TextureSamplingFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDirectionalSobelEdgeDetectionFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDirectionalSobelEdgeDetectionFilter.m deleted file mode 100644 index a3575e3a..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDirectionalSobelEdgeDetectionFilter.m +++ /dev/null @@ -1,103 +0,0 @@ -#import "GPUImageDirectionalSobelEdgeDetectionFilter.h" - -@implementation GPUImageDirectionalSobelEdgeDetectionFilter - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageDirectionalSobelEdgeDetectionFragmentShaderString = SHADER_STRING -( - precision mediump float; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r; - float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r; - float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r; - float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r; - float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r; - - vec2 gradientDirection; - gradientDirection.x = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity; - gradientDirection.y = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity; - - float gradientMagnitude = length(gradientDirection); - vec2 normalizedDirection = normalize(gradientDirection); - normalizedDirection = sign(normalizedDirection) * floor(abs(normalizedDirection) + 0.617316); // Offset by 1-sin(pi/8) to set to 0 if near axis, 1 if away - normalizedDirection = (normalizedDirection + 1.0) * 0.5; // Place -1.0 - 1.0 within 0 - 1.0 - - gl_FragColor = vec4(gradientMagnitude, normalizedDirection.x, normalizedDirection.y, 1.0); - } -); -#else -NSString *const kGPUImageDirectionalSobelEdgeDetectionFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r; - float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r; - float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r; - float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r; - float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r; - - vec2 gradientDirection; - gradientDirection.x = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity; - gradientDirection.y = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity; - - float gradientMagnitude = length(gradientDirection); - vec2 normalizedDirection = normalize(gradientDirection); - normalizedDirection = sign(normalizedDirection) * floor(abs(normalizedDirection) + 0.617316); // Offset by 1-sin(pi/8) to set to 0 if near axis, 1 if away - normalizedDirection = (normalizedDirection + 1.0) * 0.5; // Place -1.0 - 1.0 within 0 - 1.0 - - gl_FragColor = vec4(gradientMagnitude, normalizedDirection.x, normalizedDirection.y, 1.0); - } -); -#endif - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageDirectionalSobelEdgeDetectionFragmentShaderString])) - { - return nil; - } - - return self; -} - - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDissolveBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDissolveBlendFilter.h deleted file mode 100755 index b4e5720a..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDissolveBlendFilter.h +++ /dev/null @@ -1,11 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageDissolveBlendFilter : GPUImageTwoInputFilter -{ - GLint mixUniform; -} - -// Mix ranges from 0.0 (only image 1) to 1.0 (only image 2), with 0.5 (half of either) as the normal level -@property(readwrite, nonatomic) CGFloat mix; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDissolveBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDissolveBlendFilter.m deleted file mode 100755 index b4a5609f..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDissolveBlendFilter.m +++ /dev/null @@ -1,72 +0,0 @@ -#import "GPUImageDissolveBlendFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageDissolveBlendFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - uniform lowp float mixturePercent; - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - lowp vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2); - - gl_FragColor = mix(textureColor, textureColor2, mixturePercent); - } -); -#else -NSString *const kGPUImageDissolveBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - uniform float mixturePercent; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2); - - gl_FragColor = mix(textureColor, textureColor2, mixturePercent); - } -); -#endif - -@implementation GPUImageDissolveBlendFilter - -@synthesize mix = _mix; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageDissolveBlendFragmentShaderString])) - { - return nil; - } - - mixUniform = [filterProgram uniformIndex:@"mixturePercent"]; - self.mix = 0.5; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setMix:(CGFloat)newValue; -{ - _mix = newValue; - - [self setFloat:_mix forUniform:mixUniform program:filterProgram]; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDivideBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDivideBlendFilter.h deleted file mode 100644 index ad798e29..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDivideBlendFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageDivideBlendFilter : GPUImageTwoInputFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDivideBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDivideBlendFilter.m deleted file mode 100644 index 63ee071e..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageDivideBlendFilter.m +++ /dev/null @@ -1,96 +0,0 @@ -#import "GPUImageDivideBlendFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageDivideBlendFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - mediump vec4 base = texture2D(inputImageTexture, textureCoordinate); - mediump vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2); - - mediump float ra; - if (overlay.a == 0.0 || ((base.r / overlay.r) > (base.a / overlay.a))) - ra = overlay.a * base.a + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a); - else - ra = (base.r * overlay.a * overlay.a) / overlay.r + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a); - - - mediump float ga; - if (overlay.a == 0.0 || ((base.g / overlay.g) > (base.a / overlay.a))) - ga = overlay.a * base.a + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a); - else - ga = (base.g * overlay.a * overlay.a) / overlay.g + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a); - - - mediump float ba; - if (overlay.a == 0.0 || ((base.b / overlay.b) > (base.a / overlay.a))) - ba = overlay.a * base.a + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a); - else - ba = (base.b * overlay.a * overlay.a) / overlay.b + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a); - - mediump float a = overlay.a + base.a - overlay.a * base.a; - - gl_FragColor = vec4(ra, ga, ba, a); - } -); -#else -NSString *const kGPUImageDivideBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 base = texture2D(inputImageTexture, textureCoordinate); - vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2); - - float ra; - if (overlay.a == 0.0 || ((base.r / overlay.r) > (base.a / overlay.a))) - ra = overlay.a * base.a + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a); - else - ra = (base.r * overlay.a * overlay.a) / overlay.r + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a); - - - float ga; - if (overlay.a == 0.0 || ((base.g / overlay.g) > (base.a / overlay.a))) - ga = overlay.a * base.a + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a); - else - ga = (base.g * overlay.a * overlay.a) / overlay.g + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a); - - - float ba; - if (overlay.a == 0.0 || ((base.b / overlay.b) > (base.a / overlay.a))) - ba = overlay.a * base.a + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a); - else - ba = (base.b * overlay.a * overlay.a) / overlay.b + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a); - - float a = overlay.a + base.a - overlay.a * base.a; - - gl_FragColor = vec4(ra, ga, ba, a); - } - ); -#endif - -@implementation GPUImageDivideBlendFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageDivideBlendFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageEmbossFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageEmbossFilter.h deleted file mode 100755 index dbd21e82..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageEmbossFilter.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "GPUImage3x3ConvolutionFilter.h" - -@interface GPUImageEmbossFilter : GPUImage3x3ConvolutionFilter - -// The strength of the embossing, from 0.0 to 4.0, with 1.0 as the normal level -@property(readwrite, nonatomic) CGFloat intensity; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageEmbossFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageEmbossFilter.m deleted file mode 100755 index 6ba48cd4..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageEmbossFilter.m +++ /dev/null @@ -1,49 +0,0 @@ -#import "GPUImageEmbossFilter.h" - -@implementation GPUImageEmbossFilter - -@synthesize intensity = _intensity; - -- (id)init; -{ - if (!(self = [super init])) - { - return nil; - } - - self.intensity = 1.0; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setIntensity:(CGFloat)newValue; -{ -// [(GPUImage3x3ConvolutionFilter *)filter setConvolutionMatrix:(GPUMatrix3x3){ -// {-2.0f, -1.0f, 0.0f}, -// {-1.0f, 1.0f, 1.0f}, -// { 0.0f, 1.0f, 2.0f} -// }]; - - _intensity = newValue; - - GPUMatrix3x3 newConvolutionMatrix; - newConvolutionMatrix.one.one = _intensity * (-2.0); - newConvolutionMatrix.one.two = -_intensity; - newConvolutionMatrix.one.three = 0.0f; - - newConvolutionMatrix.two.one = -_intensity; - newConvolutionMatrix.two.two = 1.0; - newConvolutionMatrix.two.three = _intensity; - - newConvolutionMatrix.three.one = 0.0f; - newConvolutionMatrix.three.two = _intensity; - newConvolutionMatrix.three.three = _intensity * 2.0; - - self.convolutionKernel = newConvolutionMatrix; -} - - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageErosionFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageErosionFilter.h deleted file mode 100644 index b311a265..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageErosionFilter.h +++ /dev/null @@ -1,11 +0,0 @@ -#import "GPUImageTwoPassTextureSamplingFilter.h" - -// For each pixel, this sets it to the minimum value of the red channel in a rectangular neighborhood extending out dilationRadius pixels from the center. -// This extends out dark features, and is most commonly used with black-and-white thresholded images. - -@interface GPUImageErosionFilter : GPUImageTwoPassTextureSamplingFilter - -// Acceptable values for erosionRadius, which sets the distance in pixels to sample out from the center, are 1, 2, 3, and 4. -- (id)initWithRadius:(NSUInteger)erosionRadius; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageErosionFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageErosionFilter.m deleted file mode 100644 index 05f4f28d..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageErosionFilter.m +++ /dev/null @@ -1,312 +0,0 @@ -#import "GPUImageErosionFilter.h" -#import "GPUImageDilationFilter.h" - -@implementation GPUImageErosionFilter - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageErosionRadiusOneFragmentShaderString = SHADER_STRING -( - precision lowp float; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r; - float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r; - float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r; - - lowp float minValue = min(centerIntensity, oneStepPositiveIntensity); - minValue = min(minValue, oneStepNegativeIntensity); - - gl_FragColor = vec4(vec3(minValue), 1.0); - } -); - -NSString *const kGPUImageErosionRadiusTwoFragmentShaderString = SHADER_STRING -( - precision lowp float; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r; - float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r; - float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r; - float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r; - float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r; - - lowp float minValue = min(centerIntensity, oneStepPositiveIntensity); - minValue = min(minValue, oneStepNegativeIntensity); - minValue = min(minValue, twoStepsPositiveIntensity); - minValue = min(minValue, twoStepsNegativeIntensity); - - gl_FragColor = vec4(vec3(minValue), 1.0); - } -); - -NSString *const kGPUImageErosionRadiusThreeFragmentShaderString = SHADER_STRING -( - precision lowp float; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - varying vec2 threeStepsPositiveTextureCoordinate; - varying vec2 threeStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r; - float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r; - float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r; - float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r; - float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r; - float threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate).r; - float threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate).r; - - lowp float minValue = min(centerIntensity, oneStepPositiveIntensity); - minValue = min(minValue, oneStepNegativeIntensity); - minValue = min(minValue, twoStepsPositiveIntensity); - minValue = min(minValue, twoStepsNegativeIntensity); - minValue = min(minValue, threeStepsPositiveIntensity); - minValue = min(minValue, threeStepsNegativeIntensity); - - gl_FragColor = vec4(vec3(minValue), 1.0); - } -); - -NSString *const kGPUImageErosionRadiusFourFragmentShaderString = SHADER_STRING -( - precision lowp float; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - varying vec2 threeStepsPositiveTextureCoordinate; - varying vec2 threeStepsNegativeTextureCoordinate; - varying vec2 fourStepsPositiveTextureCoordinate; - varying vec2 fourStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r; - float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r; - float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r; - float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r; - float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r; - float threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate).r; - float threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate).r; - float fourStepsPositiveIntensity = texture2D(inputImageTexture, fourStepsPositiveTextureCoordinate).r; - float fourStepsNegativeIntensity = texture2D(inputImageTexture, fourStepsNegativeTextureCoordinate).r; - - lowp float minValue = min(centerIntensity, oneStepPositiveIntensity); - minValue = min(minValue, oneStepNegativeIntensity); - minValue = min(minValue, twoStepsPositiveIntensity); - minValue = min(minValue, twoStepsNegativeIntensity); - minValue = min(minValue, threeStepsPositiveIntensity); - minValue = min(minValue, threeStepsNegativeIntensity); - minValue = min(minValue, fourStepsPositiveIntensity); - minValue = min(minValue, fourStepsNegativeIntensity); - - gl_FragColor = vec4(vec3(minValue), 1.0); - } -); -#else -NSString *const kGPUImageErosionRadiusOneFragmentShaderString = SHADER_STRING -( - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r; - float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r; - float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r; - - float minValue = min(centerIntensity, oneStepPositiveIntensity); - minValue = min(minValue, oneStepNegativeIntensity); - - gl_FragColor = vec4(vec3(minValue), 1.0); - } -); - -NSString *const kGPUImageErosionRadiusTwoFragmentShaderString = SHADER_STRING -( - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r; - float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r; - float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r; - float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r; - float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r; - - float minValue = min(centerIntensity, oneStepPositiveIntensity); - minValue = min(minValue, oneStepNegativeIntensity); - minValue = min(minValue, twoStepsPositiveIntensity); - minValue = min(minValue, twoStepsNegativeIntensity); - - gl_FragColor = vec4(vec3(minValue), 1.0); - } -); - -NSString *const kGPUImageErosionRadiusThreeFragmentShaderString = SHADER_STRING -( - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - varying vec2 threeStepsPositiveTextureCoordinate; - varying vec2 threeStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r; - float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r; - float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r; - float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r; - float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r; - float threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate).r; - float threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate).r; - - float minValue = min(centerIntensity, oneStepPositiveIntensity); - minValue = min(minValue, oneStepNegativeIntensity); - minValue = min(minValue, twoStepsPositiveIntensity); - minValue = min(minValue, twoStepsNegativeIntensity); - minValue = min(minValue, threeStepsPositiveIntensity); - minValue = min(minValue, threeStepsNegativeIntensity); - - gl_FragColor = vec4(vec3(minValue), 1.0); - } -); - -NSString *const kGPUImageErosionRadiusFourFragmentShaderString = SHADER_STRING -( - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - varying vec2 threeStepsPositiveTextureCoordinate; - varying vec2 threeStepsNegativeTextureCoordinate; - varying vec2 fourStepsPositiveTextureCoordinate; - varying vec2 fourStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r; - float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r; - float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r; - float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r; - float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r; - float threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate).r; - float threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate).r; - float fourStepsPositiveIntensity = texture2D(inputImageTexture, fourStepsPositiveTextureCoordinate).r; - float fourStepsNegativeIntensity = texture2D(inputImageTexture, fourStepsNegativeTextureCoordinate).r; - - float minValue = min(centerIntensity, oneStepPositiveIntensity); - minValue = min(minValue, oneStepNegativeIntensity); - minValue = min(minValue, twoStepsPositiveIntensity); - minValue = min(minValue, twoStepsNegativeIntensity); - minValue = min(minValue, threeStepsPositiveIntensity); - minValue = min(minValue, threeStepsNegativeIntensity); - minValue = min(minValue, fourStepsPositiveIntensity); - minValue = min(minValue, fourStepsNegativeIntensity); - - gl_FragColor = vec4(vec3(minValue), 1.0); - } -); -#endif - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithRadius:(NSUInteger)dilationRadius; -{ - NSString *fragmentShaderForThisRadius = nil; - NSString *vertexShaderForThisRadius = nil; - - switch (dilationRadius) - { - case 0: - case 1: - { - vertexShaderForThisRadius = kGPUImageDilationRadiusOneVertexShaderString; - fragmentShaderForThisRadius = kGPUImageErosionRadiusOneFragmentShaderString; - }; break; - case 2: - { - vertexShaderForThisRadius = kGPUImageDilationRadiusTwoVertexShaderString; - fragmentShaderForThisRadius = kGPUImageErosionRadiusTwoFragmentShaderString; - }; break; - case 3: - { - vertexShaderForThisRadius = kGPUImageDilationRadiusThreeVertexShaderString; - fragmentShaderForThisRadius = kGPUImageErosionRadiusThreeFragmentShaderString; - }; break; - case 4: - { - vertexShaderForThisRadius = kGPUImageDilationRadiusFourVertexShaderString; - fragmentShaderForThisRadius = kGPUImageErosionRadiusFourFragmentShaderString; - }; break; - default: - { - vertexShaderForThisRadius = kGPUImageDilationRadiusFourVertexShaderString; - fragmentShaderForThisRadius = kGPUImageErosionRadiusFourFragmentShaderString; - }; break; - } - - if (!(self = [super initWithFirstStageVertexShaderFromString:vertexShaderForThisRadius firstStageFragmentShaderFromString:fragmentShaderForThisRadius secondStageVertexShaderFromString:vertexShaderForThisRadius secondStageFragmentShaderFromString:fragmentShaderForThisRadius])) - { - return nil; - } - - return self; -} - -- (id)init; -{ - if (!(self = [self initWithRadius:1])) - { - return nil; - } - - return self; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageExclusionBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageExclusionBlendFilter.h deleted file mode 100755 index f7c83f57..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageExclusionBlendFilter.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageExclusionBlendFilter : GPUImageTwoInputFilter -{ -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageExclusionBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageExclusionBlendFilter.m deleted file mode 100755 index c364159f..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageExclusionBlendFilter.m +++ /dev/null @@ -1,56 +0,0 @@ -#import "GPUImageExclusionBlendFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageExclusionBlendFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - mediump vec4 base = texture2D(inputImageTexture, textureCoordinate); - mediump vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2); - - // Dca = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) - - gl_FragColor = vec4((overlay.rgb * base.a + base.rgb * overlay.a - 2.0 * overlay.rgb * base.rgb) + overlay.rgb * (1.0 - base.a) + base.rgb * (1.0 - overlay.a), base.a); - } -); -#else -NSString *const kGPUImageExclusionBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 base = texture2D(inputImageTexture, textureCoordinate); - vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2); - - // Dca = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) - - gl_FragColor = vec4((overlay.rgb * base.a + base.rgb * overlay.a - 2.0 * overlay.rgb * base.rgb) + overlay.rgb * (1.0 - base.a) + base.rgb * (1.0 - overlay.a), base.a); - } - ); -#endif - -@implementation GPUImageExclusionBlendFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageExclusionBlendFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageExposureFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageExposureFilter.h deleted file mode 100755 index 886a052f..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageExposureFilter.h +++ /dev/null @@ -1,11 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageExposureFilter : GPUImageFilter -{ - GLint exposureUniform; -} - -// Exposure ranges from -10.0 to 10.0, with 0.0 as the normal level -@property(readwrite, nonatomic) CGFloat exposure; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageExposureFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageExposureFilter.m deleted file mode 100755 index d5ee2c9f..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageExposureFilter.m +++ /dev/null @@ -1,66 +0,0 @@ -#import "GPUImageExposureFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageExposureFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform highp float exposure; - - void main() - { - highp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - gl_FragColor = vec4(textureColor.rgb * pow(2.0, exposure), textureColor.w); - } -); -#else -NSString *const kGPUImageExposureFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float exposure; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - gl_FragColor = vec4(textureColor.rgb * pow(2.0, exposure), textureColor.w); - } -); -#endif - -@implementation GPUImageExposureFilter - -@synthesize exposure = _exposure; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageExposureFragmentShaderString])) - { - return nil; - } - - exposureUniform = [filterProgram uniformIndex:@"exposure"]; - self.exposure = 0.0; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setExposure:(CGFloat)newValue; -{ - _exposure = newValue; - - [self setFloat:_exposure forUniform:exposureUniform program:filterProgram]; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFASTCornerDetectionFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFASTCornerDetectionFilter.h deleted file mode 100644 index 86e7cf42..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFASTCornerDetectionFilter.h +++ /dev/null @@ -1,33 +0,0 @@ -#import "GPUImageFilterGroup.h" - -@class GPUImageGrayscaleFilter; -@class GPUImage3x3TextureSamplingFilter; -@class GPUImageNonMaximumSuppressionFilter; - -/* - An implementation of the Features from Accelerated Segment Test (FAST) feature detector as described in the following publications: - - E. Rosten and T. Drummond. Fusing points and lines for high performance tracking. IEEE International Conference on Computer Vision, 2005. - E. Rosten and T. Drummond. Machine learning for high-speed corner detection. European Conference on Computer Vision, 2006. - - For more about the FAST feature detector, see the resources here: - http://www.edwardrosten.com/work/fast.html - */ - -typedef enum { kGPUImageFAST12Contiguous, kGPUImageFAST12ContiguousNonMaximumSuppressed} GPUImageFASTDetectorType; - -@interface GPUImageFASTCornerDetectionFilter : GPUImageFilterGroup -{ - GPUImageGrayscaleFilter *luminanceReductionFilter; - GPUImage3x3TextureSamplingFilter *featureDetectionFilter; - GPUImageNonMaximumSuppressionFilter *nonMaximumSuppressionFilter; -// Generate a lookup texture based on the bit patterns - -// Step 1: convert to monochrome if necessary -// Step 2: do a lookup at each pixel based on the Bresenham circle, encode comparison in two color components -// Step 3: do non-maximum suppression of close corner points -} - -- (id)initWithFASTDetectorVariant:(GPUImageFASTDetectorType)detectorType; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFASTCornerDetectionFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFASTCornerDetectionFilter.m deleted file mode 100644 index b04a24aa..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFASTCornerDetectionFilter.m +++ /dev/null @@ -1,89 +0,0 @@ -#import "GPUImageFASTCornerDetectionFilter.h" - -#import "GPUImageGrayscaleFilter.h" -#import "GPUImage3x3TextureSamplingFilter.h" -#import "GPUImageNonMaximumSuppressionFilter.h" - -// 14 total texture coordinates from vertex shader for non-dependent reads -// 3 texture coordinates for dependent reads, then - -NSString *const kGPUImageFASTDetectorFragmentShaderString = SHADER_STRING -( - precision highp float; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - uniform sampler2D lookupTable; - - void main() - { - lowp float centerIntensity = texture2D(inputImageTexture, textureCoordinate).r; - lowp float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - lowp float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r; - lowp float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - lowp float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - lowp float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r; - lowp float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r; - lowp float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r; - lowp float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r; - - lowp float byteTally = 1.0 / 255.0 * step(centerIntensity, topRightIntensity); - byteTally += 2.0 / 255.0 * step(centerIntensity, topIntensity); - byteTally += 4.0 / 255.0 * step(centerIntensity, topLeftIntensity); - byteTally += 8.0 / 255.0 * step(centerIntensity, leftIntensity); - byteTally += 16.0 / 255.0 * step(centerIntensity, bottomLeftIntensity); - byteTally += 32.0 / 255.0 * step(centerIntensity, bottomIntensity); - byteTally += 64.0 / 255.0 * step(centerIntensity, bottomRightIntensity); - byteTally += 128.0 / 255.0 * step(centerIntensity, rightIntensity); - - // TODO: Replace the above with a dot product and two vec4s - // TODO: Apply step to a matrix, rather than individually - - gl_FragColor = vec4(byteTally, byteTally, byteTally, 1.0); - } - ); - - -@implementation GPUImageFASTCornerDetectionFilter - -- (id)init; -{ - if (!(self = [self initWithFASTDetectorVariant:kGPUImageFAST12ContiguousNonMaximumSuppressed])) - { - return nil; - } - - return self; -} - -- (id)initWithFASTDetectorVariant:(GPUImageFASTDetectorType)detectorType; -{ - if (!(self = [super init])) - { - return nil; - } - -// [derivativeFilter addTarget:blurFilter]; -// [blurFilter addTarget:harrisCornerDetectionFilter]; -// [harrisCornerDetectionFilter addTarget:nonMaximumSuppressionFilter]; - // [simpleThresholdFilter addTarget:colorPackingFilter]; - -// self.initialFilters = [NSArray arrayWithObjects:derivativeFilter, nil]; - // self.terminalFilter = colorPackingFilter; -// self.terminalFilter = nonMaximumSuppressionFilter; - - return self; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFalseColorFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFalseColorFilter.h deleted file mode 100644 index cb0b82f7..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFalseColorFilter.h +++ /dev/null @@ -1,15 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageFalseColorFilter : GPUImageFilter -{ - GLint firstColorUniform, secondColorUniform; -} - -// The first and second colors specify what colors replace the dark and light areas of the image, respectively. The defaults are (0.0, 0.0, 0.5) amd (1.0, 0.0, 0.0). -@property(readwrite, nonatomic) GPUVector4 firstColor; -@property(readwrite, nonatomic) GPUVector4 secondColor; - -- (void)setFirstColorRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent; -- (void)setSecondColorRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFalseColorFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFalseColorFilter.m deleted file mode 100644 index f514dbab..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFalseColorFilter.m +++ /dev/null @@ -1,101 +0,0 @@ -#import "GPUImageFalseColorFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUFalseColorFragmentShaderString = SHADER_STRING -( - precision lowp float; - - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float intensity; - uniform vec3 firstColor; - uniform vec3 secondColor; - - const mediump vec3 luminanceWeighting = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - float luminance = dot(textureColor.rgb, luminanceWeighting); - - gl_FragColor = vec4( mix(firstColor.rgb, secondColor.rgb, luminance), textureColor.a); - } -); -#else -NSString *const kGPUFalseColorFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float intensity; - uniform vec3 firstColor; - uniform vec3 secondColor; - - const vec3 luminanceWeighting = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - float luminance = dot(textureColor.rgb, luminanceWeighting); - - gl_FragColor = vec4( mix(firstColor.rgb, secondColor.rgb, luminance), textureColor.a); - } -); -#endif - - -@implementation GPUImageFalseColorFilter - -@synthesize secondColor = _secondColor; -@synthesize firstColor = _firstColor; - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUFalseColorFragmentShaderString])) - { - return nil; - } - - firstColorUniform = [filterProgram uniformIndex:@"firstColor"]; - secondColorUniform = [filterProgram uniformIndex:@"secondColor"]; - - self.firstColor = (GPUVector4){0.0f, 0.0f, 0.5f, 1.0f}; - self.secondColor = (GPUVector4){1.0f, 0.0f, 0.0f, 1.0f}; - - return self; -} - - -#pragma mark - -#pragma mark Accessors - -- (void)setFirstColor:(GPUVector4)newValue; -{ - _firstColor = newValue; - - [self setFirstColorRed:_firstColor.one green:_firstColor.two blue:_firstColor.three]; -} - -- (void)setSecondColor:(GPUVector4)newValue; -{ - _secondColor = newValue; - - [self setSecondColorRed:_secondColor.one green:_secondColor.two blue:_secondColor.three]; -} - -- (void)setFirstColorRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent; -{ - GPUVector3 firstColor = {redComponent, greenComponent, blueComponent}; - - [self setVec3:firstColor forUniform:firstColorUniform program:filterProgram]; -} - -- (void)setSecondColorRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent; -{ - GPUVector3 secondColor = {redComponent, greenComponent, blueComponent}; - - [self setVec3:secondColor forUniform:secondColorUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilter.h deleted file mode 100755 index 0171aa80..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilter.h +++ /dev/null @@ -1,134 +0,0 @@ -#import "GPUImageOutput.h" - -#define STRINGIZE(x) #x -#define STRINGIZE2(x) STRINGIZE(x) -#define SHADER_STRING(text) @ STRINGIZE2(text) - -#define GPUImageHashIdentifier # -#define GPUImageWrappedLabel(x) x -#define GPUImageEscapedHashIdentifier(a) GPUImageWrappedLabel(GPUImageHashIdentifier)a - -extern NSString *const kGPUImageVertexShaderString; -extern NSString *const kGPUImagePassthroughFragmentShaderString; - -struct GPUVector4 { - GLfloat one; - GLfloat two; - GLfloat three; - GLfloat four; -}; -typedef struct GPUVector4 GPUVector4; - -struct GPUVector3 { - GLfloat one; - GLfloat two; - GLfloat three; -}; -typedef struct GPUVector3 GPUVector3; - -struct GPUMatrix4x4 { - GPUVector4 one; - GPUVector4 two; - GPUVector4 three; - GPUVector4 four; -}; -typedef struct GPUMatrix4x4 GPUMatrix4x4; - -struct GPUMatrix3x3 { - GPUVector3 one; - GPUVector3 two; - GPUVector3 three; -}; -typedef struct GPUMatrix3x3 GPUMatrix3x3; - -/** GPUImage's base filter class - - Filters and other subsequent elements in the chain conform to the GPUImageInput protocol, which lets them take in the supplied or processed texture from the previous link in the chain and do something with it. Objects one step further down the chain are considered targets, and processing can be branched by adding multiple targets to a single output or filter. - */ -@interface GPUImageFilter : GPUImageOutput -{ - GPUImageFramebuffer *firstInputFramebuffer; - - GLProgram *filterProgram; - GLint filterPositionAttribute, filterTextureCoordinateAttribute; - GLint filterInputTextureUniform; - GLfloat backgroundColorRed, backgroundColorGreen, backgroundColorBlue, backgroundColorAlpha; - - BOOL isEndProcessing; - - CGSize currentFilterSize; - GPUImageRotationMode inputRotation; - - BOOL currentlyReceivingMonochromeInput; - - NSMutableDictionary *uniformStateRestorationBlocks; - dispatch_semaphore_t imageCaptureSemaphore; -} - -@property(readonly) CVPixelBufferRef renderTarget; -@property(readwrite, nonatomic) BOOL preventRendering; -@property(readwrite, nonatomic) BOOL currentlyReceivingMonochromeInput; - -/// @name Initialization and teardown - -/** - Initialize with vertex and fragment shaders - - You make take advantage of the SHADER_STRING macro to write your shaders in-line. - @param vertexShaderString Source code of the vertex shader to use - @param fragmentShaderString Source code of the fragment shader to use - */ -- (id)initWithVertexShaderFromString:(NSString *)vertexShaderString fragmentShaderFromString:(NSString *)fragmentShaderString; - -/** - Initialize with a fragment shader - - You may take advantage of the SHADER_STRING macro to write your shader in-line. - @param fragmentShaderString Source code of fragment shader to use - */ -- (id)initWithFragmentShaderFromString:(NSString *)fragmentShaderString; -/** - Initialize with a fragment shader - @param fragmentShaderFilename Filename of fragment shader to load - */ -- (id)initWithFragmentShaderFromFile:(NSString *)fragmentShaderFilename; -- (void)initializeAttributes; -- (void)setupFilterForSize:(CGSize)filterFrameSize; -- (CGSize)rotatedSize:(CGSize)sizeToRotate forIndex:(NSInteger)textureIndex; -- (CGPoint)rotatedPoint:(CGPoint)pointToRotate forRotation:(GPUImageRotationMode)rotation; - -/// @name Managing the display FBOs -/** Size of the frame buffer object - */ -- (CGSize)sizeOfFBO; - -/// @name Rendering -+ (const GLfloat *)textureCoordinatesForRotation:(GPUImageRotationMode)rotationMode; -- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates; -- (void)informTargetsAboutNewFrameAtTime:(CMTime)frameTime; -- (CGSize)outputFrameSize; - -/// @name Input parameters -- (void)setBackgroundColorRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent alpha:(GLfloat)alphaComponent; -- (void)setInteger:(GLint)newInteger forUniformName:(NSString *)uniformName; -- (void)setFloat:(GLfloat)newFloat forUniformName:(NSString *)uniformName; -- (void)setSize:(CGSize)newSize forUniformName:(NSString *)uniformName; -- (void)setPoint:(CGPoint)newPoint forUniformName:(NSString *)uniformName; -- (void)setFloatVec3:(GPUVector3)newVec3 forUniformName:(NSString *)uniformName; -- (void)setFloatVec4:(GPUVector4)newVec4 forUniform:(NSString *)uniformName; -- (void)setFloatArray:(GLfloat *)array length:(GLsizei)count forUniform:(NSString*)uniformName; - -- (void)setMatrix3f:(GPUMatrix3x3)matrix forUniform:(GLint)uniform program:(GLProgram *)shaderProgram; -- (void)setMatrix4f:(GPUMatrix4x4)matrix forUniform:(GLint)uniform program:(GLProgram *)shaderProgram; -- (void)setFloat:(GLfloat)floatValue forUniform:(GLint)uniform program:(GLProgram *)shaderProgram; -- (void)setPoint:(CGPoint)pointValue forUniform:(GLint)uniform program:(GLProgram *)shaderProgram; -- (void)setSize:(CGSize)sizeValue forUniform:(GLint)uniform program:(GLProgram *)shaderProgram; -- (void)setVec3:(GPUVector3)vectorValue forUniform:(GLint)uniform program:(GLProgram *)shaderProgram; -- (void)setVec4:(GPUVector4)vectorValue forUniform:(GLint)uniform program:(GLProgram *)shaderProgram; -- (void)setFloatArray:(GLfloat *)arrayValue length:(GLsizei)arrayLength forUniform:(GLint)uniform program:(GLProgram *)shaderProgram; -- (void)setInteger:(GLint)intValue forUniform:(GLint)uniform program:(GLProgram *)shaderProgram; - -- (void)setAndExecuteUniformStateCallbackAtIndex:(GLint)uniform forProgram:(GLProgram *)shaderProgram toBlock:(dispatch_block_t)uniformStateBlock; -- (void)setUniformsForProgramAtIndex:(NSUInteger)programIndex; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilter.m deleted file mode 100755 index 406d707a..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilter.m +++ /dev/null @@ -1,753 +0,0 @@ -#import "GPUImageFilter.h" -#import "GPUImagePicture.h" -#import - -// Hardcode the vertex shader for standard filters, but this can be overridden -NSString *const kGPUImageVertexShaderString = SHADER_STRING -( - attribute vec4 position; - attribute vec4 inputTextureCoordinate; - - varying vec2 textureCoordinate; - - void main() - { - gl_Position = position; - textureCoordinate = inputTextureCoordinate.xy; - } - ); - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - -NSString *const kGPUImagePassthroughFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - gl_FragColor = texture2D(inputImageTexture, textureCoordinate); - } -); - -#else - -NSString *const kGPUImagePassthroughFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - gl_FragColor = texture2D(inputImageTexture, textureCoordinate); - } -); -#endif - - -@implementation GPUImageFilter - -@synthesize preventRendering = _preventRendering; -@synthesize currentlyReceivingMonochromeInput; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithVertexShaderFromString:(NSString *)vertexShaderString fragmentShaderFromString:(NSString *)fragmentShaderString; -{ - if (!(self = [super init])) - { - return nil; - } - - uniformStateRestorationBlocks = [NSMutableDictionary dictionaryWithCapacity:10]; - _preventRendering = NO; - currentlyReceivingMonochromeInput = NO; - inputRotation = kGPUImageNoRotation; - backgroundColorRed = 0.0; - backgroundColorGreen = 0.0; - backgroundColorBlue = 0.0; - backgroundColorAlpha = 0.0; - imageCaptureSemaphore = dispatch_semaphore_create(0); - dispatch_semaphore_signal(imageCaptureSemaphore); - - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext useImageProcessingContext]; - - filterProgram = [[GPUImageContext sharedImageProcessingContext] programForVertexShaderString:vertexShaderString fragmentShaderString:fragmentShaderString]; - - if (!filterProgram.initialized) - { - [self initializeAttributes]; - - if (![filterProgram link]) - { - NSString *progLog = [filterProgram programLog]; - NSLog(@"Program link log: %@", progLog); - NSString *fragLog = [filterProgram fragmentShaderLog]; - NSLog(@"Fragment shader compile log: %@", fragLog); - NSString *vertLog = [filterProgram vertexShaderLog]; - NSLog(@"Vertex shader compile log: %@", vertLog); - filterProgram = nil; - NSAssert(NO, @"Filter shader link failed"); - } - } - - filterPositionAttribute = [filterProgram attributeIndex:@"position"]; - filterTextureCoordinateAttribute = [filterProgram attributeIndex:@"inputTextureCoordinate"]; - filterInputTextureUniform = [filterProgram uniformIndex:@"inputImageTexture"]; // This does assume a name of "inputImageTexture" for the fragment shader - - [GPUImageContext setActiveShaderProgram:filterProgram]; - - glEnableVertexAttribArray(filterPositionAttribute); - glEnableVertexAttribArray(filterTextureCoordinateAttribute); - }); - - return self; -} - -- (id)initWithFragmentShaderFromString:(NSString *)fragmentShaderString; -{ - if (!(self = [self initWithVertexShaderFromString:kGPUImageVertexShaderString fragmentShaderFromString:fragmentShaderString])) - { - return nil; - } - - return self; -} - -- (id)initWithFragmentShaderFromFile:(NSString *)fragmentShaderFilename; -{ - NSString *fragmentShaderPathname = [[NSBundle mainBundle] pathForResource:fragmentShaderFilename ofType:@"fsh"]; - NSString *fragmentShaderString = [NSString stringWithContentsOfFile:fragmentShaderPathname encoding:NSUTF8StringEncoding error:nil]; - - if (!(self = [self initWithFragmentShaderFromString:fragmentShaderString])) - { - return nil; - } - - return self; -} - -- (id)init; -{ - if (!(self = [self initWithFragmentShaderFromString:kGPUImagePassthroughFragmentShaderString])) - { - return nil; - } - - return self; -} - -- (void)initializeAttributes; -{ - [filterProgram addAttribute:@"position"]; - [filterProgram addAttribute:@"inputTextureCoordinate"]; - - // Override this, calling back to this super method, in order to add new attributes to your vertex shader -} - -- (void)setupFilterForSize:(CGSize)filterFrameSize; -{ - // This is where you can override to provide some custom setup, if your filter has a size-dependent element -} - -- (void)dealloc -{ -#if !OS_OBJECT_USE_OBJC - if (imageCaptureSemaphore != NULL) - { - dispatch_release(imageCaptureSemaphore); - } -#endif - -} - -#pragma mark - -#pragma mark Still image processing - -- (void)useNextFrameForImageCapture; -{ - usingNextFrameForImageCapture = YES; - - // Set the semaphore high, if it isn't already - if (dispatch_semaphore_wait(imageCaptureSemaphore, DISPATCH_TIME_NOW) != 0) - { - return; - } -} - -- (CGImageRef)newCGImageFromCurrentlyProcessedOutput -{ - // Give it three seconds to process, then abort if they forgot to set up the image capture properly - double timeoutForImageCapture = 3.0; - dispatch_time_t convertedTimeout = dispatch_time(DISPATCH_TIME_NOW, timeoutForImageCapture * NSEC_PER_SEC); - - if (dispatch_semaphore_wait(imageCaptureSemaphore, convertedTimeout) != 0) - { - return NULL; - } - - GPUImageFramebuffer* framebuffer = [self framebufferForOutput]; - - usingNextFrameForImageCapture = NO; - dispatch_semaphore_signal(imageCaptureSemaphore); - - CGImageRef image = [framebuffer newCGImageFromFramebufferContents]; - return image; -} - -#pragma mark - -#pragma mark Managing the display FBOs - -- (CGSize)sizeOfFBO; -{ - CGSize outputSize = [self maximumOutputSize]; - if ( (CGSizeEqualToSize(outputSize, CGSizeZero)) || (inputTextureSize.width < outputSize.width) ) - { - return inputTextureSize; - } - else - { - return outputSize; - } -} - -#pragma mark - -#pragma mark Rendering - -+ (const GLfloat *)textureCoordinatesForRotation:(GPUImageRotationMode)rotationMode; -{ - static const GLfloat noRotationTextureCoordinates[] = { - 0.0f, 0.0f, - 1.0f, 0.0f, - 0.0f, 1.0f, - 1.0f, 1.0f, - }; - - static const GLfloat rotateLeftTextureCoordinates[] = { - 1.0f, 0.0f, - 1.0f, 1.0f, - 0.0f, 0.0f, - 0.0f, 1.0f, - }; - - static const GLfloat rotateRightTextureCoordinates[] = { - 0.0f, 1.0f, - 0.0f, 0.0f, - 1.0f, 1.0f, - 1.0f, 0.0f, - }; - - static const GLfloat verticalFlipTextureCoordinates[] = { - 0.0f, 1.0f, - 1.0f, 1.0f, - 0.0f, 0.0f, - 1.0f, 0.0f, - }; - - static const GLfloat horizontalFlipTextureCoordinates[] = { - 1.0f, 0.0f, - 0.0f, 0.0f, - 1.0f, 1.0f, - 0.0f, 1.0f, - }; - - static const GLfloat rotateRightVerticalFlipTextureCoordinates[] = { - 0.0f, 0.0f, - 0.0f, 1.0f, - 1.0f, 0.0f, - 1.0f, 1.0f, - }; - - static const GLfloat rotateRightHorizontalFlipTextureCoordinates[] = { - 1.0f, 1.0f, - 1.0f, 0.0f, - 0.0f, 1.0f, - 0.0f, 0.0f, - }; - - static const GLfloat rotate180TextureCoordinates[] = { - 1.0f, 1.0f, - 0.0f, 1.0f, - 1.0f, 0.0f, - 0.0f, 0.0f, - }; - - switch(rotationMode) - { - case kGPUImageNoRotation: return noRotationTextureCoordinates; - case kGPUImageRotateLeft: return rotateLeftTextureCoordinates; - case kGPUImageRotateRight: return rotateRightTextureCoordinates; - case kGPUImageFlipVertical: return verticalFlipTextureCoordinates; - case kGPUImageFlipHorizonal: return horizontalFlipTextureCoordinates; - case kGPUImageRotateRightFlipVertical: return rotateRightVerticalFlipTextureCoordinates; - case kGPUImageRotateRightFlipHorizontal: return rotateRightHorizontalFlipTextureCoordinates; - case kGPUImageRotate180: return rotate180TextureCoordinates; - } -} - -- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates; -{ - if (self.preventRendering) - { - [firstInputFramebuffer unlock]; - return; - } - - [GPUImageContext setActiveShaderProgram:filterProgram]; - - outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:[self sizeOfFBO] textureOptions:self.outputTextureOptions onlyTexture:NO]; - [outputFramebuffer activateFramebuffer]; - if (usingNextFrameForImageCapture) - { - [outputFramebuffer lock]; - } - - [self setUniformsForProgramAtIndex:0]; - - glClearColor(backgroundColorRed, backgroundColorGreen, backgroundColorBlue, backgroundColorAlpha); - glClear(GL_COLOR_BUFFER_BIT); - - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, [firstInputFramebuffer texture]); - - glUniform1i(filterInputTextureUniform, 2); - - glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, vertices); - glVertexAttribPointer(filterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - [firstInputFramebuffer unlock]; - - if (usingNextFrameForImageCapture) - { - dispatch_semaphore_signal(imageCaptureSemaphore); - } -} - -- (void)informTargetsAboutNewFrameAtTime:(CMTime)frameTime; -{ - if (self.frameProcessingCompletionBlock != NULL) - { - self.frameProcessingCompletionBlock(self, frameTime); - } - - // Get all targets the framebuffer so they can grab a lock on it - for (id currentTarget in targets) - { - if (currentTarget != self.targetToIgnoreForUpdates) - { - NSInteger indexOfObject = [targets indexOfObject:currentTarget]; - NSInteger textureIndex = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; - - [self setInputFramebufferForTarget:currentTarget atIndex:textureIndex]; - [currentTarget setInputSize:[self outputFrameSize] atIndex:textureIndex]; - } - } - - // Release our hold so it can return to the cache immediately upon processing - [[self framebufferForOutput] unlock]; - - if (usingNextFrameForImageCapture) - { -// usingNextFrameForImageCapture = NO; - } - else - { - [self removeOutputFramebuffer]; - } - - // Trigger processing last, so that our unlock comes first in serial execution, avoiding the need for a callback - for (id currentTarget in targets) - { - if (currentTarget != self.targetToIgnoreForUpdates) - { - NSInteger indexOfObject = [targets indexOfObject:currentTarget]; - NSInteger textureIndex = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; - [currentTarget newFrameReadyAtTime:frameTime atIndex:textureIndex]; - } - } -} - -- (CGSize)outputFrameSize; -{ - return inputTextureSize; -} - -#pragma mark - -#pragma mark Input parameters - -- (void)setBackgroundColorRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent alpha:(GLfloat)alphaComponent; -{ - backgroundColorRed = redComponent; - backgroundColorGreen = greenComponent; - backgroundColorBlue = blueComponent; - backgroundColorAlpha = alphaComponent; -} - -- (void)setInteger:(GLint)newInteger forUniformName:(NSString *)uniformName; -{ - GLint uniformIndex = [filterProgram uniformIndex:uniformName]; - [self setInteger:newInteger forUniform:uniformIndex program:filterProgram]; -} - -- (void)setFloat:(GLfloat)newFloat forUniformName:(NSString *)uniformName; -{ - GLint uniformIndex = [filterProgram uniformIndex:uniformName]; - [self setFloat:newFloat forUniform:uniformIndex program:filterProgram]; -} - -- (void)setSize:(CGSize)newSize forUniformName:(NSString *)uniformName; -{ - GLint uniformIndex = [filterProgram uniformIndex:uniformName]; - [self setSize:newSize forUniform:uniformIndex program:filterProgram]; -} - -- (void)setPoint:(CGPoint)newPoint forUniformName:(NSString *)uniformName; -{ - GLint uniformIndex = [filterProgram uniformIndex:uniformName]; - [self setPoint:newPoint forUniform:uniformIndex program:filterProgram]; -} - -- (void)setFloatVec3:(GPUVector3)newVec3 forUniformName:(NSString *)uniformName; -{ - GLint uniformIndex = [filterProgram uniformIndex:uniformName]; - [self setVec3:newVec3 forUniform:uniformIndex program:filterProgram]; -} - -- (void)setFloatVec4:(GPUVector4)newVec4 forUniform:(NSString *)uniformName; -{ - GLint uniformIndex = [filterProgram uniformIndex:uniformName]; - [self setVec4:newVec4 forUniform:uniformIndex program:filterProgram]; -} - -- (void)setFloatArray:(GLfloat *)array length:(GLsizei)count forUniform:(NSString*)uniformName -{ - GLint uniformIndex = [filterProgram uniformIndex:uniformName]; - - [self setFloatArray:array length:count forUniform:uniformIndex program:filterProgram]; -} - -- (void)setMatrix3f:(GPUMatrix3x3)matrix forUniform:(GLint)uniform program:(GLProgram *)shaderProgram; -{ - runAsynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext setActiveShaderProgram:shaderProgram]; - [self setAndExecuteUniformStateCallbackAtIndex:uniform forProgram:shaderProgram toBlock:^{ - glUniformMatrix3fv(uniform, 1, GL_FALSE, (GLfloat *)&matrix); - }]; - }); -} - -- (void)setMatrix4f:(GPUMatrix4x4)matrix forUniform:(GLint)uniform program:(GLProgram *)shaderProgram; -{ - runAsynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext setActiveShaderProgram:shaderProgram]; - [self setAndExecuteUniformStateCallbackAtIndex:uniform forProgram:shaderProgram toBlock:^{ - glUniformMatrix4fv(uniform, 1, GL_FALSE, (GLfloat *)&matrix); - }]; - }); -} - -- (void)setFloat:(GLfloat)floatValue forUniform:(GLint)uniform program:(GLProgram *)shaderProgram; -{ - runAsynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext setActiveShaderProgram:shaderProgram]; - [self setAndExecuteUniformStateCallbackAtIndex:uniform forProgram:shaderProgram toBlock:^{ - glUniform1f(uniform, floatValue); - }]; - }); -} - -- (void)setPoint:(CGPoint)pointValue forUniform:(GLint)uniform program:(GLProgram *)shaderProgram; -{ - runAsynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext setActiveShaderProgram:shaderProgram]; - [self setAndExecuteUniformStateCallbackAtIndex:uniform forProgram:shaderProgram toBlock:^{ - GLfloat positionArray[2]; - positionArray[0] = pointValue.x; - positionArray[1] = pointValue.y; - - glUniform2fv(uniform, 1, positionArray); - }]; - }); -} - -- (void)setSize:(CGSize)sizeValue forUniform:(GLint)uniform program:(GLProgram *)shaderProgram; -{ - runAsynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext setActiveShaderProgram:shaderProgram]; - - [self setAndExecuteUniformStateCallbackAtIndex:uniform forProgram:shaderProgram toBlock:^{ - GLfloat sizeArray[2]; - sizeArray[0] = sizeValue.width; - sizeArray[1] = sizeValue.height; - - glUniform2fv(uniform, 1, sizeArray); - }]; - }); -} - -- (void)setVec3:(GPUVector3)vectorValue forUniform:(GLint)uniform program:(GLProgram *)shaderProgram; -{ - runAsynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext setActiveShaderProgram:shaderProgram]; - - [self setAndExecuteUniformStateCallbackAtIndex:uniform forProgram:shaderProgram toBlock:^{ - glUniform3fv(uniform, 1, (GLfloat *)&vectorValue); - }]; - }); -} - -- (void)setVec4:(GPUVector4)vectorValue forUniform:(GLint)uniform program:(GLProgram *)shaderProgram; -{ - runAsynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext setActiveShaderProgram:shaderProgram]; - - [self setAndExecuteUniformStateCallbackAtIndex:uniform forProgram:shaderProgram toBlock:^{ - glUniform4fv(uniform, 1, (GLfloat *)&vectorValue); - }]; - }); -} - -- (void)setFloatArray:(GLfloat *)arrayValue length:(GLsizei)arrayLength forUniform:(GLint)uniform program:(GLProgram *)shaderProgram; -{ - // Make a copy of the data, so it doesn't get overwritten before async call executes - NSData* arrayData = [NSData dataWithBytes:arrayValue length:arrayLength * sizeof(arrayValue[0])]; - - runAsynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext setActiveShaderProgram:shaderProgram]; - - [self setAndExecuteUniformStateCallbackAtIndex:uniform forProgram:shaderProgram toBlock:^{ - glUniform1fv(uniform, arrayLength, [arrayData bytes]); - }]; - }); -} - -- (void)setInteger:(GLint)intValue forUniform:(GLint)uniform program:(GLProgram *)shaderProgram; -{ - runAsynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext setActiveShaderProgram:shaderProgram]; - - [self setAndExecuteUniformStateCallbackAtIndex:uniform forProgram:shaderProgram toBlock:^{ - glUniform1i(uniform, intValue); - }]; - }); -} - -- (void)setAndExecuteUniformStateCallbackAtIndex:(GLint)uniform forProgram:(GLProgram *)shaderProgram toBlock:(dispatch_block_t)uniformStateBlock; -{ - [uniformStateRestorationBlocks setObject:[uniformStateBlock copy] forKey:[NSNumber numberWithInt:uniform]]; - uniformStateBlock(); -} - -- (void)setUniformsForProgramAtIndex:(NSUInteger)programIndex; -{ - [uniformStateRestorationBlocks enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop){ - dispatch_block_t currentBlock = obj; - currentBlock(); - }]; -} - -#pragma mark - -#pragma mark GPUImageInput - -- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex; -{ - static const GLfloat imageVertices[] = { - -1.0f, -1.0f, - 1.0f, -1.0f, - -1.0f, 1.0f, - 1.0f, 1.0f, - }; - - [self renderToTextureWithVertices:imageVertices textureCoordinates:[[self class] textureCoordinatesForRotation:inputRotation]]; - - [self informTargetsAboutNewFrameAtTime:frameTime]; -} - -- (NSInteger)nextAvailableTextureIndex; -{ - return 0; -} - -- (void)setInputFramebuffer:(GPUImageFramebuffer *)newInputFramebuffer atIndex:(NSInteger)textureIndex; -{ - firstInputFramebuffer = newInputFramebuffer; - [firstInputFramebuffer lock]; -} - -- (CGSize)rotatedSize:(CGSize)sizeToRotate forIndex:(NSInteger)textureIndex; -{ - CGSize rotatedSize = sizeToRotate; - - if (GPUImageRotationSwapsWidthAndHeight(inputRotation)) - { - rotatedSize.width = sizeToRotate.height; - rotatedSize.height = sizeToRotate.width; - } - - return rotatedSize; -} - -- (CGPoint)rotatedPoint:(CGPoint)pointToRotate forRotation:(GPUImageRotationMode)rotation; -{ - CGPoint rotatedPoint; - switch(rotation) - { - case kGPUImageNoRotation: return pointToRotate; break; - case kGPUImageFlipHorizonal: - { - rotatedPoint.x = 1.0 - pointToRotate.x; - rotatedPoint.y = pointToRotate.y; - }; break; - case kGPUImageFlipVertical: - { - rotatedPoint.x = pointToRotate.x; - rotatedPoint.y = 1.0 - pointToRotate.y; - }; break; - case kGPUImageRotateLeft: - { - rotatedPoint.x = 1.0 - pointToRotate.y; - rotatedPoint.y = pointToRotate.x; - }; break; - case kGPUImageRotateRight: - { - rotatedPoint.x = pointToRotate.y; - rotatedPoint.y = 1.0 - pointToRotate.x; - }; break; - case kGPUImageRotateRightFlipVertical: - { - rotatedPoint.x = pointToRotate.y; - rotatedPoint.y = pointToRotate.x; - }; break; - case kGPUImageRotateRightFlipHorizontal: - { - rotatedPoint.x = 1.0 - pointToRotate.y; - rotatedPoint.y = 1.0 - pointToRotate.x; - }; break; - case kGPUImageRotate180: - { - rotatedPoint.x = 1.0 - pointToRotate.x; - rotatedPoint.y = 1.0 - pointToRotate.y; - }; break; - } - - return rotatedPoint; -} - -- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex; -{ - if (self.preventRendering) - { - return; - } - - if (overrideInputSize) - { - if (CGSizeEqualToSize(forcedMaximumSize, CGSizeZero)) - { - } - else - { - CGRect insetRect = AVMakeRectWithAspectRatioInsideRect(newSize, CGRectMake(0.0, 0.0, forcedMaximumSize.width, forcedMaximumSize.height)); - inputTextureSize = insetRect.size; - } - } - else - { - CGSize rotatedSize = [self rotatedSize:newSize forIndex:textureIndex]; - - if (CGSizeEqualToSize(rotatedSize, CGSizeZero)) - { - inputTextureSize = rotatedSize; - } - else if (!CGSizeEqualToSize(inputTextureSize, rotatedSize)) - { - inputTextureSize = rotatedSize; - } - } - - [self setupFilterForSize:[self sizeOfFBO]]; -} - -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -{ - inputRotation = newInputRotation; -} - -- (void)forceProcessingAtSize:(CGSize)frameSize; -{ - if (CGSizeEqualToSize(frameSize, CGSizeZero)) - { - overrideInputSize = NO; - } - else - { - overrideInputSize = YES; - inputTextureSize = frameSize; - forcedMaximumSize = CGSizeZero; - } -} - -- (void)forceProcessingAtSizeRespectingAspectRatio:(CGSize)frameSize; -{ - if (CGSizeEqualToSize(frameSize, CGSizeZero)) - { - overrideInputSize = NO; - inputTextureSize = CGSizeZero; - forcedMaximumSize = CGSizeZero; - } - else - { - overrideInputSize = YES; - forcedMaximumSize = frameSize; - } -} - -- (CGSize)maximumOutputSize; -{ - // I'm temporarily disabling adjustments for smaller output sizes until I figure out how to make this work better - return CGSizeZero; - - /* - if (CGSizeEqualToSize(cachedMaximumOutputSize, CGSizeZero)) - { - for (id currentTarget in targets) - { - if ([currentTarget maximumOutputSize].width > cachedMaximumOutputSize.width) - { - cachedMaximumOutputSize = [currentTarget maximumOutputSize]; - } - } - } - - return cachedMaximumOutputSize; - */ -} - -- (void)endProcessing -{ - if (!isEndProcessing) - { - isEndProcessing = YES; - - for (id currentTarget in targets) - { - [currentTarget endProcessing]; - } - } -} - -- (BOOL)wantsMonochromeInput; -{ - return NO; -} - -#pragma mark - -#pragma mark Accessors - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilterGroup.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilterGroup.h deleted file mode 100755 index 6817cdf0..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilterGroup.h +++ /dev/null @@ -1,19 +0,0 @@ -#import "GPUImageOutput.h" -#import "GPUImageFilter.h" - -@interface GPUImageFilterGroup : GPUImageOutput -{ - NSMutableArray *filters; - BOOL isEndProcessing; -} - -@property(readwrite, nonatomic, strong) GPUImageOutput *terminalFilter; -@property(readwrite, nonatomic, strong) NSArray *initialFilters; -@property(readwrite, nonatomic, strong) GPUImageOutput *inputFilterToIgnoreForUpdates; - -// Filter management -- (void)addFilter:(GPUImageOutput *)newFilter; -- (GPUImageOutput *)filterAtIndex:(NSUInteger)filterIndex; -- (NSUInteger)filterCount; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilterGroup.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilterGroup.m deleted file mode 100755 index 72cfe5e7..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilterGroup.m +++ /dev/null @@ -1,208 +0,0 @@ -#import "GPUImageFilterGroup.h" -#import "GPUImagePicture.h" - -@implementation GPUImageFilterGroup - -@synthesize terminalFilter = _terminalFilter; -@synthesize initialFilters = _initialFilters; -@synthesize inputFilterToIgnoreForUpdates = _inputFilterToIgnoreForUpdates; - -- (id)init; -{ - if (!(self = [super init])) - { - return nil; - } - - filters = [[NSMutableArray alloc] init]; - - return self; -} - -#pragma mark - -#pragma mark Filter management - -- (void)addFilter:(GPUImageOutput *)newFilter; -{ - [filters addObject:newFilter]; -} - -- (GPUImageOutput *)filterAtIndex:(NSUInteger)filterIndex; -{ - return [filters objectAtIndex:filterIndex]; -} - -- (NSUInteger)filterCount; -{ - return [filters count]; -} - -#pragma mark - -#pragma mark Still image processing - -- (void)useNextFrameForImageCapture; -{ - [self.terminalFilter useNextFrameForImageCapture]; -} - -- (CGImageRef)newCGImageFromCurrentlyProcessedOutput; -{ - return [self.terminalFilter newCGImageFromCurrentlyProcessedOutput]; -} - -#pragma mark - -#pragma mark GPUImageOutput overrides - -- (void)setTargetToIgnoreForUpdates:(id)targetToIgnoreForUpdates; -{ - [_terminalFilter setTargetToIgnoreForUpdates:targetToIgnoreForUpdates]; -} - -- (void)addTarget:(id)newTarget atTextureLocation:(NSInteger)textureLocation; -{ - [_terminalFilter addTarget:newTarget atTextureLocation:textureLocation]; -} - -- (void)removeTarget:(id)targetToRemove; -{ - [_terminalFilter removeTarget:targetToRemove]; -} - -- (void)removeAllTargets; -{ - [_terminalFilter removeAllTargets]; -} - -- (NSArray *)targets; -{ - return [_terminalFilter targets]; -} - -- (void)setFrameProcessingCompletionBlock:(void (^)(GPUImageOutput *, CMTime))frameProcessingCompletionBlock; -{ - [_terminalFilter setFrameProcessingCompletionBlock:frameProcessingCompletionBlock]; -} - -- (void (^)(GPUImageOutput *, CMTime))frameProcessingCompletionBlock; -{ - return [_terminalFilter frameProcessingCompletionBlock]; -} - -#pragma mark - -#pragma mark GPUImageInput protocol - -- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex; -{ - for (GPUImageOutput *currentFilter in _initialFilters) - { - if (currentFilter != self.inputFilterToIgnoreForUpdates) - { - [currentFilter newFrameReadyAtTime:frameTime atIndex:textureIndex]; - } - } -} - -- (void)setInputFramebuffer:(GPUImageFramebuffer *)newInputFramebuffer atIndex:(NSInteger)textureIndex; -{ - for (GPUImageOutput *currentFilter in _initialFilters) - { - [currentFilter setInputFramebuffer:newInputFramebuffer atIndex:textureIndex]; - } -} - -- (NSInteger)nextAvailableTextureIndex; -{ -// if ([_initialFilters count] > 0) -// { -// return [[_initialFilters objectAtIndex:0] nextAvailableTextureIndex]; -// } - - return 0; -} - -- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex; -{ - for (GPUImageOutput *currentFilter in _initialFilters) - { - [currentFilter setInputSize:newSize atIndex:textureIndex]; - } -} - -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -{ - for (GPUImageOutput *currentFilter in _initialFilters) - { - [currentFilter setInputRotation:newInputRotation atIndex:(NSInteger)textureIndex]; - } -} - -- (void)forceProcessingAtSize:(CGSize)frameSize; -{ - for (GPUImageOutput *currentFilter in filters) - { - [currentFilter forceProcessingAtSize:frameSize]; - } -} - -- (void)forceProcessingAtSizeRespectingAspectRatio:(CGSize)frameSize; -{ - for (GPUImageOutput *currentFilter in filters) - { - [currentFilter forceProcessingAtSizeRespectingAspectRatio:frameSize]; - } -} - -- (CGSize)maximumOutputSize; -{ - // I'm temporarily disabling adjustments for smaller output sizes until I figure out how to make this work better - return CGSizeZero; - - /* - if (CGSizeEqualToSize(cachedMaximumOutputSize, CGSizeZero)) - { - for (id currentTarget in _initialFilters) - { - if ([currentTarget maximumOutputSize].width > cachedMaximumOutputSize.width) - { - cachedMaximumOutputSize = [currentTarget maximumOutputSize]; - } - } - } - - return cachedMaximumOutputSize; - */ -} - -- (void)endProcessing; -{ - if (!isEndProcessing) - { - isEndProcessing = YES; - - for (id currentTarget in _initialFilters) - { - [currentTarget endProcessing]; - } - } -} - -- (BOOL)wantsMonochromeInput; -{ - BOOL allInputsWantMonochromeInput = YES; - for (GPUImageOutput *currentFilter in _initialFilters) - { - allInputsWantMonochromeInput = allInputsWantMonochromeInput && [currentFilter wantsMonochromeInput]; - } - - return allInputsWantMonochromeInput; -} - -- (void)setCurrentlyReceivingMonochromeInput:(BOOL)newValue; -{ - for (GPUImageOutput *currentFilter in _initialFilters) - { - [currentFilter setCurrentlyReceivingMonochromeInput:newValue]; - } -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilterPipeline.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilterPipeline.h deleted file mode 100755 index dc2baeac..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilterPipeline.h +++ /dev/null @@ -1,30 +0,0 @@ -#import -#import "GPUImageOutput.h" - -@interface GPUImageFilterPipeline : NSObject -{ - NSString *stringValue; -} - -@property (strong) NSMutableArray *filters; - -@property (strong) GPUImageOutput *input; -@property (strong) id output; - -- (id) initWithOrderedFilters:(NSArray*) filters input:(GPUImageOutput*)input output:(id )output; -- (id) initWithConfiguration:(NSDictionary*) configuration input:(GPUImageOutput*)input output:(id )output; -- (id) initWithConfigurationFile:(NSURL*) configuration input:(GPUImageOutput*)input output:(id )output; - -- (void) addFilter:(GPUImageOutput *)filter; -- (void) addFilter:(GPUImageOutput *)filter atIndex:(NSUInteger)insertIndex; -- (void) replaceFilterAtIndex:(NSUInteger)index withFilter:(GPUImageOutput *)filter; -- (void) replaceAllFilters:(NSArray *) newFilters; -- (void) removeFilter:(GPUImageOutput *)filter; -- (void) removeFilterAtIndex:(NSUInteger)index; -- (void) removeAllFilters; - -- (UIImage *) currentFilteredFrame; -- (UIImage *) currentFilteredFrameWithOrientation:(UIImageOrientation)imageOrientation; -- (CGImageRef) newCGImageFromCurrentFilteredFrame; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilterPipeline.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilterPipeline.m deleted file mode 100755 index 4fbe5ebb..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFilterPipeline.m +++ /dev/null @@ -1,218 +0,0 @@ -#import "GPUImageFilterPipeline.h" - -@interface GPUImageFilterPipeline () - -- (BOOL)_parseConfiguration:(NSDictionary *)configuration; - -- (void)_refreshFilters; - -@end - -@implementation GPUImageFilterPipeline - -@synthesize filters = _filters, input = _input, output = _output; - -#pragma mark Config file init - -- (id)initWithConfiguration:(NSDictionary *)configuration input:(GPUImageOutput *)input output:(id )output { - self = [super init]; - if (self) { - self.input = input; - self.output = output; - if (![self _parseConfiguration:configuration]) { - NSLog(@"Sorry, a parsing error occurred."); - abort(); - } - [self _refreshFilters]; - } - return self; -} - -- (id)initWithConfigurationFile:(NSURL *)configuration input:(GPUImageOutput *)input output:(id )output { - return [self initWithConfiguration:[NSDictionary dictionaryWithContentsOfURL:configuration] input:input output:output]; -} - -- (BOOL)_parseConfiguration:(NSDictionary *)configuration { - NSArray *filters = [configuration objectForKey:@"Filters"]; - if (!filters) { - return NO; - } - - NSError *regexError = nil; - NSRegularExpression *parsingRegex = [NSRegularExpression regularExpressionWithPattern:@"(float|CGPoint|NSString)\\((.*?)(?:,\\s*(.*?))*\\)" - options:0 - error:®exError]; - - // It's faster to put them into an array and then pass it to the filters property than it is to call [self addFilter:] every time - NSMutableArray *orderedFilters = [NSMutableArray arrayWithCapacity:[filters count]]; - for (NSDictionary *filter in filters) { - NSString *filterName = [filter objectForKey:@"FilterName"]; - Class theClass = NSClassFromString(filterName); - GPUImageOutput *genericFilter = [[theClass alloc] init]; - // Set up the properties - NSDictionary *filterAttributes; - if ((filterAttributes = [filter objectForKey:@"Attributes"])) { - for (NSString *propertyKey in filterAttributes) { - // Set up the selector - SEL theSelector = NSSelectorFromString(propertyKey); - NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[theClass instanceMethodSignatureForSelector:theSelector]]; - [inv setSelector:theSelector]; - [inv setTarget:genericFilter]; - - // check selector given with parameter - if ([propertyKey hasSuffix:@":"]) { - - stringValue = nil; - - // Then parse the arguments - NSMutableArray *parsedArray; - if ([[filterAttributes objectForKey:propertyKey] isKindOfClass:[NSArray class]]) { - NSArray *array = [filterAttributes objectForKey:propertyKey]; - parsedArray = [NSMutableArray arrayWithCapacity:[array count]]; - for (NSString *string in array) { - NSTextCheckingResult *parse = [parsingRegex firstMatchInString:string - options:0 - range:NSMakeRange(0, [string length])]; - - NSString *modifier = [string substringWithRange:[parse rangeAtIndex:1]]; - if ([modifier isEqualToString:@"float"]) { - // Float modifier, one argument - CGFloat value = [[string substringWithRange:[parse rangeAtIndex:2]] floatValue]; - [parsedArray addObject:[NSNumber numberWithFloat:value]]; - [inv setArgument:&value atIndex:2]; - } else if ([modifier isEqualToString:@"CGPoint"]) { - // CGPoint modifier, two float arguments - CGFloat x = [[string substringWithRange:[parse rangeAtIndex:2]] floatValue]; - CGFloat y = [[string substringWithRange:[parse rangeAtIndex:3]] floatValue]; - CGPoint value = CGPointMake(x, y); - [parsedArray addObject:[NSValue valueWithCGPoint:value]]; - } else if ([modifier isEqualToString:@"NSString"]) { - // NSString modifier, one string argument - stringValue = [[string substringWithRange:[parse rangeAtIndex:2]] copy]; - [inv setArgument:&stringValue atIndex:2]; - - } else { - return NO; - } - } - [inv setArgument:&parsedArray atIndex:2]; - } else { - NSString *string = [filterAttributes objectForKey:propertyKey]; - NSTextCheckingResult *parse = [parsingRegex firstMatchInString:string - options:0 - range:NSMakeRange(0, [string length])]; - - NSString *modifier = [string substringWithRange:[parse rangeAtIndex:1]]; - if ([modifier isEqualToString:@"float"]) { - // Float modifier, one argument - CGFloat value = [[string substringWithRange:[parse rangeAtIndex:2]] floatValue]; - [inv setArgument:&value atIndex:2]; - } else if ([modifier isEqualToString:@"CGPoint"]) { - // CGPoint modifier, two float arguments - CGFloat x = [[string substringWithRange:[parse rangeAtIndex:2]] floatValue]; - CGFloat y = [[string substringWithRange:[parse rangeAtIndex:3]] floatValue]; - CGPoint value = CGPointMake(x, y); - [inv setArgument:&value atIndex:2]; - } else if ([modifier isEqualToString:@"NSString"]) { - // NSString modifier, one string argument - stringValue = [[string substringWithRange:[parse rangeAtIndex:2]] copy]; - [inv setArgument:&stringValue atIndex:2]; - - } else { - return NO; - } - } - } - - - [inv invoke]; - } - } - [orderedFilters addObject:genericFilter]; - } - self.filters = orderedFilters; - - return YES; -} - -#pragma mark Regular init - -- (id)initWithOrderedFilters:(NSArray *)filters input:(GPUImageOutput *)input output:(id )output { - self = [super init]; - if (self) { - self.input = input; - self.output = output; - self.filters = [NSMutableArray arrayWithArray:filters]; - [self _refreshFilters]; - } - return self; -} - -- (void)addFilter:(GPUImageOutput *)filter atIndex:(NSUInteger)insertIndex { - [self.filters insertObject:filter atIndex:insertIndex]; - [self _refreshFilters]; -} - -- (void)addFilter:(GPUImageOutput *)filter { - [self.filters addObject:filter]; - [self _refreshFilters]; -} - -- (void)replaceFilterAtIndex:(NSUInteger)index withFilter:(GPUImageOutput *)filter { - [self.filters replaceObjectAtIndex:index withObject:filter]; - [self _refreshFilters]; -} - -- (void) removeFilter:(GPUImageOutput *)filter; -{ - [self.filters removeObject:filter]; - [self _refreshFilters]; -} - -- (void)removeFilterAtIndex:(NSUInteger)index { - [self.filters removeObjectAtIndex:index]; - [self _refreshFilters]; -} - -- (void)removeAllFilters { - [self.filters removeAllObjects]; - [self _refreshFilters]; -} - -- (void)replaceAllFilters:(NSArray *)newFilters { - self.filters = [NSMutableArray arrayWithArray:newFilters]; - [self _refreshFilters]; -} - -- (void)_refreshFilters { - - id prevFilter = self.input; - GPUImageOutput *theFilter = nil; - - for (int i = 0; i < [self.filters count]; i++) { - theFilter = [self.filters objectAtIndex:i]; - [prevFilter removeAllTargets]; - [prevFilter addTarget:theFilter]; - prevFilter = theFilter; - } - - [prevFilter removeAllTargets]; - - if (self.output != nil) { - [prevFilter addTarget:self.output]; - } -} - -- (UIImage *)currentFilteredFrame { - return [(GPUImageOutput *)[_filters lastObject] imageFromCurrentFramebuffer]; -} - -- (UIImage *)currentFilteredFrameWithOrientation:(UIImageOrientation)imageOrientation { - return [(GPUImageOutput *)[_filters lastObject] imageFromCurrentFramebufferWithOrientation:imageOrientation]; -} - -- (CGImageRef)newCGImageFromCurrentFilteredFrame { - return [(GPUImageOutput *)[_filters lastObject] newCGImageFromCurrentlyProcessedOutput]; -} - -@end \ No newline at end of file diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFramebuffer.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFramebuffer.h deleted file mode 100644 index 5cf20dd3..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFramebuffer.h +++ /dev/null @@ -1,58 +0,0 @@ -#import - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -#import -#import -#import -#else -#import -#import -#endif - -#import -#import - - -typedef struct GPUTextureOptions { - GLenum minFilter; - GLenum magFilter; - GLenum wrapS; - GLenum wrapT; - GLenum internalFormat; - GLenum format; - GLenum type; -} GPUTextureOptions; - -@interface GPUImageFramebuffer : NSObject - -@property(readonly) CGSize size; -@property(readonly) GPUTextureOptions textureOptions; -@property(readonly) GLuint texture; -@property(readonly) BOOL missingFramebuffer; - -// Initialization and teardown -- (id)initWithSize:(CGSize)framebufferSize; -- (id)initWithSize:(CGSize)framebufferSize textureOptions:(GPUTextureOptions)fboTextureOptions onlyTexture:(BOOL)onlyGenerateTexture; -- (id)initWithSize:(CGSize)framebufferSize overriddenTexture:(GLuint)inputTexture; - -// Usage -- (void)activateFramebuffer; - -// Reference counting -- (void)lock; -- (void)unlock; -- (void)clearAllLocks; -- (void)disableReferenceCounting; -- (void)enableReferenceCounting; - -// Image capture -- (CGImageRef)newCGImageFromFramebufferContents; -- (void)restoreRenderTarget; - -// Raw data bytes -- (void)lockForReading; -- (void)unlockAfterReading; -- (NSUInteger)bytesPerRow; -- (GLubyte *)byteBuffer; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFramebuffer.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFramebuffer.m deleted file mode 100644 index 1d3d48fc..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFramebuffer.m +++ /dev/null @@ -1,448 +0,0 @@ -#import "GPUImageFramebuffer.h" -#import "GPUImageOutput.h" - -@interface GPUImageFramebuffer() -{ - GLuint framebuffer; -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - CVPixelBufferRef renderTarget; - CVOpenGLESTextureRef renderTexture; - NSUInteger readLockCount; -#else -#endif - NSUInteger framebufferReferenceCount; - BOOL referenceCountingDisabled; -} - -- (void)generateFramebuffer; -- (void)generateTexture; -- (void)destroyFramebuffer; - -@end - -void dataProviderReleaseCallback (void *info, const void *data, size_t size); -void dataProviderUnlockCallback (void *info, const void *data, size_t size); - -@implementation GPUImageFramebuffer - -@synthesize size = _size; -@synthesize textureOptions = _textureOptions; -@synthesize texture = _texture; -@synthesize missingFramebuffer = _missingFramebuffer; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithSize:(CGSize)framebufferSize textureOptions:(GPUTextureOptions)fboTextureOptions onlyTexture:(BOOL)onlyGenerateTexture; -{ - if (!(self = [super init])) - { - return nil; - } - - _textureOptions = fboTextureOptions; - _size = framebufferSize; - framebufferReferenceCount = 0; - referenceCountingDisabled = NO; - _missingFramebuffer = onlyGenerateTexture; - - if (_missingFramebuffer) - { - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext useImageProcessingContext]; - [self generateTexture]; - framebuffer = 0; - }); - } - else - { - [self generateFramebuffer]; - } - return self; -} - -- (id)initWithSize:(CGSize)framebufferSize overriddenTexture:(GLuint)inputTexture; -{ - if (!(self = [super init])) - { - return nil; - } - - GPUTextureOptions defaultTextureOptions; - defaultTextureOptions.minFilter = GL_LINEAR; - defaultTextureOptions.magFilter = GL_LINEAR; - defaultTextureOptions.wrapS = GL_CLAMP_TO_EDGE; - defaultTextureOptions.wrapT = GL_CLAMP_TO_EDGE; - defaultTextureOptions.internalFormat = GL_RGBA; - defaultTextureOptions.format = GL_BGRA; - defaultTextureOptions.type = GL_UNSIGNED_BYTE; - - _textureOptions = defaultTextureOptions; - _size = framebufferSize; - framebufferReferenceCount = 0; - referenceCountingDisabled = YES; - - _texture = inputTexture; - - return self; -} - -- (id)initWithSize:(CGSize)framebufferSize; -{ - GPUTextureOptions defaultTextureOptions; - defaultTextureOptions.minFilter = GL_LINEAR; - defaultTextureOptions.magFilter = GL_LINEAR; - defaultTextureOptions.wrapS = GL_CLAMP_TO_EDGE; - defaultTextureOptions.wrapT = GL_CLAMP_TO_EDGE; - defaultTextureOptions.internalFormat = GL_RGBA; - defaultTextureOptions.format = GL_BGRA; - defaultTextureOptions.type = GL_UNSIGNED_BYTE; - - if (!(self = [self initWithSize:framebufferSize textureOptions:defaultTextureOptions onlyTexture:NO])) - { - return nil; - } - - return self; -} - -- (void)dealloc -{ - [self destroyFramebuffer]; -} - -#pragma mark - -#pragma mark Internal - -- (void)generateTexture; -{ - glActiveTexture(GL_TEXTURE1); - glGenTextures(1, &_texture); - glBindTexture(GL_TEXTURE_2D, _texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _textureOptions.minFilter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _textureOptions.magFilter); - // This is necessary for non-power-of-two textures - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _textureOptions.wrapS); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _textureOptions.wrapT); - - // TODO: Handle mipmaps -} - -- (void)generateFramebuffer; -{ - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext useImageProcessingContext]; - - glGenFramebuffers(1, &framebuffer); - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - - // By default, all framebuffers on iOS 5.0+ devices are backed by texture caches, using one shared cache - if ([GPUImageContext supportsFastTextureUpload]) - { -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - CVOpenGLESTextureCacheRef coreVideoTextureCache = [[GPUImageContext sharedImageProcessingContext] coreVideoTextureCache]; - // Code originally sourced from http://allmybrain.com/2011/12/08/rendering-to-a-texture-with-ios-5-texture-cache-api/ - - CFDictionaryRef empty; // empty value for attr value. - CFMutableDictionaryRef attrs; - empty = CFDictionaryCreate(kCFAllocatorDefault, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); // our empty IOSurface properties dictionary - attrs = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFDictionarySetValue(attrs, kCVPixelBufferIOSurfacePropertiesKey, empty); - - CVReturn err = CVPixelBufferCreate(kCFAllocatorDefault, (int)_size.width, (int)_size.height, kCVPixelFormatType_32BGRA, attrs, &renderTarget); - if (err) - { - NSLog(@"FBO size: %f, %f", _size.width, _size.height); - NSAssert(NO, @"Error at CVPixelBufferCreate %d", err); - } - - err = CVOpenGLESTextureCacheCreateTextureFromImage (kCFAllocatorDefault, coreVideoTextureCache, renderTarget, - NULL, // texture attributes - GL_TEXTURE_2D, - _textureOptions.internalFormat, // opengl format - (int)_size.width, - (int)_size.height, - _textureOptions.format, // native iOS format - _textureOptions.type, - 0, - &renderTexture); - if (err) - { - NSAssert(NO, @"Error at CVOpenGLESTextureCacheCreateTextureFromImage %d", err); - } - - CFRelease(attrs); - CFRelease(empty); - - glBindTexture(CVOpenGLESTextureGetTarget(renderTexture), CVOpenGLESTextureGetName(renderTexture)); - _texture = CVOpenGLESTextureGetName(renderTexture); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _textureOptions.wrapS); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _textureOptions.wrapT); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, CVOpenGLESTextureGetName(renderTexture), 0); -#endif - } - else - { - [self generateTexture]; - - glBindTexture(GL_TEXTURE_2D, _texture); - - glTexImage2D(GL_TEXTURE_2D, 0, _textureOptions.internalFormat, (int)_size.width, (int)_size.height, 0, _textureOptions.format, _textureOptions.type, 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture, 0); - } - - #ifndef NS_BLOCK_ASSERTIONS - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - NSAssert(status == GL_FRAMEBUFFER_COMPLETE, @"Incomplete filter FBO: %d", status); - #endif - - glBindTexture(GL_TEXTURE_2D, 0); - }); -} - -- (void)destroyFramebuffer; -{ - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext useImageProcessingContext]; - - if (framebuffer) - { - glDeleteFramebuffers(1, &framebuffer); - framebuffer = 0; - } - - - if ([GPUImageContext supportsFastTextureUpload] && (!_missingFramebuffer)) - { -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - if (renderTarget) - { - CFRelease(renderTarget); - renderTarget = NULL; - } - - if (renderTexture) - { - CFRelease(renderTexture); - renderTexture = NULL; - } -#endif - } - else - { - glDeleteTextures(1, &_texture); - } - - }); -} - -#pragma mark - -#pragma mark Usage - -- (void)activateFramebuffer; -{ - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - glViewport(0, 0, (int)_size.width, (int)_size.height); -} - -#pragma mark - -#pragma mark Reference counting - -- (void)lock; -{ - if (referenceCountingDisabled) - { - return; - } - - framebufferReferenceCount++; -} - -- (void)unlock; -{ - if (referenceCountingDisabled) - { - return; - } - - NSAssert(framebufferReferenceCount > 0, @"Tried to overrelease a framebuffer, did you forget to call -useNextFrameForImageCapture before using -imageFromCurrentFramebuffer?"); - framebufferReferenceCount--; - if (framebufferReferenceCount < 1) - { - [[GPUImageContext sharedFramebufferCache] returnFramebufferToCache:self]; - } -} - -- (void)clearAllLocks; -{ - framebufferReferenceCount = 0; -} - -- (void)disableReferenceCounting; -{ - referenceCountingDisabled = YES; -} - -- (void)enableReferenceCounting; -{ - referenceCountingDisabled = NO; -} - -#pragma mark - -#pragma mark Image capture - -void dataProviderReleaseCallback (void *info, const void *data, size_t size) -{ - free((void *)data); -} - -void dataProviderUnlockCallback (void *info, const void *data, size_t size) -{ - GPUImageFramebuffer *framebuffer = (__bridge_transfer GPUImageFramebuffer*)info; - - [framebuffer restoreRenderTarget]; - [framebuffer unlock]; - [[GPUImageContext sharedFramebufferCache] removeFramebufferFromActiveImageCaptureList:framebuffer]; -} - -- (CGImageRef)newCGImageFromFramebufferContents; -{ - // a CGImage can only be created from a 'normal' color texture - NSAssert(self.textureOptions.internalFormat == GL_RGBA, @"For conversion to a CGImage the output texture format for this filter must be GL_RGBA."); - NSAssert(self.textureOptions.type == GL_UNSIGNED_BYTE, @"For conversion to a CGImage the type of the output texture of this filter must be GL_UNSIGNED_BYTE."); - - __block CGImageRef cgImageFromBytes; - - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext useImageProcessingContext]; - - NSUInteger totalBytesForImage = (int)_size.width * (int)_size.height * 4; - // It appears that the width of a texture must be padded out to be a multiple of 8 (32 bytes) if reading from it using a texture cache - - GLubyte *rawImagePixels; - - CGDataProviderRef dataProvider = NULL; - if ([GPUImageContext supportsFastTextureUpload]) - { -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - NSUInteger paddedWidthOfImage = CVPixelBufferGetBytesPerRow(renderTarget) / 4.0; - NSUInteger paddedBytesForImage = paddedWidthOfImage * (int)_size.height * 4; - - glFinish(); - CFRetain(renderTarget); // I need to retain the pixel buffer here and release in the data source callback to prevent its bytes from being prematurely deallocated during a photo write operation - [self lockForReading]; - rawImagePixels = (GLubyte *)CVPixelBufferGetBaseAddress(renderTarget); - dataProvider = CGDataProviderCreateWithData((__bridge_retained void*)self, rawImagePixels, paddedBytesForImage, dataProviderUnlockCallback); - [[GPUImageContext sharedFramebufferCache] addFramebufferToActiveImageCaptureList:self]; // In case the framebuffer is swapped out on the filter, need to have a strong reference to it somewhere for it to hang on while the image is in existence -#else -#endif - } - else - { - [self activateFramebuffer]; - rawImagePixels = (GLubyte *)malloc(totalBytesForImage); - glReadPixels(0, 0, (int)_size.width, (int)_size.height, GL_RGBA, GL_UNSIGNED_BYTE, rawImagePixels); - dataProvider = CGDataProviderCreateWithData(NULL, rawImagePixels, totalBytesForImage, dataProviderReleaseCallback); - [self unlock]; // Don't need to keep this around anymore - } - - CGColorSpaceRef defaultRGBColorSpace = CGColorSpaceCreateDeviceRGB(); - - if ([GPUImageContext supportsFastTextureUpload]) - { -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - cgImageFromBytes = CGImageCreate((int)_size.width, (int)_size.height, 8, 32, CVPixelBufferGetBytesPerRow(renderTarget), defaultRGBColorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst, dataProvider, NULL, NO, kCGRenderingIntentDefault); -#else -#endif - } - else - { - cgImageFromBytes = CGImageCreate((int)_size.width, (int)_size.height, 8, 32, 4 * (int)_size.width, defaultRGBColorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaLast, dataProvider, NULL, NO, kCGRenderingIntentDefault); - } - - // Capture image with current device orientation - CGDataProviderRelease(dataProvider); - CGColorSpaceRelease(defaultRGBColorSpace); - - }); - - return cgImageFromBytes; -} - -- (void)restoreRenderTarget; -{ -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - [self unlockAfterReading]; - CFRelease(renderTarget); -#else -#endif -} - -#pragma mark - -#pragma mark Raw data bytes - -- (void)lockForReading -{ -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - if ([GPUImageContext supportsFastTextureUpload]) - { - if (readLockCount == 0) - { - CVPixelBufferLockBaseAddress(renderTarget, 0); - } - readLockCount++; - } -#endif -} - -- (void)unlockAfterReading -{ -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - if ([GPUImageContext supportsFastTextureUpload]) - { - NSAssert(readLockCount > 0, @"Unbalanced call to -[GPUImageFramebuffer unlockAfterReading]"); - readLockCount--; - if (readLockCount == 0) - { - CVPixelBufferUnlockBaseAddress(renderTarget, 0); - } - } -#endif -} - -- (NSUInteger)bytesPerRow; -{ - if ([GPUImageContext supportsFastTextureUpload]) - { -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - return CVPixelBufferGetBytesPerRow(renderTarget); -#else - return _size.width * 4; // TODO: do more with this on the non-texture-cache side -#endif - } - else - { - return _size.width * 4; - } -} - -- (GLubyte *)byteBuffer; -{ -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - [self lockForReading]; - GLubyte * bufferBytes = CVPixelBufferGetBaseAddress(renderTarget); - [self unlockAfterReading]; - return bufferBytes; -#else - return NULL; // TODO: do more with this on the non-texture-cache side -#endif -} - -- (GLuint)texture; -{ -// NSLog(@"Accessing texture: %d from FB: %@", _texture, self); - return _texture; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFramebufferCache.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFramebufferCache.h deleted file mode 100644 index e56a3456..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFramebufferCache.h +++ /dev/null @@ -1,15 +0,0 @@ -#import -#import -#import "GPUImageFramebuffer.h" - -@interface GPUImageFramebufferCache : NSObject - -// Framebuffer management -- (GPUImageFramebuffer *)fetchFramebufferForSize:(CGSize)framebufferSize textureOptions:(GPUTextureOptions)textureOptions onlyTexture:(BOOL)onlyTexture; -- (GPUImageFramebuffer *)fetchFramebufferForSize:(CGSize)framebufferSize onlyTexture:(BOOL)onlyTexture; -- (void)returnFramebufferToCache:(GPUImageFramebuffer *)framebuffer; -- (void)purgeAllUnassignedFramebuffers; -- (void)addFramebufferToActiveImageCaptureList:(GPUImageFramebuffer *)framebuffer; -- (void)removeFramebufferFromActiveImageCaptureList:(GPUImageFramebuffer *)framebuffer; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFramebufferCache.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFramebufferCache.m deleted file mode 100644 index 21925ad9..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageFramebufferCache.m +++ /dev/null @@ -1,179 +0,0 @@ -#import "GPUImageFramebufferCache.h" -#import "GPUImageContext.h" -#import "GPUImageOutput.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -#import -#else -#endif - -@interface GPUImageFramebufferCache() -{ -// NSCache *framebufferCache; - NSMutableDictionary *framebufferCache; - NSMutableDictionary *framebufferTypeCounts; - NSMutableArray *activeImageCaptureList; // Where framebuffers that may be lost by a filter, but which are still needed for a UIImage, etc., are stored - id memoryWarningObserver; - - dispatch_queue_t framebufferCacheQueue; -} - -- (NSString *)hashForSize:(CGSize)size textureOptions:(GPUTextureOptions)textureOptions onlyTexture:(BOOL)onlyTexture; - -@end - - -@implementation GPUImageFramebufferCache - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super init])) - { - return nil; - } - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - memoryWarningObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidReceiveMemoryWarningNotification object:nil queue:nil usingBlock:^(NSNotification *note) { - - [self purgeAllUnassignedFramebuffers]; - }]; -#else -#endif - -// framebufferCache = [[NSCache alloc] init]; - framebufferCache = [[NSMutableDictionary alloc] init]; - framebufferTypeCounts = [[NSMutableDictionary alloc] init]; - activeImageCaptureList = [[NSMutableArray alloc] init]; - framebufferCacheQueue = dispatch_queue_create("com.sunsetlakesoftware.GPUImage.framebufferCacheQueue", NULL); - - return self; -} - -#pragma mark - -#pragma mark Framebuffer management - -- (NSString *)hashForSize:(CGSize)size textureOptions:(GPUTextureOptions)textureOptions onlyTexture:(BOOL)onlyTexture; -{ - if (onlyTexture) - { - return [NSString stringWithFormat:@"%.1fx%.1f-%d:%d:%d:%d:%d:%d:%d-NOFB", size.width, size.height, textureOptions.minFilter, textureOptions.magFilter, textureOptions.wrapS, textureOptions.wrapT, textureOptions.internalFormat, textureOptions.format, textureOptions.type]; - } - else - { - return [NSString stringWithFormat:@"%.1fx%.1f-%d:%d:%d:%d:%d:%d:%d", size.width, size.height, textureOptions.minFilter, textureOptions.magFilter, textureOptions.wrapS, textureOptions.wrapT, textureOptions.internalFormat, textureOptions.format, textureOptions.type]; - } -} - -- (GPUImageFramebuffer *)fetchFramebufferForSize:(CGSize)framebufferSize textureOptions:(GPUTextureOptions)textureOptions onlyTexture:(BOOL)onlyTexture; -{ - __block GPUImageFramebuffer *framebufferFromCache = nil; -// dispatch_sync(framebufferCacheQueue, ^{ - runSynchronouslyOnVideoProcessingQueue(^{ - NSString *lookupHash = [self hashForSize:framebufferSize textureOptions:textureOptions onlyTexture:onlyTexture]; - NSNumber *numberOfMatchingTexturesInCache = [framebufferTypeCounts objectForKey:lookupHash]; - NSInteger numberOfMatchingTextures = [numberOfMatchingTexturesInCache integerValue]; - - if ([numberOfMatchingTexturesInCache integerValue] < 1) - { - // Nothing in the cache, create a new framebuffer to use - framebufferFromCache = [[GPUImageFramebuffer alloc] initWithSize:framebufferSize textureOptions:textureOptions onlyTexture:onlyTexture]; - } - else - { - // Something found, pull the old framebuffer and decrement the count - NSInteger currentTextureID = (numberOfMatchingTextures - 1); - while ((framebufferFromCache == nil) && (currentTextureID >= 0)) - { - NSString *textureHash = [NSString stringWithFormat:@"%@-%ld", lookupHash, (long)currentTextureID]; - framebufferFromCache = [framebufferCache objectForKey:textureHash]; - // Test the values in the cache first, to see if they got invalidated behind our back - if (framebufferFromCache != nil) - { - // Withdraw this from the cache while it's in use - [framebufferCache removeObjectForKey:textureHash]; - } - currentTextureID--; - } - - currentTextureID++; - - [framebufferTypeCounts setObject:[NSNumber numberWithInteger:currentTextureID] forKey:lookupHash]; - - if (framebufferFromCache == nil) - { - framebufferFromCache = [[GPUImageFramebuffer alloc] initWithSize:framebufferSize textureOptions:textureOptions onlyTexture:onlyTexture]; - } - } - }); - - [framebufferFromCache lock]; - return framebufferFromCache; -} - -- (GPUImageFramebuffer *)fetchFramebufferForSize:(CGSize)framebufferSize onlyTexture:(BOOL)onlyTexture; -{ - GPUTextureOptions defaultTextureOptions; - defaultTextureOptions.minFilter = GL_LINEAR; - defaultTextureOptions.magFilter = GL_LINEAR; - defaultTextureOptions.wrapS = GL_CLAMP_TO_EDGE; - defaultTextureOptions.wrapT = GL_CLAMP_TO_EDGE; - defaultTextureOptions.internalFormat = GL_RGBA; - defaultTextureOptions.format = GL_BGRA; - defaultTextureOptions.type = GL_UNSIGNED_BYTE; - - return [self fetchFramebufferForSize:framebufferSize textureOptions:defaultTextureOptions onlyTexture:onlyTexture]; -} - -- (void)returnFramebufferToCache:(GPUImageFramebuffer *)framebuffer; -{ - [framebuffer clearAllLocks]; - -// dispatch_async(framebufferCacheQueue, ^{ - runAsynchronouslyOnVideoProcessingQueue(^{ - CGSize framebufferSize = framebuffer.size; - GPUTextureOptions framebufferTextureOptions = framebuffer.textureOptions; - NSString *lookupHash = [self hashForSize:framebufferSize textureOptions:framebufferTextureOptions onlyTexture:framebuffer.missingFramebuffer]; - NSNumber *numberOfMatchingTexturesInCache = [framebufferTypeCounts objectForKey:lookupHash]; - NSInteger numberOfMatchingTextures = [numberOfMatchingTexturesInCache integerValue]; - - NSString *textureHash = [NSString stringWithFormat:@"%@-%ld", lookupHash, (long)numberOfMatchingTextures]; - -// [framebufferCache setObject:framebuffer forKey:textureHash cost:round(framebufferSize.width * framebufferSize.height * 4.0)]; - [framebufferCache setObject:framebuffer forKey:textureHash]; - [framebufferTypeCounts setObject:[NSNumber numberWithInteger:(numberOfMatchingTextures + 1)] forKey:lookupHash]; - }); -} - -- (void)purgeAllUnassignedFramebuffers; -{ - runAsynchronouslyOnVideoProcessingQueue(^{ -// dispatch_async(framebufferCacheQueue, ^{ - [framebufferCache removeAllObjects]; - [framebufferTypeCounts removeAllObjects]; -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - CVOpenGLESTextureCacheFlush([[GPUImageContext sharedImageProcessingContext] coreVideoTextureCache], 0); -#else -#endif - }); -} - -- (void)addFramebufferToActiveImageCaptureList:(GPUImageFramebuffer *)framebuffer; -{ - runAsynchronouslyOnVideoProcessingQueue(^{ -// dispatch_async(framebufferCacheQueue, ^{ - [activeImageCaptureList addObject:framebuffer]; - }); -} - -- (void)removeFramebufferFromActiveImageCaptureList:(GPUImageFramebuffer *)framebuffer; -{ - runAsynchronouslyOnVideoProcessingQueue(^{ -// dispatch_async(framebufferCacheQueue, ^{ - [activeImageCaptureList removeObject:framebuffer]; - }); -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGammaFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGammaFilter.h deleted file mode 100755 index 0521d089..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGammaFilter.h +++ /dev/null @@ -1,11 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageGammaFilter : GPUImageFilter -{ - GLint gammaUniform; -} - -// Gamma ranges from 0.0 to 3.0, with 1.0 as the normal level -@property(readwrite, nonatomic) CGFloat gamma; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGammaFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGammaFilter.m deleted file mode 100755 index 35adaba2..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGammaFilter.m +++ /dev/null @@ -1,66 +0,0 @@ -#import "GPUImageGammaFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageGammaFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform lowp float gamma; - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - gl_FragColor = vec4(pow(textureColor.rgb, vec3(gamma)), textureColor.w); - } -); -#else -NSString *const kGPUImageGammaFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float gamma; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - gl_FragColor = vec4(pow(textureColor.rgb, vec3(gamma)), textureColor.w); - } -); -#endif - -@implementation GPUImageGammaFilter - -@synthesize gamma = _gamma; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageGammaFragmentShaderString])) - { - return nil; - } - - gammaUniform = [filterProgram uniformIndex:@"gamma"]; - self.gamma = 1.0; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setGamma:(CGFloat)newValue; -{ - _gamma = newValue; - - [self setFloat:_gamma forUniform:gammaUniform program:filterProgram]; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianBlurFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianBlurFilter.h deleted file mode 100755 index 1fb7a137..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianBlurFilter.h +++ /dev/null @@ -1,36 +0,0 @@ -#import "GPUImageTwoPassTextureSamplingFilter.h" - -/** A Gaussian blur filter - Interpolated optimization based on Daniel Rákos' work at http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/ - */ - -@interface GPUImageGaussianBlurFilter : GPUImageTwoPassTextureSamplingFilter -{ - BOOL shouldResizeBlurRadiusWithImageSize; - CGFloat _blurRadiusInPixels; -} - -/** A multiplier for the spacing between texels, ranging from 0.0 on up, with a default of 1.0. Adjusting this may slightly increase the blur strength, but will introduce artifacts in the result. - */ -@property (readwrite, nonatomic) CGFloat texelSpacingMultiplier; - -/** A radius in pixels to use for the blur, with a default of 2.0. This adjusts the sigma variable in the Gaussian distribution function. - */ -@property (readwrite, nonatomic) CGFloat blurRadiusInPixels; - -/** Setting these properties will allow the blur radius to scale with the size of the image. These properties are mutually exclusive; setting either will set the other to 0. - */ -@property (readwrite, nonatomic) CGFloat blurRadiusAsFractionOfImageWidth; -@property (readwrite, nonatomic) CGFloat blurRadiusAsFractionOfImageHeight; - -/// The number of times to sequentially blur the incoming image. The more passes, the slower the filter. -@property(readwrite, nonatomic) NSUInteger blurPasses; - -+ (NSString *)vertexShaderForStandardBlurOfRadius:(NSUInteger)blurRadius sigma:(CGFloat)sigma; -+ (NSString *)fragmentShaderForStandardBlurOfRadius:(NSUInteger)blurRadius sigma:(CGFloat)sigma; -+ (NSString *)vertexShaderForOptimizedBlurOfRadius:(NSUInteger)blurRadius sigma:(CGFloat)sigma; -+ (NSString *)fragmentShaderForOptimizedBlurOfRadius:(NSUInteger)blurRadius sigma:(CGFloat)sigma; - -- (void)switchToVertexShader:(NSString *)newVertexShader fragmentShader:(NSString *)newFragmentShader; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianBlurFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianBlurFilter.m deleted file mode 100755 index ec99352a..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianBlurFilter.m +++ /dev/null @@ -1,513 +0,0 @@ -#import "GPUImageGaussianBlurFilter.h" - -@implementation GPUImageGaussianBlurFilter - -@synthesize texelSpacingMultiplier = _texelSpacingMultiplier; -@synthesize blurRadiusInPixels = _blurRadiusInPixels; -@synthesize blurRadiusAsFractionOfImageWidth = _blurRadiusAsFractionOfImageWidth; -@synthesize blurRadiusAsFractionOfImageHeight = _blurRadiusAsFractionOfImageHeight; -@synthesize blurPasses = _blurPasses; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithFirstStageVertexShaderFromString:(NSString *)firstStageVertexShaderString firstStageFragmentShaderFromString:(NSString *)firstStageFragmentShaderString secondStageVertexShaderFromString:(NSString *)secondStageVertexShaderString secondStageFragmentShaderFromString:(NSString *)secondStageFragmentShaderString -{ - if (!(self = [super initWithFirstStageVertexShaderFromString:firstStageVertexShaderString firstStageFragmentShaderFromString:firstStageFragmentShaderString secondStageVertexShaderFromString:secondStageVertexShaderString secondStageFragmentShaderFromString:secondStageFragmentShaderString])) - { - return nil; - } - - self.texelSpacingMultiplier = 1.0; - _blurRadiusInPixels = 2.0; - shouldResizeBlurRadiusWithImageSize = NO; - - return self; -} - -- (id)init; -{ - NSString *currentGaussianBlurVertexShader = [[self class] vertexShaderForOptimizedBlurOfRadius:4 sigma:2.0]; - NSString *currentGaussianBlurFragmentShader = [[self class] fragmentShaderForOptimizedBlurOfRadius:4 sigma:2.0]; - - return [self initWithFirstStageVertexShaderFromString:currentGaussianBlurVertexShader firstStageFragmentShaderFromString:currentGaussianBlurFragmentShader secondStageVertexShaderFromString:currentGaussianBlurVertexShader secondStageFragmentShaderFromString:currentGaussianBlurFragmentShader]; -} - -#pragma mark - -#pragma mark Auto-generation of optimized Gaussian shaders - -// "Implementation limit of 32 varying components exceeded" - Max number of varyings for these GPUs - -+ (NSString *)vertexShaderForStandardBlurOfRadius:(NSUInteger)blurRadius sigma:(CGFloat)sigma; -{ - if (blurRadius < 1) - { - return kGPUImageVertexShaderString; - } - -// NSLog(@"Max varyings: %d", [GPUImageContext maximumVaryingVectorsForThisDevice]); - NSMutableString *shaderString = [[NSMutableString alloc] init]; - - // Header - [shaderString appendFormat:@"\ - attribute vec4 position;\n\ - attribute vec4 inputTextureCoordinate;\n\ - \n\ - uniform float texelWidthOffset;\n\ - uniform float texelHeightOffset;\n\ - \n\ - varying vec2 blurCoordinates[%lu];\n\ - \n\ - void main()\n\ - {\n\ - gl_Position = position;\n\ - \n\ - vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset);\n", (unsigned long)(blurRadius * 2 + 1) ]; - - // Inner offset loop - for (NSUInteger currentBlurCoordinateIndex = 0; currentBlurCoordinateIndex < (blurRadius * 2 + 1); currentBlurCoordinateIndex++) - { - NSInteger offsetFromCenter = currentBlurCoordinateIndex - blurRadius; - if (offsetFromCenter < 0) - { - [shaderString appendFormat:@"blurCoordinates[%ld] = inputTextureCoordinate.xy - singleStepOffset * %f;\n", (unsigned long)currentBlurCoordinateIndex, (GLfloat)(-offsetFromCenter)]; - } - else if (offsetFromCenter > 0) - { - [shaderString appendFormat:@"blurCoordinates[%ld] = inputTextureCoordinate.xy + singleStepOffset * %f;\n", (unsigned long)currentBlurCoordinateIndex, (GLfloat)(offsetFromCenter)]; - } - else - { - [shaderString appendFormat:@"blurCoordinates[%ld] = inputTextureCoordinate.xy;\n", (unsigned long)currentBlurCoordinateIndex]; - } - } - - // Footer - [shaderString appendString:@"}\n"]; - - return shaderString; -} - -+ (NSString *)fragmentShaderForStandardBlurOfRadius:(NSUInteger)blurRadius sigma:(CGFloat)sigma; -{ - if (blurRadius < 1) - { - return kGPUImagePassthroughFragmentShaderString; - } - - // First, generate the normal Gaussian weights for a given sigma - GLfloat *standardGaussianWeights = calloc(blurRadius + 1, sizeof(GLfloat)); - GLfloat sumOfWeights = 0.0; - for (NSUInteger currentGaussianWeightIndex = 0; currentGaussianWeightIndex < blurRadius + 1; currentGaussianWeightIndex++) - { - standardGaussianWeights[currentGaussianWeightIndex] = (1.0 / sqrt(2.0 * M_PI * pow(sigma, 2.0))) * exp(-pow(currentGaussianWeightIndex, 2.0) / (2.0 * pow(sigma, 2.0))); - - if (currentGaussianWeightIndex == 0) - { - sumOfWeights += standardGaussianWeights[currentGaussianWeightIndex]; - } - else - { - sumOfWeights += 2.0 * standardGaussianWeights[currentGaussianWeightIndex]; - } - } - - // Next, normalize these weights to prevent the clipping of the Gaussian curve at the end of the discrete samples from reducing luminance - for (NSUInteger currentGaussianWeightIndex = 0; currentGaussianWeightIndex < blurRadius + 1; currentGaussianWeightIndex++) - { - standardGaussianWeights[currentGaussianWeightIndex] = standardGaussianWeights[currentGaussianWeightIndex] / sumOfWeights; - } - - // Finally, generate the shader from these weights - NSMutableString *shaderString = [[NSMutableString alloc] init]; - - // Header -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - [shaderString appendFormat:@"\ - uniform sampler2D inputImageTexture;\n\ - \n\ - varying highp vec2 blurCoordinates[%lu];\n\ - \n\ - void main()\n\ - {\n\ - lowp vec4 sum = vec4(0.0);\n", (unsigned long)(blurRadius * 2 + 1) ]; -#else - [shaderString appendFormat:@"\ - uniform sampler2D inputImageTexture;\n\ - \n\ - varying vec2 blurCoordinates[%lu];\n\ - \n\ - void main()\n\ - {\n\ - vec4 sum = vec4(0.0);\n", (blurRadius * 2 + 1) ]; -#endif - - // Inner texture loop - for (NSUInteger currentBlurCoordinateIndex = 0; currentBlurCoordinateIndex < (blurRadius * 2 + 1); currentBlurCoordinateIndex++) - { - NSInteger offsetFromCenter = currentBlurCoordinateIndex - blurRadius; - if (offsetFromCenter < 0) - { - [shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[%lu]) * %f;\n", (unsigned long)currentBlurCoordinateIndex, standardGaussianWeights[-offsetFromCenter]]; - } - else - { - [shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[%lu]) * %f;\n", (unsigned long)currentBlurCoordinateIndex, standardGaussianWeights[offsetFromCenter]]; - } - } - - // Footer - [shaderString appendString:@"\ - gl_FragColor = sum;\n\ - }\n"]; - - free(standardGaussianWeights); - return shaderString; -} - -+ (NSString *)vertexShaderForOptimizedBlurOfRadius:(NSUInteger)blurRadius sigma:(CGFloat)sigma; -{ - if (blurRadius < 1) - { - return kGPUImageVertexShaderString; - } - - // First, generate the normal Gaussian weights for a given sigma - GLfloat *standardGaussianWeights = calloc(blurRadius + 1, sizeof(GLfloat)); - GLfloat sumOfWeights = 0.0; - for (NSUInteger currentGaussianWeightIndex = 0; currentGaussianWeightIndex < blurRadius + 1; currentGaussianWeightIndex++) - { - standardGaussianWeights[currentGaussianWeightIndex] = (1.0 / sqrt(2.0 * M_PI * pow(sigma, 2.0))) * exp(-pow(currentGaussianWeightIndex, 2.0) / (2.0 * pow(sigma, 2.0))); - - if (currentGaussianWeightIndex == 0) - { - sumOfWeights += standardGaussianWeights[currentGaussianWeightIndex]; - } - else - { - sumOfWeights += 2.0 * standardGaussianWeights[currentGaussianWeightIndex]; - } - } - - // Next, normalize these weights to prevent the clipping of the Gaussian curve at the end of the discrete samples from reducing luminance - for (NSUInteger currentGaussianWeightIndex = 0; currentGaussianWeightIndex < blurRadius + 1; currentGaussianWeightIndex++) - { - standardGaussianWeights[currentGaussianWeightIndex] = standardGaussianWeights[currentGaussianWeightIndex] / sumOfWeights; - } - - // From these weights we calculate the offsets to read interpolated values from - NSUInteger numberOfOptimizedOffsets = MIN(blurRadius / 2 + (blurRadius % 2), 7); - GLfloat *optimizedGaussianOffsets = calloc(numberOfOptimizedOffsets, sizeof(GLfloat)); - - for (NSUInteger currentOptimizedOffset = 0; currentOptimizedOffset < numberOfOptimizedOffsets; currentOptimizedOffset++) - { - GLfloat firstWeight = standardGaussianWeights[currentOptimizedOffset*2 + 1]; - GLfloat secondWeight = standardGaussianWeights[currentOptimizedOffset*2 + 2]; - - GLfloat optimizedWeight = firstWeight + secondWeight; - - optimizedGaussianOffsets[currentOptimizedOffset] = (firstWeight * (currentOptimizedOffset*2 + 1) + secondWeight * (currentOptimizedOffset*2 + 2)) / optimizedWeight; - } - - NSMutableString *shaderString = [[NSMutableString alloc] init]; - // Header - [shaderString appendFormat:@"\ - attribute vec4 position;\n\ - attribute vec4 inputTextureCoordinate;\n\ - \n\ - uniform float texelWidthOffset;\n\ - uniform float texelHeightOffset;\n\ - \n\ - varying vec2 blurCoordinates[%lu];\n\ - \n\ - void main()\n\ - {\n\ - gl_Position = position;\n\ - \n\ - vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset);\n", (unsigned long)(1 + (numberOfOptimizedOffsets * 2))]; - - // Inner offset loop - [shaderString appendString:@"blurCoordinates[0] = inputTextureCoordinate.xy;\n"]; - for (NSUInteger currentOptimizedOffset = 0; currentOptimizedOffset < numberOfOptimizedOffsets; currentOptimizedOffset++) - { - [shaderString appendFormat:@"\ - blurCoordinates[%lu] = inputTextureCoordinate.xy + singleStepOffset * %f;\n\ - blurCoordinates[%lu] = inputTextureCoordinate.xy - singleStepOffset * %f;\n", (unsigned long)((currentOptimizedOffset * 2) + 1), optimizedGaussianOffsets[currentOptimizedOffset], (unsigned long)((currentOptimizedOffset * 2) + 2), optimizedGaussianOffsets[currentOptimizedOffset]]; - } - - // Footer - [shaderString appendString:@"}\n"]; - - free(optimizedGaussianOffsets); - free(standardGaussianWeights); - return shaderString; -} - -+ (NSString *)fragmentShaderForOptimizedBlurOfRadius:(NSUInteger)blurRadius sigma:(CGFloat)sigma; -{ - if (blurRadius < 1) - { - return kGPUImagePassthroughFragmentShaderString; - } - - // First, generate the normal Gaussian weights for a given sigma - GLfloat *standardGaussianWeights = calloc(blurRadius + 1, sizeof(GLfloat)); - GLfloat sumOfWeights = 0.0; - for (NSUInteger currentGaussianWeightIndex = 0; currentGaussianWeightIndex < blurRadius + 1; currentGaussianWeightIndex++) - { - standardGaussianWeights[currentGaussianWeightIndex] = (1.0 / sqrt(2.0 * M_PI * pow(sigma, 2.0))) * exp(-pow(currentGaussianWeightIndex, 2.0) / (2.0 * pow(sigma, 2.0))); - - if (currentGaussianWeightIndex == 0) - { - sumOfWeights += standardGaussianWeights[currentGaussianWeightIndex]; - } - else - { - sumOfWeights += 2.0 * standardGaussianWeights[currentGaussianWeightIndex]; - } - } - - // Next, normalize these weights to prevent the clipping of the Gaussian curve at the end of the discrete samples from reducing luminance - for (NSUInteger currentGaussianWeightIndex = 0; currentGaussianWeightIndex < blurRadius + 1; currentGaussianWeightIndex++) - { - standardGaussianWeights[currentGaussianWeightIndex] = standardGaussianWeights[currentGaussianWeightIndex] / sumOfWeights; - } - - // From these weights we calculate the offsets to read interpolated values from - NSUInteger numberOfOptimizedOffsets = MIN(blurRadius / 2 + (blurRadius % 2), 7); - NSUInteger trueNumberOfOptimizedOffsets = blurRadius / 2 + (blurRadius % 2); - - NSMutableString *shaderString = [[NSMutableString alloc] init]; - - // Header -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - [shaderString appendFormat:@"\ - uniform sampler2D inputImageTexture;\n\ - uniform highp float texelWidthOffset;\n\ - uniform highp float texelHeightOffset;\n\ - \n\ - varying highp vec2 blurCoordinates[%lu];\n\ - \n\ - void main()\n\ - {\n\ - lowp vec4 sum = vec4(0.0);\n", (unsigned long)(1 + (numberOfOptimizedOffsets * 2)) ]; -#else - [shaderString appendFormat:@"\ - uniform sampler2D inputImageTexture;\n\ - uniform float texelWidthOffset;\n\ - uniform float texelHeightOffset;\n\ - \n\ - varying vec2 blurCoordinates[%lu];\n\ - \n\ - void main()\n\ - {\n\ - vec4 sum = vec4(0.0);\n", 1 + (numberOfOptimizedOffsets * 2) ]; -#endif - - // Inner texture loop - [shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[0]) * %f;\n", standardGaussianWeights[0]]; - - for (NSUInteger currentBlurCoordinateIndex = 0; currentBlurCoordinateIndex < numberOfOptimizedOffsets; currentBlurCoordinateIndex++) - { - GLfloat firstWeight = standardGaussianWeights[currentBlurCoordinateIndex * 2 + 1]; - GLfloat secondWeight = standardGaussianWeights[currentBlurCoordinateIndex * 2 + 2]; - GLfloat optimizedWeight = firstWeight + secondWeight; - - [shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[%lu]) * %f;\n", (unsigned long)((currentBlurCoordinateIndex * 2) + 1), optimizedWeight]; - [shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[%lu]) * %f;\n", (unsigned long)((currentBlurCoordinateIndex * 2) + 2), optimizedWeight]; - } - - // If the number of required samples exceeds the amount we can pass in via varyings, we have to do dependent texture reads in the fragment shader - if (trueNumberOfOptimizedOffsets > numberOfOptimizedOffsets) - { -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - [shaderString appendString:@"highp vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset);\n"]; -#else - [shaderString appendString:@"vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset);\n"]; -#endif - - for (NSUInteger currentOverlowTextureRead = numberOfOptimizedOffsets; currentOverlowTextureRead < trueNumberOfOptimizedOffsets; currentOverlowTextureRead++) - { - GLfloat firstWeight = standardGaussianWeights[currentOverlowTextureRead * 2 + 1]; - GLfloat secondWeight = standardGaussianWeights[currentOverlowTextureRead * 2 + 2]; - - GLfloat optimizedWeight = firstWeight + secondWeight; - GLfloat optimizedOffset = (firstWeight * (currentOverlowTextureRead * 2 + 1) + secondWeight * (currentOverlowTextureRead * 2 + 2)) / optimizedWeight; - - [shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[0] + singleStepOffset * %f) * %f;\n", optimizedOffset, optimizedWeight]; - [shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[0] - singleStepOffset * %f) * %f;\n", optimizedOffset, optimizedWeight]; - } - } - - // Footer - [shaderString appendString:@"\ - gl_FragColor = sum;\n\ - }\n"]; - - free(standardGaussianWeights); - return shaderString; -} - -- (void)setupFilterForSize:(CGSize)filterFrameSize; -{ - [super setupFilterForSize:filterFrameSize]; - - if (shouldResizeBlurRadiusWithImageSize) - { - if (self.blurRadiusAsFractionOfImageWidth > 0) - { - self.blurRadiusInPixels = filterFrameSize.width * self.blurRadiusAsFractionOfImageWidth; - } - else - { - self.blurRadiusInPixels = filterFrameSize.height * self.blurRadiusAsFractionOfImageHeight; - } - } -} - -#pragma mark - -#pragma mark Rendering - -- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates; -{ - [super renderToTextureWithVertices:vertices textureCoordinates:textureCoordinates]; - - for (NSUInteger currentAdditionalBlurPass = 1; currentAdditionalBlurPass < _blurPasses; currentAdditionalBlurPass++) - { - [super renderToTextureWithVertices:vertices textureCoordinates:[[self class] textureCoordinatesForRotation:kGPUImageNoRotation]]; - } -} - -- (void)switchToVertexShader:(NSString *)newVertexShader fragmentShader:(NSString *)newFragmentShader; -{ - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext useImageProcessingContext]; - - filterProgram = [[GPUImageContext sharedImageProcessingContext] programForVertexShaderString:newVertexShader fragmentShaderString:newFragmentShader]; - - if (!filterProgram.initialized) - { - [self initializeAttributes]; - - if (![filterProgram link]) - { - NSString *progLog = [filterProgram programLog]; - NSLog(@"Program link log: %@", progLog); - NSString *fragLog = [filterProgram fragmentShaderLog]; - NSLog(@"Fragment shader compile log: %@", fragLog); - NSString *vertLog = [filterProgram vertexShaderLog]; - NSLog(@"Vertex shader compile log: %@", vertLog); - filterProgram = nil; - NSAssert(NO, @"Filter shader link failed"); - } - } - - filterPositionAttribute = [filterProgram attributeIndex:@"position"]; - filterTextureCoordinateAttribute = [filterProgram attributeIndex:@"inputTextureCoordinate"]; - filterInputTextureUniform = [filterProgram uniformIndex:@"inputImageTexture"]; // This does assume a name of "inputImageTexture" for the fragment shader - verticalPassTexelWidthOffsetUniform = [filterProgram uniformIndex:@"texelWidthOffset"]; - verticalPassTexelHeightOffsetUniform = [filterProgram uniformIndex:@"texelHeightOffset"]; - [GPUImageContext setActiveShaderProgram:filterProgram]; - - glEnableVertexAttribArray(filterPositionAttribute); - glEnableVertexAttribArray(filterTextureCoordinateAttribute); - - secondFilterProgram = [[GPUImageContext sharedImageProcessingContext] programForVertexShaderString:newVertexShader fragmentShaderString:newFragmentShader]; - - if (!secondFilterProgram.initialized) - { - [self initializeSecondaryAttributes]; - - if (![secondFilterProgram link]) - { - NSString *progLog = [secondFilterProgram programLog]; - NSLog(@"Program link log: %@", progLog); - NSString *fragLog = [secondFilterProgram fragmentShaderLog]; - NSLog(@"Fragment shader compile log: %@", fragLog); - NSString *vertLog = [secondFilterProgram vertexShaderLog]; - NSLog(@"Vertex shader compile log: %@", vertLog); - secondFilterProgram = nil; - NSAssert(NO, @"Filter shader link failed"); - } - } - - secondFilterPositionAttribute = [secondFilterProgram attributeIndex:@"position"]; - secondFilterTextureCoordinateAttribute = [secondFilterProgram attributeIndex:@"inputTextureCoordinate"]; - secondFilterInputTextureUniform = [secondFilterProgram uniformIndex:@"inputImageTexture"]; // This does assume a name of "inputImageTexture" for the fragment shader - secondFilterInputTextureUniform2 = [secondFilterProgram uniformIndex:@"inputImageTexture2"]; // This does assume a name of "inputImageTexture2" for second input texture in the fragment shader - horizontalPassTexelWidthOffsetUniform = [secondFilterProgram uniformIndex:@"texelWidthOffset"]; - horizontalPassTexelHeightOffsetUniform = [secondFilterProgram uniformIndex:@"texelHeightOffset"]; - [GPUImageContext setActiveShaderProgram:secondFilterProgram]; - - glEnableVertexAttribArray(secondFilterPositionAttribute); - glEnableVertexAttribArray(secondFilterTextureCoordinateAttribute); - - [self setupFilterForSize:[self sizeOfFBO]]; - glFinish(); - }); - -} - -#pragma mark - -#pragma mark Accessors - -- (void)setTexelSpacingMultiplier:(CGFloat)newValue; -{ - _texelSpacingMultiplier = newValue; - - _verticalTexelSpacing = _texelSpacingMultiplier; - _horizontalTexelSpacing = _texelSpacingMultiplier; - - [self setupFilterForSize:[self sizeOfFBO]]; -} - -// inputRadius for Core Image's CIGaussianBlur is really sigma in the Gaussian equation, so I'm using that for my blur radius, to be consistent -- (void)setBlurRadiusInPixels:(CGFloat)newValue; -{ - // 7.0 is the limit for blur size for hardcoded varying offsets - - if (round(newValue) != _blurRadiusInPixels) - { - _blurRadiusInPixels = round(newValue); // For now, only do integral sigmas - - NSUInteger calculatedSampleRadius = 0; - if (_blurRadiusInPixels >= 1) // Avoid a divide-by-zero error here - { - // Calculate the number of pixels to sample from by setting a bottom limit for the contribution of the outermost pixel - CGFloat minimumWeightToFindEdgeOfSamplingArea = 1.0/256.0; - calculatedSampleRadius = floor(sqrt(-2.0 * pow(_blurRadiusInPixels, 2.0) * log(minimumWeightToFindEdgeOfSamplingArea * sqrt(2.0 * M_PI * pow(_blurRadiusInPixels, 2.0))) )); - calculatedSampleRadius += calculatedSampleRadius % 2; // There's nothing to gain from handling odd radius sizes, due to the optimizations I use - } - -// NSLog(@"Blur radius: %f, calculated sample radius: %d", _blurRadiusInPixels, calculatedSampleRadius); -// - NSString *newGaussianBlurVertexShader = [[self class] vertexShaderForOptimizedBlurOfRadius:calculatedSampleRadius sigma:_blurRadiusInPixels]; - NSString *newGaussianBlurFragmentShader = [[self class] fragmentShaderForOptimizedBlurOfRadius:calculatedSampleRadius sigma:_blurRadiusInPixels]; - -// NSLog(@"Optimized vertex shader: \n%@", newGaussianBlurVertexShader); -// NSLog(@"Optimized fragment shader: \n%@", newGaussianBlurFragmentShader); -// - [self switchToVertexShader:newGaussianBlurVertexShader fragmentShader:newGaussianBlurFragmentShader]; - } - shouldResizeBlurRadiusWithImageSize = NO; -} - -- (void)setBlurRadiusAsFractionOfImageWidth:(CGFloat)blurRadiusAsFractionOfImageWidth -{ - if (blurRadiusAsFractionOfImageWidth < 0) return; - - shouldResizeBlurRadiusWithImageSize = _blurRadiusAsFractionOfImageWidth != blurRadiusAsFractionOfImageWidth && blurRadiusAsFractionOfImageWidth > 0; - _blurRadiusAsFractionOfImageWidth = blurRadiusAsFractionOfImageWidth; - _blurRadiusAsFractionOfImageHeight = 0; -} - -- (void)setBlurRadiusAsFractionOfImageHeight:(CGFloat)blurRadiusAsFractionOfImageHeight -{ - if (blurRadiusAsFractionOfImageHeight < 0) return; - - shouldResizeBlurRadiusWithImageSize = _blurRadiusAsFractionOfImageHeight != blurRadiusAsFractionOfImageHeight && blurRadiusAsFractionOfImageHeight > 0; - _blurRadiusAsFractionOfImageHeight = blurRadiusAsFractionOfImageHeight; - _blurRadiusAsFractionOfImageWidth = 0; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianBlurPositionFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianBlurPositionFilter.h deleted file mode 100755 index dc88a563..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianBlurPositionFilter.h +++ /dev/null @@ -1,22 +0,0 @@ -#import "GPUImageTwoPassTextureSamplingFilter.h" - -/** A more generalized 9x9 Gaussian blur filter - */ -@interface GPUImageGaussianBlurPositionFilter : GPUImageTwoPassTextureSamplingFilter -{ - GLint blurCenterUniform, blurRadiusUniform, aspectRatioUniform; -} - -/** A multiplier for the blur size, ranging from 0.0 on up, with a default of 1.0 - */ -@property (readwrite, nonatomic) CGFloat blurSize; - -/** Center for the blur, defaults to 0.5, 0.5 - */ -@property (readwrite, nonatomic) CGPoint blurCenter; - -/** Radius for the blur, defaults to 1.0 - */ -@property (readwrite, nonatomic) CGFloat blurRadius; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianBlurPositionFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianBlurPositionFilter.m deleted file mode 100755 index 8ecd9246..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianBlurPositionFilter.m +++ /dev/null @@ -1,232 +0,0 @@ -#import "GPUImageGaussianBlurPositionFilter.h" - -NSString *const kGPUImageGaussianBlurPositionVertexShaderString = SHADER_STRING -( - attribute vec4 position; - attribute vec4 inputTextureCoordinate; - - const int GAUSSIAN_SAMPLES = 9; - - uniform float texelWidthOffset; - uniform float texelHeightOffset; - varying vec2 textureCoordinate; - varying vec2 blurCoordinates[GAUSSIAN_SAMPLES]; - - void main() - { - gl_Position = position; - textureCoordinate = inputTextureCoordinate.xy; - - // Calculate the positions for the blur - int multiplier = 0; - vec2 blurStep; - vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset); - - for (int i = 0; i < GAUSSIAN_SAMPLES; i++) { - multiplier = (i - ((GAUSSIAN_SAMPLES - 1) / 2)); - // Blur in x (horizontal) - blurStep = float(multiplier) * singleStepOffset; - blurCoordinates[i] = inputTextureCoordinate.xy + blurStep; - } - } -); - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageGaussianBlurPositionFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - - const lowp int GAUSSIAN_SAMPLES = 9; - - varying highp vec2 textureCoordinate; - varying highp vec2 blurCoordinates[GAUSSIAN_SAMPLES]; - - uniform highp float aspectRatio; - uniform lowp vec2 blurCenter; - uniform highp float blurRadius; - - void main() { - highp vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); - highp float dist = distance(blurCenter, textureCoordinateToUse); - - if (dist < blurRadius) - { - lowp vec4 sum = vec4(0.0); - - sum += texture2D(inputImageTexture, blurCoordinates[0]) * 0.05; - sum += texture2D(inputImageTexture, blurCoordinates[1]) * 0.09; - sum += texture2D(inputImageTexture, blurCoordinates[2]) * 0.12; - sum += texture2D(inputImageTexture, blurCoordinates[3]) * 0.15; - sum += texture2D(inputImageTexture, blurCoordinates[4]) * 0.18; - sum += texture2D(inputImageTexture, blurCoordinates[5]) * 0.15; - sum += texture2D(inputImageTexture, blurCoordinates[6]) * 0.12; - sum += texture2D(inputImageTexture, blurCoordinates[7]) * 0.09; - sum += texture2D(inputImageTexture, blurCoordinates[8]) * 0.05; - - gl_FragColor = sum; - } - else - { - gl_FragColor = texture2D(inputImageTexture, textureCoordinate); - } - } -); -#else -NSString *const kGPUImageGaussianBlurPositionFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - - const int GAUSSIAN_SAMPLES = 9; - - varying vec2 textureCoordinate; - varying vec2 blurCoordinates[GAUSSIAN_SAMPLES]; - - uniform float aspectRatio; - uniform vec2 blurCenter; - uniform float blurRadius; - - void main() - { - vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); - float dist = distance(blurCenter, textureCoordinateToUse); - - if (dist < blurRadius) - { - vec4 sum = vec4(0.0); - - sum += texture2D(inputImageTexture, blurCoordinates[0]) * 0.05; - sum += texture2D(inputImageTexture, blurCoordinates[1]) * 0.09; - sum += texture2D(inputImageTexture, blurCoordinates[2]) * 0.12; - sum += texture2D(inputImageTexture, blurCoordinates[3]) * 0.15; - sum += texture2D(inputImageTexture, blurCoordinates[4]) * 0.18; - sum += texture2D(inputImageTexture, blurCoordinates[5]) * 0.15; - sum += texture2D(inputImageTexture, blurCoordinates[6]) * 0.12; - sum += texture2D(inputImageTexture, blurCoordinates[7]) * 0.09; - sum += texture2D(inputImageTexture, blurCoordinates[8]) * 0.05; - - gl_FragColor = sum; - } - else - { - gl_FragColor = texture2D(inputImageTexture, textureCoordinate); - } - } -); -#endif - -@interface GPUImageGaussianBlurPositionFilter () - -- (void)adjustAspectRatio; - -@property (readwrite, nonatomic) CGFloat aspectRatio; - -@end - -@implementation GPUImageGaussianBlurPositionFilter - -@synthesize blurSize = _blurSize; -@synthesize blurCenter = _blurCenter; -@synthesize aspectRatio = _aspectRatio; - -- (id) initWithFirstStageVertexShaderFromString:(NSString *)firstStageVertexShaderString - firstStageFragmentShaderFromString:(NSString *)firstStageFragmentShaderString - secondStageVertexShaderFromString:(NSString *)secondStageVertexShaderString - secondStageFragmentShaderFromString:(NSString *)secondStageFragmentShaderString { - - if (!(self = [super initWithFirstStageVertexShaderFromString:firstStageVertexShaderString ? firstStageVertexShaderString : kGPUImageGaussianBlurPositionVertexShaderString - firstStageFragmentShaderFromString:firstStageFragmentShaderString ? firstStageFragmentShaderString : kGPUImageGaussianBlurPositionFragmentShaderString - secondStageVertexShaderFromString:secondStageVertexShaderString ? secondStageVertexShaderString : kGPUImageGaussianBlurPositionVertexShaderString - secondStageFragmentShaderFromString:secondStageFragmentShaderString ? secondStageFragmentShaderString : kGPUImageGaussianBlurPositionFragmentShaderString])) { - return nil; - } - - aspectRatioUniform = [secondFilterProgram uniformIndex:@"aspectRatio"]; - blurCenterUniform = [secondFilterProgram uniformIndex:@"blurCenter"]; - blurRadiusUniform = [secondFilterProgram uniformIndex:@"blurRadius"]; - - self.blurSize = 1.0; - self.blurRadius = 1.0; - self.blurCenter = CGPointMake(0.5, 0.5); - - return self; -} - -- (id)init; -{ - return [self initWithFirstStageVertexShaderFromString:nil - firstStageFragmentShaderFromString:nil - secondStageVertexShaderFromString:nil - secondStageFragmentShaderFromString:nil]; -} - -- (void)adjustAspectRatio; -{ - if (GPUImageRotationSwapsWidthAndHeight(inputRotation)) - { - [self setAspectRatio:(inputTextureSize.width / inputTextureSize.height)]; - } - else - { - [self setAspectRatio:(inputTextureSize.height / inputTextureSize.width)]; - } -} - -- (void)forceProcessingAtSize:(CGSize)frameSize; -{ - [super forceProcessingAtSize:frameSize]; - [self adjustAspectRatio]; -} - -- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex; -{ - CGSize oldInputSize = inputTextureSize; - [super setInputSize:newSize atIndex:textureIndex]; - - if ( (!CGSizeEqualToSize(oldInputSize, inputTextureSize)) && (!CGSizeEqualToSize(newSize, CGSizeZero)) ) - { - [self adjustAspectRatio]; - } -} - -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -{ - [super setInputRotation:newInputRotation atIndex:textureIndex]; - [self setBlurCenter:self.blurCenter]; - [self adjustAspectRatio]; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setBlurSize:(CGFloat)newValue; -{ - _blurSize = newValue; - - _verticalTexelSpacing = _blurSize; - _horizontalTexelSpacing = _blurSize; - - [self setupFilterForSize:[self sizeOfFBO]]; -} - -- (void) setBlurCenter:(CGPoint)blurCenter; -{ - _blurCenter = blurCenter; - CGPoint rotatedPoint = [self rotatedPoint:blurCenter forRotation:inputRotation]; - [self setPoint:rotatedPoint forUniform:blurCenterUniform program:secondFilterProgram]; -} - -- (void) setBlurRadius:(CGFloat)blurRadius; -{ - _blurRadius = blurRadius; - - [self setFloat:_blurRadius forUniform:blurRadiusUniform program:secondFilterProgram]; -} - -- (void) setAspectRatio:(CGFloat)newValue; -{ - _aspectRatio = newValue; - - [self setFloat:_aspectRatio forUniform:aspectRatioUniform program:secondFilterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianSelectiveBlurFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianSelectiveBlurFilter.h deleted file mode 100755 index 02324566..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianSelectiveBlurFilter.h +++ /dev/null @@ -1,30 +0,0 @@ -#import "GPUImageFilterGroup.h" - -@class GPUImageGaussianBlurFilter; - -/** A Gaussian blur that preserves focus within a circular region - */ -@interface GPUImageGaussianSelectiveBlurFilter : GPUImageFilterGroup -{ - GPUImageGaussianBlurFilter *blurFilter; - GPUImageFilter *selectiveFocusFilter; - BOOL hasOverriddenAspectRatio; -} - -/** The radius of the circular area being excluded from the blur - */ -@property (readwrite, nonatomic) CGFloat excludeCircleRadius; -/** The center of the circular area being excluded from the blur - */ -@property (readwrite, nonatomic) CGPoint excludeCirclePoint; -/** The size of the area between the blurred portion and the clear circle - */ -@property (readwrite, nonatomic) CGFloat excludeBlurSize; -/** A radius in pixels to use for the blur, with a default of 5.0. This adjusts the sigma variable in the Gaussian distribution function. - */ -@property (readwrite, nonatomic) CGFloat blurRadiusInPixels; -/** The aspect ratio of the image, used to adjust the circularity of the in-focus region. By default, this matches the image aspect ratio, but you can override this value. - */ -@property (readwrite, nonatomic) CGFloat aspectRatio; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianSelectiveBlurFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianSelectiveBlurFilter.m deleted file mode 100755 index 7ebc9e19..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGaussianSelectiveBlurFilter.m +++ /dev/null @@ -1,147 +0,0 @@ -#import "GPUImageGaussianSelectiveBlurFilter.h" -#import "GPUImageGaussianBlurFilter.h" -#import "GPUImageTwoInputFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageGaussianSelectiveBlurFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - uniform lowp float excludeCircleRadius; - uniform lowp vec2 excludeCirclePoint; - uniform lowp float excludeBlurSize; - uniform highp float aspectRatio; - - void main() - { - lowp vec4 sharpImageColor = texture2D(inputImageTexture, textureCoordinate); - lowp vec4 blurredImageColor = texture2D(inputImageTexture2, textureCoordinate2); - - highp vec2 textureCoordinateToUse = vec2(textureCoordinate2.x, (textureCoordinate2.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); - highp float distanceFromCenter = distance(excludeCirclePoint, textureCoordinateToUse); - - gl_FragColor = mix(sharpImageColor, blurredImageColor, smoothstep(excludeCircleRadius - excludeBlurSize, excludeCircleRadius, distanceFromCenter)); - } -); -#else -NSString *const kGPUImageGaussianSelectiveBlurFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - uniform float excludeCircleRadius; - uniform vec2 excludeCirclePoint; - uniform float excludeBlurSize; - uniform float aspectRatio; - - void main() - { - vec4 sharpImageColor = texture2D(inputImageTexture, textureCoordinate); - vec4 blurredImageColor = texture2D(inputImageTexture2, textureCoordinate2); - - vec2 textureCoordinateToUse = vec2(textureCoordinate2.x, (textureCoordinate2.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); - float distanceFromCenter = distance(excludeCirclePoint, textureCoordinateToUse); - - gl_FragColor = mix(sharpImageColor, blurredImageColor, smoothstep(excludeCircleRadius - excludeBlurSize, excludeCircleRadius, distanceFromCenter)); - } -); -#endif - -@implementation GPUImageGaussianSelectiveBlurFilter - -@synthesize excludeCirclePoint = _excludeCirclePoint, excludeCircleRadius = _excludeCircleRadius, excludeBlurSize = _excludeBlurSize; -@synthesize blurRadiusInPixels = _blurRadiusInPixels; -@synthesize aspectRatio = _aspectRatio; - -- (id)init; -{ - if (!(self = [super init])) - { - return nil; - } - - hasOverriddenAspectRatio = NO; - - // First pass: apply a variable Gaussian blur - blurFilter = [[GPUImageGaussianBlurFilter alloc] init]; - [self addFilter:blurFilter]; - - // Second pass: combine the blurred image with the original sharp one - selectiveFocusFilter = [[GPUImageTwoInputFilter alloc] initWithFragmentShaderFromString:kGPUImageGaussianSelectiveBlurFragmentShaderString]; - [self addFilter:selectiveFocusFilter]; - - // Texture location 0 needs to be the sharp image for both the blur and the second stage processing - [blurFilter addTarget:selectiveFocusFilter atTextureLocation:1]; - - // To prevent double updating of this filter, disable updates from the sharp image side - self.initialFilters = [NSArray arrayWithObjects:blurFilter, selectiveFocusFilter, nil]; - self.terminalFilter = selectiveFocusFilter; - - self.blurRadiusInPixels = 5.0; - - self.excludeCircleRadius = 60.0/320.0; - self.excludeCirclePoint = CGPointMake(0.5f, 0.5f); - self.excludeBlurSize = 30.0/320.0; - - return self; -} - -- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex; -{ - CGSize oldInputSize = inputTextureSize; - [super setInputSize:newSize atIndex:textureIndex]; - inputTextureSize = newSize; - - if ( (!CGSizeEqualToSize(oldInputSize, inputTextureSize)) && (!hasOverriddenAspectRatio) && (!CGSizeEqualToSize(newSize, CGSizeZero)) ) - { - _aspectRatio = (inputTextureSize.width / inputTextureSize.height); - [selectiveFocusFilter setFloat:_aspectRatio forUniformName:@"aspectRatio"]; - } -} - -#pragma mark - -#pragma mark Accessors - -- (void)setBlurRadiusInPixels:(CGFloat)newValue; -{ - blurFilter.blurRadiusInPixels = newValue; -} - -- (CGFloat)blurRadiusInPixels; -{ - return blurFilter.blurRadiusInPixels; -} - -- (void)setExcludeCirclePoint:(CGPoint)newValue; -{ - _excludeCirclePoint = newValue; - [selectiveFocusFilter setPoint:newValue forUniformName:@"excludeCirclePoint"]; -} - -- (void)setExcludeCircleRadius:(CGFloat)newValue; -{ - _excludeCircleRadius = newValue; - [selectiveFocusFilter setFloat:newValue forUniformName:@"excludeCircleRadius"]; -} - -- (void)setExcludeBlurSize:(CGFloat)newValue; -{ - _excludeBlurSize = newValue; - [selectiveFocusFilter setFloat:newValue forUniformName:@"excludeBlurSize"]; -} - -- (void)setAspectRatio:(CGFloat)newValue; -{ - hasOverriddenAspectRatio = YES; - _aspectRatio = newValue; - [selectiveFocusFilter setFloat:_aspectRatio forUniformName:@"aspectRatio"]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGlassSphereFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGlassSphereFilter.h deleted file mode 100644 index 809a4ee8..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGlassSphereFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImageSphereRefractionFilter.h" - -@interface GPUImageGlassSphereFilter : GPUImageSphereRefractionFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGlassSphereFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGlassSphereFilter.m deleted file mode 100644 index 18662916..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGlassSphereFilter.m +++ /dev/null @@ -1,106 +0,0 @@ -#import "GPUImageGlassSphereFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageGlassSphereFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform highp vec2 center; - uniform highp float radius; - uniform highp float aspectRatio; - uniform highp float refractiveIndex; -// uniform vec3 lightPosition; - const highp vec3 lightPosition = vec3(-0.5, 0.5, 1.0); - const highp vec3 ambientLightPosition = vec3(0.0, 0.0, 1.0); - - void main() - { - highp vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); - highp float distanceFromCenter = distance(center, textureCoordinateToUse); - lowp float checkForPresenceWithinSphere = step(distanceFromCenter, radius); - - distanceFromCenter = distanceFromCenter / radius; - - highp float normalizedDepth = radius * sqrt(1.0 - distanceFromCenter * distanceFromCenter); - highp vec3 sphereNormal = normalize(vec3(textureCoordinateToUse - center, normalizedDepth)); - - highp vec3 refractedVector = 2.0 * refract(vec3(0.0, 0.0, -1.0), sphereNormal, refractiveIndex); - refractedVector.xy = -refractedVector.xy; - - highp vec3 finalSphereColor = texture2D(inputImageTexture, (refractedVector.xy + 1.0) * 0.5).rgb; - - // Grazing angle lighting - highp float lightingIntensity = 2.5 * (1.0 - pow(clamp(dot(ambientLightPosition, sphereNormal), 0.0, 1.0), 0.25)); - finalSphereColor += lightingIntensity; - - // Specular lighting - lightingIntensity = clamp(dot(normalize(lightPosition), sphereNormal), 0.0, 1.0); - lightingIntensity = pow(lightingIntensity, 15.0); - finalSphereColor += vec3(0.8, 0.8, 0.8) * lightingIntensity; - - gl_FragColor = vec4(finalSphereColor, 1.0) * checkForPresenceWithinSphere; - } -); -#else -NSString *const kGPUImageGlassSphereFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform vec2 center; - uniform float radius; - uniform float aspectRatio; - uniform float refractiveIndex; - // uniform vec3 lightPosition; - const vec3 lightPosition = vec3(-0.5, 0.5, 1.0); - const vec3 ambientLightPosition = vec3(0.0, 0.0, 1.0); - - void main() - { - vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); - float distanceFromCenter = distance(center, textureCoordinateToUse); - float checkForPresenceWithinSphere = step(distanceFromCenter, radius); - - distanceFromCenter = distanceFromCenter / radius; - - float normalizedDepth = radius * sqrt(1.0 - distanceFromCenter * distanceFromCenter); - vec3 sphereNormal = normalize(vec3(textureCoordinateToUse - center, normalizedDepth)); - - vec3 refractedVector = 2.0 * refract(vec3(0.0, 0.0, -1.0), sphereNormal, refractiveIndex); - refractedVector.xy = -refractedVector.xy; - - vec3 finalSphereColor = texture2D(inputImageTexture, (refractedVector.xy + 1.0) * 0.5).rgb; - - // Grazing angle lighting - float lightingIntensity = 2.5 * (1.0 - pow(clamp(dot(ambientLightPosition, sphereNormal), 0.0, 1.0), 0.25)); - finalSphereColor += lightingIntensity; - - // Specular lighting - lightingIntensity = clamp(dot(normalize(lightPosition), sphereNormal), 0.0, 1.0); - lightingIntensity = pow(lightingIntensity, 15.0); - finalSphereColor += vec3(0.8, 0.8, 0.8) * lightingIntensity; - - gl_FragColor = vec4(finalSphereColor, 1.0) * checkForPresenceWithinSphere; - } -); -#endif - -@implementation GPUImageGlassSphereFilter - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageGlassSphereFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGrayscaleFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGrayscaleFilter.h deleted file mode 100755 index 2d97f8c3..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGrayscaleFilter.h +++ /dev/null @@ -1,9 +0,0 @@ -#import "GPUImageFilter.h" - -extern NSString *const kGPUImageLuminanceFragmentShaderString; - -/** Converts an image to grayscale (a slightly faster implementation of the saturation filter, without the ability to vary the color contribution) - */ -@interface GPUImageGrayscaleFilter : GPUImageFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGrayscaleFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGrayscaleFilter.m deleted file mode 100755 index 0066ca87..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageGrayscaleFilter.m +++ /dev/null @@ -1,141 +0,0 @@ -#import "GPUImageGrayscaleFilter.h" - -@implementation GPUImageGrayscaleFilter - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageLuminanceFragmentShaderString = SHADER_STRING -( - precision highp float; - - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - const highp vec3 W = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - float luminance = dot(textureColor.rgb, W); - - gl_FragColor = vec4(vec3(luminance), textureColor.a); - } -); -#else -NSString *const kGPUImageLuminanceFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - const vec3 W = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - float luminance = dot(textureColor.rgb, W); - - gl_FragColor = vec4(vec3(luminance), textureColor.a); - } -); -#endif - - -- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates; -{ - if (!currentlyReceivingMonochromeInput) - { - [super renderToTextureWithVertices:vertices textureCoordinates:textureCoordinates]; - } -} - -//- (void)setInputTexture:(GLuint)newInputTexture atIndex:(NSInteger)textureIndex; -//{ -// [super setInputTexture:newInputTexture atIndex:textureIndex]; -// if (currentlyReceivingMonochromeInput) -// { -// [self notifyTargetsAboutNewOutputTexture]; -// } -//} - -//- (GLuint)textureForOutput; -//{ -// if (currentlyReceivingMonochromeInput) -// { -// return filterSourceTexture; -// } -// else -// { -// return outputTexture; -// } -//} - -- (BOOL)wantsMonochromeInput; -{ -// return YES; - return NO; -} - -- (BOOL)providesMonochromeOutput; -{ -// return YES; - return NO; -} - -// TODO: Rewrite this based on the new GPUImageFilter implementation -//- (void)informTargetsAboutNewFrameAtTime:(CMTime)frameTime; -//{ -// if (self.frameProcessingCompletionBlock != NULL) -// { -// self.frameProcessingCompletionBlock(self, frameTime); -// } -// -// for (id currentTarget in targets) -// { -// if (currentTarget != self.targetToIgnoreForUpdates) -// { -// NSInteger indexOfObject = [targets indexOfObject:currentTarget]; -// NSInteger textureIndex = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; -// -// if ([GPUImageContext supportsFastTextureUpload] && preparedToCaptureImage) -// { -// [self setInputTextureForTarget:currentTarget atIndex:textureIndex]; -// } -// -// if (currentlyReceivingMonochromeInput) -// { -// [currentTarget setInputRotation:inputRotation atIndex:textureIndex]; -// -// CGSize sizeToRotate = [self outputFrameSize]; -// CGSize rotatedSize = sizeToRotate; -// if (GPUImageRotationSwapsWidthAndHeight(inputRotation)) -// { -// rotatedSize.width = sizeToRotate.height; -// rotatedSize.height = sizeToRotate.width; -// } -// [currentTarget setInputSize:rotatedSize atIndex:textureIndex]; -// } -// else -// { -// [currentTarget setInputSize:[self outputFrameSize] atIndex:textureIndex]; -// } -// [currentTarget newFrameReadyAtTime:frameTime atIndex:textureIndex]; -// } -// } -//} - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageLuminanceFragmentShaderString])) - { - return nil; - } - - return self; -} - - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHSBFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHSBFilter.h deleted file mode 100644 index 65a9e1de..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHSBFilter.h +++ /dev/null @@ -1,27 +0,0 @@ -#import "GPUImageColorMatrixFilter.h" - -@interface GPUImageHSBFilter : GPUImageColorMatrixFilter - -/** Reset the filter to have no transformations. - */ -- (void)reset; - -/** Add a hue rotation to the filter. - The hue rotation is in the range [-360, 360] with 0 being no-change. - Note that this adjustment is additive, so use the reset method if you need to. - */ -- (void)rotateHue:(float)h; - -/** Add a saturation adjustment to the filter. - The saturation adjustment is in the range [0.0, 2.0] with 1.0 being no-change. - Note that this adjustment is additive, so use the reset method if you need to. - */ -- (void)adjustSaturation:(float)s; - -/** Add a brightness adjustment to the filter. - The brightness adjustment is in the range [0.0, 2.0] with 1.0 being no-change. - Note that this adjustment is additive, so use the reset method if you need to. - */ -- (void)adjustBrightness:(float)b; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHSBFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHSBFilter.m deleted file mode 100644 index eb668f7d..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHSBFilter.m +++ /dev/null @@ -1,414 +0,0 @@ -#import "GPUImageHSBFilter.h" - -@implementation GPUImageHSBFilter { - float matrix[4][4]; -} - -- (id)init -{ - self = [super init]; - if (self) { - [self reset]; - } - return self; -} - -- (void)reset { - identmat(matrix); - [self _updateColorMatrix]; -} - -- (void)rotateHue:(float)h { - huerotatemat(matrix, h); - [self _updateColorMatrix]; -} - -- (void)adjustSaturation:(float)s { - saturatemat(matrix, s); - [self _updateColorMatrix]; -} - -- (void)adjustBrightness:(float)b { - cscalemat(matrix, b, b, b); - [self _updateColorMatrix]; -} - -- (void)_updateColorMatrix { - GPUMatrix4x4 gpuMatrix; - gpuMatrix.one.one = matrix[0][0]; - gpuMatrix.one.two = matrix[1][0]; - gpuMatrix.one.three = matrix[2][0]; - gpuMatrix.one.four = matrix[3][0]; - gpuMatrix.two.one = matrix[0][1]; - gpuMatrix.two.two = matrix[1][1]; - gpuMatrix.two.three = matrix[2][1]; - gpuMatrix.two.four = matrix[3][1]; - gpuMatrix.three.one = matrix[0][2]; - gpuMatrix.three.two = matrix[1][2]; - gpuMatrix.three.three = matrix[2][2]; - gpuMatrix.three.four = matrix[3][2]; - gpuMatrix.four.one = matrix[0][3]; - gpuMatrix.four.two = matrix[1][3]; - gpuMatrix.four.three = matrix[2][3]; - gpuMatrix.four.four = matrix[3][3]; - self.colorMatrix = gpuMatrix; -} - -#pragma mark - Matrix algorithms - -/* Matrix algorithms adapted from http://www.graficaobscura.com/matrix/index.html - - Note about luminance vector values below from that page: - Where rwgt is 0.3086, gwgt is 0.6094, and bwgt is 0.0820. This is the luminance vector. Notice here that we do not use the standard NTSC weights of 0.299, 0.587, and 0.114. The NTSC weights are only applicable to RGB colors in a gamma 2.2 color space. For linear RGB colors the values above are better. - */ -//#define RLUM (0.3086f) -//#define GLUM (0.6094f) -//#define BLUM (0.0820f) - -/* This is the vector value from the PDF specification, and may be closer to what Photoshop uses */ -#define RLUM (0.3f) -#define GLUM (0.59f) -#define BLUM (0.11f) - -/* - * matrixmult - - * multiply two matricies - */ -static void matrixmult(a,b,c) -float a[4][4], b[4][4], c[4][4]; -{ - int x, y; - float temp[4][4]; - - for(y=0; y<4 ; y++) - for(x=0 ; x<4 ; x++) { - temp[y][x] = b[y][0] * a[0][x] - + b[y][1] * a[1][x] - + b[y][2] * a[2][x] - + b[y][3] * a[3][x]; - } - for(y=0; y<4; y++) - for(x=0; x<4; x++) - c[y][x] = temp[y][x]; -} - -/* - * identmat - - * make an identity matrix - */ -static void identmat(matrix) -float matrix[4][4]; -{ - memset(matrix, 0, sizeof(float[4][4])); - matrix[0][0] = 1.0f; - matrix[1][1] = 1.0f; - matrix[2][2] = 1.0f; - matrix[3][3] = 1.0f; -} - -/* - * xformpnt - - * transform a 3D point using a matrix - */ -static void xformpnt(matrix,x,y,z,tx,ty,tz) -float matrix[4][4]; -float x,y,z; -float *tx,*ty,*tz; -{ - *tx = x*matrix[0][0] + y*matrix[1][0] + z*matrix[2][0] + matrix[3][0]; - *ty = x*matrix[0][1] + y*matrix[1][1] + z*matrix[2][1] + matrix[3][1]; - *tz = x*matrix[0][2] + y*matrix[1][2] + z*matrix[2][2] + matrix[3][2]; -} - -/* - * cscalemat - - * make a color scale marix - */ -static void cscalemat(mat,rscale,gscale,bscale) -float mat[4][4]; -float rscale, gscale, bscale; -{ - float mmat[4][4]; - - mmat[0][0] = rscale; - mmat[0][1] = 0.0; - mmat[0][2] = 0.0; - mmat[0][3] = 0.0; - - mmat[1][0] = 0.0; - mmat[1][1] = gscale; - mmat[1][2] = 0.0; - mmat[1][3] = 0.0; - - - mmat[2][0] = 0.0; - mmat[2][1] = 0.0; - mmat[2][2] = bscale; - mmat[2][3] = 0.0; - - mmat[3][0] = 0.0; - mmat[3][1] = 0.0; - mmat[3][2] = 0.0; - mmat[3][3] = 1.0; - matrixmult(mmat,mat,mat); -} - -/* - * saturatemat - - * make a saturation marix - */ -static void saturatemat(mat,sat) -float mat[4][4]; -float sat; -{ - float mmat[4][4]; - float a, b, c, d, e, f, g, h, i; - float rwgt, gwgt, bwgt; - - rwgt = RLUM; - gwgt = GLUM; - bwgt = BLUM; - - a = (1.0-sat)*rwgt + sat; - b = (1.0-sat)*rwgt; - c = (1.0-sat)*rwgt; - d = (1.0-sat)*gwgt; - e = (1.0-sat)*gwgt + sat; - f = (1.0-sat)*gwgt; - g = (1.0-sat)*bwgt; - h = (1.0-sat)*bwgt; - i = (1.0-sat)*bwgt + sat; - mmat[0][0] = a; - mmat[0][1] = b; - mmat[0][2] = c; - mmat[0][3] = 0.0; - - mmat[1][0] = d; - mmat[1][1] = e; - mmat[1][2] = f; - mmat[1][3] = 0.0; - - mmat[2][0] = g; - mmat[2][1] = h; - mmat[2][2] = i; - mmat[2][3] = 0.0; - - mmat[3][0] = 0.0; - mmat[3][1] = 0.0; - mmat[3][2] = 0.0; - mmat[3][3] = 1.0; - matrixmult(mmat,mat,mat); -} - -/* - * xrotate - - * rotate about the x (red) axis - */ -static void xrotatemat(mat,rs,rc) -float mat[4][4]; -float rs, rc; -{ - float mmat[4][4]; - - mmat[0][0] = 1.0; - mmat[0][1] = 0.0; - mmat[0][2] = 0.0; - mmat[0][3] = 0.0; - - mmat[1][0] = 0.0; - mmat[1][1] = rc; - mmat[1][2] = rs; - mmat[1][3] = 0.0; - - mmat[2][0] = 0.0; - mmat[2][1] = -rs; - mmat[2][2] = rc; - mmat[2][3] = 0.0; - - mmat[3][0] = 0.0; - mmat[3][1] = 0.0; - mmat[3][2] = 0.0; - mmat[3][3] = 1.0; - matrixmult(mmat,mat,mat); -} - -/* - * yrotate - - * rotate about the y (green) axis - */ -static void yrotatemat(mat,rs,rc) -float mat[4][4]; -float rs, rc; -{ - float mmat[4][4]; - - mmat[0][0] = rc; - mmat[0][1] = 0.0; - mmat[0][2] = -rs; - mmat[0][3] = 0.0; - - mmat[1][0] = 0.0; - mmat[1][1] = 1.0; - mmat[1][2] = 0.0; - mmat[1][3] = 0.0; - - mmat[2][0] = rs; - mmat[2][1] = 0.0; - mmat[2][2] = rc; - mmat[2][3] = 0.0; - - mmat[3][0] = 0.0; - mmat[3][1] = 0.0; - mmat[3][2] = 0.0; - mmat[3][3] = 1.0; - matrixmult(mmat,mat,mat); -} - -/* - * zrotate - - * rotate about the z (blue) axis - */ -static void zrotatemat(mat,rs,rc) -float mat[4][4]; -float rs, rc; -{ - float mmat[4][4]; - - mmat[0][0] = rc; - mmat[0][1] = rs; - mmat[0][2] = 0.0; - mmat[0][3] = 0.0; - - mmat[1][0] = -rs; - mmat[1][1] = rc; - mmat[1][2] = 0.0; - mmat[1][3] = 0.0; - - mmat[2][0] = 0.0; - mmat[2][1] = 0.0; - mmat[2][2] = 1.0; - mmat[2][3] = 0.0; - - mmat[3][0] = 0.0; - mmat[3][1] = 0.0; - mmat[3][2] = 0.0; - mmat[3][3] = 1.0; - matrixmult(mmat,mat,mat); -} - -/* - * zshear - - * shear z using x and y. - */ -static void zshearmat(mat,dx,dy) -float mat[4][4]; -float dx, dy; -{ - float mmat[4][4]; - - mmat[0][0] = 1.0; - mmat[0][1] = 0.0; - mmat[0][2] = dx; - mmat[0][3] = 0.0; - - mmat[1][0] = 0.0; - mmat[1][1] = 1.0; - mmat[1][2] = dy; - mmat[1][3] = 0.0; - - mmat[2][0] = 0.0; - mmat[2][1] = 0.0; - mmat[2][2] = 1.0; - mmat[2][3] = 0.0; - - mmat[3][0] = 0.0; - mmat[3][1] = 0.0; - mmat[3][2] = 0.0; - mmat[3][3] = 1.0; - matrixmult(mmat,mat,mat); -} - -/* - * simplehuerotatemat - - * simple hue rotation. This changes luminance - */ -//static void simplehuerotatemat(mat,rot) -//float mat[4][4]; -//float rot; -//{ -// float mag; -// float xrs, xrc; -// float yrs, yrc; -// float zrs, zrc; -// -// /* rotate the grey vector into positive Z */ -// mag = sqrt(2.0); -// xrs = 1.0/mag; -// xrc = 1.0/mag; -// xrotatemat(mat,xrs,xrc); -// -// mag = sqrt(3.0); -// yrs = -1.0/mag; -// yrc = sqrt(2.0)/mag; -// yrotatemat(mat,yrs,yrc); -// -// /* rotate the hue */ -// zrs = sin(rot*M_PI/180.0); -// zrc = cos(rot*M_PI/180.0); -// zrotatemat(mat,zrs,zrc); -// -// /* rotate the grey vector back into place */ -// yrotatemat(mat,-yrs,yrc); -// xrotatemat(mat,-xrs,xrc); -//} - -/* - * huerotatemat - - * rotate the hue, while maintaining luminance. - */ -static void huerotatemat(mat,rot) -float mat[4][4]; -float rot; -{ - float mmat[4][4]; - float mag; - float lx, ly, lz; - float xrs, xrc; - float yrs, yrc; - float zrs, zrc; - float zsx, zsy; - - identmat(mmat); - - /* rotate the grey vector into positive Z */ - mag = sqrt(2.0); - xrs = 1.0/mag; - xrc = 1.0/mag; - xrotatemat(mmat,xrs,xrc); - mag = sqrt(3.0); - yrs = -1.0/mag; - yrc = sqrt(2.0)/mag; - yrotatemat(mmat,yrs,yrc); - - /* shear the space to make the luminance plane horizontal */ - xformpnt(mmat,RLUM,GLUM,BLUM,&lx,&ly,&lz); - zsx = lx/lz; - zsy = ly/lz; - zshearmat(mmat,zsx,zsy); - - /* rotate the hue */ - zrs = sin(rot*M_PI/180.0); - zrc = cos(rot*M_PI/180.0); - zrotatemat(mmat,zrs,zrc); - - /* unshear the space to put the luminance plane back */ - zshearmat(mmat,-zsx,-zsy); - - /* rotate the grey vector back into place */ - yrotatemat(mmat,-yrs,yrc); - xrotatemat(mmat,-xrs,xrc); - - matrixmult(mmat,mat,mat); -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHalftoneFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHalftoneFilter.h deleted file mode 100644 index 1860bc97..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHalftoneFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImagePixellateFilter.h" - -@interface GPUImageHalftoneFilter : GPUImagePixellateFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHalftoneFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHalftoneFilter.m deleted file mode 100644 index 1b621c6a..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHalftoneFilter.m +++ /dev/null @@ -1,79 +0,0 @@ -#import "GPUImageHalftoneFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageHalftoneFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform highp float fractionalWidthOfPixel; - uniform highp float aspectRatio; - uniform highp float dotScaling; - - const highp vec3 W = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - highp vec2 sampleDivisor = vec2(fractionalWidthOfPixel, fractionalWidthOfPixel / aspectRatio); - - highp vec2 samplePos = textureCoordinate - mod(textureCoordinate, sampleDivisor) + 0.5 * sampleDivisor; - highp vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); - highp vec2 adjustedSamplePos = vec2(samplePos.x, (samplePos.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); - highp float distanceFromSamplePoint = distance(adjustedSamplePos, textureCoordinateToUse); - - lowp vec3 sampledColor = texture2D(inputImageTexture, samplePos ).rgb; - highp float dotScaling = 1.0 - dot(sampledColor, W); - - lowp float checkForPresenceWithinDot = 1.0 - step(distanceFromSamplePoint, (fractionalWidthOfPixel * 0.5) * dotScaling); - - gl_FragColor = vec4(vec3(checkForPresenceWithinDot), 1.0); - } -); -#else -NSString *const kGPUImageHalftoneFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform float fractionalWidthOfPixel; - uniform float aspectRatio; - uniform float dotScaling; - - const vec3 W = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - vec2 sampleDivisor = vec2(fractionalWidthOfPixel, fractionalWidthOfPixel / aspectRatio); - - vec2 samplePos = textureCoordinate - mod(textureCoordinate, sampleDivisor) + 0.5 * sampleDivisor; - vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); - vec2 adjustedSamplePos = vec2(samplePos.x, (samplePos.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); - float distanceFromSamplePoint = distance(adjustedSamplePos, textureCoordinateToUse); - - vec3 sampledColor = texture2D(inputImageTexture, samplePos ).rgb; - float dotScaling = 1.0 - dot(sampledColor, W); - - float checkForPresenceWithinDot = 1.0 - step(distanceFromSamplePoint, (fractionalWidthOfPixel * 0.5) * dotScaling); - - gl_FragColor = vec4(vec3(checkForPresenceWithinDot), 1.0); - } -); -#endif - -@implementation GPUImageHalftoneFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageHalftoneFragmentShaderString])) - { - return nil; - } - - self.fractionalWidthOfAPixel = 0.01; - - return self; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHardLightBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHardLightBlendFilter.h deleted file mode 100755 index 47d62609..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHardLightBlendFilter.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageHardLightBlendFilter : GPUImageTwoInputFilter -{ -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHardLightBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHardLightBlendFilter.m deleted file mode 100755 index 2896ce82..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHardLightBlendFilter.m +++ /dev/null @@ -1,99 +0,0 @@ -#import "GPUImageHardLightBlendFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageHardLightBlendFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - const highp vec3 W = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - mediump vec4 base = texture2D(inputImageTexture, textureCoordinate); - mediump vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2); - - highp float ra; - if (2.0 * overlay.r < overlay.a) { - ra = 2.0 * overlay.r * base.r + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a); - } else { - ra = overlay.a * base.a - 2.0 * (base.a - base.r) * (overlay.a - overlay.r) + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a); - } - - highp float ga; - if (2.0 * overlay.g < overlay.a) { - ga = 2.0 * overlay.g * base.g + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a); - } else { - ga = overlay.a * base.a - 2.0 * (base.a - base.g) * (overlay.a - overlay.g) + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a); - } - - highp float ba; - if (2.0 * overlay.b < overlay.a) { - ba = 2.0 * overlay.b * base.b + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a); - } else { - ba = overlay.a * base.a - 2.0 * (base.a - base.b) * (overlay.a - overlay.b) + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a); - } - - gl_FragColor = vec4(ra, ga, ba, 1.0); - } -); -#else -NSString *const kGPUImageHardLightBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - const vec3 W = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - vec4 base = texture2D(inputImageTexture, textureCoordinate); - vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2); - - float ra; - if (2.0 * overlay.r < overlay.a) { - ra = 2.0 * overlay.r * base.r + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a); - } else { - ra = overlay.a * base.a - 2.0 * (base.a - base.r) * (overlay.a - overlay.r) + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a); - } - - float ga; - if (2.0 * overlay.g < overlay.a) { - ga = 2.0 * overlay.g * base.g + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a); - } else { - ga = overlay.a * base.a - 2.0 * (base.a - base.g) * (overlay.a - overlay.g) + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a); - } - - float ba; - if (2.0 * overlay.b < overlay.a) { - ba = 2.0 * overlay.b * base.b + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a); - } else { - ba = overlay.a * base.a - 2.0 * (base.a - base.b) * (overlay.a - overlay.b) + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a); - } - - gl_FragColor = vec4(ra, ga, ba, 1.0); - } -); -#endif - - -@implementation GPUImageHardLightBlendFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageHardLightBlendFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHarrisCornerDetectionFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHarrisCornerDetectionFilter.h deleted file mode 100755 index 1492b8b8..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHarrisCornerDetectionFilter.h +++ /dev/null @@ -1,53 +0,0 @@ -#import "GPUImageFilterGroup.h" - -@class GPUImageGaussianBlurFilter; -@class GPUImageXYDerivativeFilter; -@class GPUImageGrayscaleFilter; -@class GPUImageGaussianBlurFilter; -@class GPUImageThresholdedNonMaximumSuppressionFilter; -@class GPUImageColorPackingFilter; - -//#define DEBUGFEATUREDETECTION - -/** Harris corner detector - - First pass: reduce to luminance and take the derivative of the luminance texture (GPUImageXYDerivativeFilter) - - Second pass: blur the derivative (GPUImageGaussianBlurFilter) - - Third pass: apply the Harris corner detection calculation - - This is the Harris corner detector, as described in - C. Harris and M. Stephens. A Combined Corner and Edge Detector. Proc. Alvey Vision Conf., Univ. Manchester, pp. 147-151, 1988. - */ -@interface GPUImageHarrisCornerDetectionFilter : GPUImageFilterGroup -{ - GPUImageXYDerivativeFilter *derivativeFilter; - GPUImageGaussianBlurFilter *blurFilter; - GPUImageFilter *harrisCornerDetectionFilter; - GPUImageThresholdedNonMaximumSuppressionFilter *nonMaximumSuppressionFilter; - GPUImageColorPackingFilter *colorPackingFilter; - GLfloat *cornersArray; - GLubyte *rawImagePixels; -} - -/** The radius of the underlying Gaussian blur. The default is 2.0. - */ -@property(readwrite, nonatomic) CGFloat blurRadiusInPixels; - -// This changes the dynamic range of the Harris corner detector by amplifying small cornerness values. Default is 5.0. -@property(readwrite, nonatomic) CGFloat sensitivity; - -// A threshold value at which a point is recognized as being a corner after the non-maximum suppression. Default is 0.20. -@property(readwrite, nonatomic) CGFloat threshold; - -// This block is called on the detection of new corner points, usually on every processed frame. A C array containing normalized coordinates in X, Y pairs is passed in, along with a count of the number of corners detected and the current timestamp of the video frame -@property(nonatomic, copy) void(^cornersDetectedBlock)(GLfloat* cornerArray, NSUInteger cornersDetected, CMTime frameTime); - -// These images are only enabled when built with DEBUGFEATUREDETECTION defined, and are used to examine the intermediate states of the feature detector -@property(nonatomic, readonly, strong) NSMutableArray *intermediateImages; - -// Initialization and teardown -- (id)initWithCornerDetectionFragmentShader:(NSString *)cornerDetectionFragmentShader; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHarrisCornerDetectionFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHarrisCornerDetectionFilter.m deleted file mode 100755 index 999748dd..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHarrisCornerDetectionFilter.m +++ /dev/null @@ -1,292 +0,0 @@ -#import "GPUImageHarrisCornerDetectionFilter.h" -#import "GPUImageGaussianBlurFilter.h" -#import "GPUImageXYDerivativeFilter.h" -#import "GPUImageGrayscaleFilter.h" -#import "GPUImageThresholdedNonMaximumSuppressionFilter.h" -#import "GPUImageColorPackingFilter.h" -#import "GPUImageGaussianBlurFilter.h" - -@interface GPUImageHarrisCornerDetectionFilter() - -- (void)extractCornerLocationsFromImageAtFrameTime:(CMTime)frameTime; - -@end - -// This is the Harris corner detector, as described in -// C. Harris and M. Stephens. A Combined Corner and Edge Detector. Proc. Alvey Vision Conf., Univ. Manchester, pp. 147-151, 1988. - -@implementation GPUImageHarrisCornerDetectionFilter - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageHarrisCornerDetectionFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform lowp float sensitivity; - - const mediump float harrisConstant = 0.04; - - void main() - { - mediump vec3 derivativeElements = texture2D(inputImageTexture, textureCoordinate).rgb; - - mediump float derivativeSum = derivativeElements.x + derivativeElements.y; - - mediump float zElement = (derivativeElements.z * 2.0) - 1.0; - - // R = Ix^2 * Iy^2 - Ixy * Ixy - k * (Ix^2 + Iy^2)^2 - mediump float cornerness = derivativeElements.x * derivativeElements.y - (zElement * zElement) - harrisConstant * derivativeSum * derivativeSum; - - gl_FragColor = vec4(vec3(cornerness * sensitivity), 1.0); - } -); -#else -NSString *const kGPUImageHarrisCornerDetectionFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float sensitivity; - - const float harrisConstant = 0.04; - - void main() - { - vec3 derivativeElements = texture2D(inputImageTexture, textureCoordinate).rgb; - - float derivativeSum = derivativeElements.x + derivativeElements.y; - - float zElement = (derivativeElements.z * 2.0) - 1.0; - - // R = Ix^2 * Iy^2 - Ixy * Ixy - k * (Ix^2 + Iy^2)^2 - float cornerness = derivativeElements.x * derivativeElements.y - (zElement * zElement) - harrisConstant * derivativeSum * derivativeSum; - - gl_FragColor = vec4(vec3(cornerness * sensitivity), 1.0); - } -); -#endif - -@synthesize blurRadiusInPixels; -@synthesize cornersDetectedBlock; -@synthesize sensitivity = _sensitivity; -@synthesize threshold = _threshold; -@synthesize intermediateImages = _intermediateImages; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [self initWithCornerDetectionFragmentShader:kGPUImageHarrisCornerDetectionFragmentShaderString])) - { - return nil; - } - - return self; -} - -- (id)initWithCornerDetectionFragmentShader:(NSString *)cornerDetectionFragmentShader; -{ - if (!(self = [super init])) - { - return nil; - } - -#ifdef DEBUGFEATUREDETECTION - _intermediateImages = [[NSMutableArray alloc] init]; -#endif - - // First pass: reduce to luminance and take the derivative of the luminance texture - derivativeFilter = [[GPUImageXYDerivativeFilter alloc] init]; - [self addFilter:derivativeFilter]; - -#ifdef DEBUGFEATUREDETECTION - __unsafe_unretained NSMutableArray *weakIntermediateImages = _intermediateImages; - __unsafe_unretained GPUImageFilter *weakFilter = derivativeFilter; - [derivativeFilter setFrameProcessingCompletionBlock:^(GPUImageOutput *filter, CMTime frameTime){ - UIImage *intermediateImage = [weakFilter imageFromCurrentlyProcessedOutput]; - [weakIntermediateImages addObject:intermediateImage]; - }]; -#endif - - // Second pass: blur the derivative - blurFilter = [[GPUImageGaussianBlurFilter alloc] init]; - [self addFilter:blurFilter]; - -#ifdef DEBUGFEATUREDETECTION - weakFilter = blurFilter; - [blurFilter setFrameProcessingCompletionBlock:^(GPUImageOutput *filter, CMTime frameTime){ - UIImage *intermediateImage = [weakFilter imageFromCurrentlyProcessedOutput]; - [weakIntermediateImages addObject:intermediateImage]; - }]; -#endif - - // Third pass: apply the Harris corner detection calculation - harrisCornerDetectionFilter = [[GPUImageFilter alloc] initWithFragmentShaderFromString:cornerDetectionFragmentShader]; - [self addFilter:harrisCornerDetectionFilter]; - -#ifdef DEBUGFEATUREDETECTION - weakFilter = harrisCornerDetectionFilter; - [harrisCornerDetectionFilter setFrameProcessingCompletionBlock:^(GPUImageOutput *filter, CMTime frameTime){ - UIImage *intermediateImage = [weakFilter imageFromCurrentlyProcessedOutput]; - [weakIntermediateImages addObject:intermediateImage]; - }]; -#endif - - // Fourth pass: apply non-maximum suppression and thresholding to find the local maxima - nonMaximumSuppressionFilter = [[GPUImageThresholdedNonMaximumSuppressionFilter alloc] init]; - [self addFilter:nonMaximumSuppressionFilter]; - - __unsafe_unretained GPUImageHarrisCornerDetectionFilter *weakSelf = self; -#ifdef DEBUGFEATUREDETECTION - weakFilter = nonMaximumSuppressionFilter; - [nonMaximumSuppressionFilter setFrameProcessingCompletionBlock:^(GPUImageOutput *filter, CMTime frameTime){ - UIImage *intermediateImage = [weakFilter imageFromCurrentlyProcessedOutput]; - [weakIntermediateImages addObject:intermediateImage]; - - [weakSelf extractCornerLocationsFromImageAtFrameTime:frameTime]; - }]; -#else - [nonMaximumSuppressionFilter setFrameProcessingCompletionBlock:^(GPUImageOutput *filter, CMTime frameTime) { - [weakSelf extractCornerLocationsFromImageAtFrameTime:frameTime]; - }]; -#endif - -// Sixth pass: compress the thresholded points into the RGBA channels -// colorPackingFilter = [[GPUImageColorPackingFilter alloc] init]; -// [self addFilter:colorPackingFilter]; -// -// -//#ifdef DEBUGFEATUREDETECTION -// __unsafe_unretained GPUImageHarrisCornerDetectionFilter *weakSelf = self; -// weakFilter = colorPackingFilter; -// [colorPackingFilter setFrameProcessingCompletionBlock:^(GPUImageOutput *filter, CMTime frameTime){ -// NSLog(@"Triggered response from compaction filter"); -// -// UIImage *intermediateImage = [weakFilter imageFromCurrentlyProcessedOutput]; -// [weakIntermediateImages addObject:intermediateImage]; -// -// [weakSelf extractCornerLocationsFromImageAtFrameTime:frameTime]; -// }]; -//#else -// __unsafe_unretained GPUImageHarrisCornerDetectionFilter *weakSelf = self; -// [colorPackingFilter setFrameProcessingCompletionBlock:^(GPUImageOutput *filter, CMTime frameTime) { -// [weakSelf extractCornerLocationsFromImageAtFrameTime:frameTime]; -// }]; -//#endif - - [derivativeFilter addTarget:blurFilter]; - [blurFilter addTarget:harrisCornerDetectionFilter]; - [harrisCornerDetectionFilter addTarget:nonMaximumSuppressionFilter]; -// [simpleThresholdFilter addTarget:colorPackingFilter]; - - self.initialFilters = [NSArray arrayWithObjects:derivativeFilter, nil]; -// self.terminalFilter = colorPackingFilter; - self.terminalFilter = nonMaximumSuppressionFilter; - - self.blurRadiusInPixels = 2.0; - self.sensitivity = 5.0; - self.threshold = 0.20; - - return self; -} - -- (void)dealloc; -{ - free(rawImagePixels); - free(cornersArray); -} - -#pragma mark - -#pragma mark Corner extraction - -- (void)extractCornerLocationsFromImageAtFrameTime:(CMTime)frameTime; -{ - // we need a normal color texture for this filter - NSAssert(self.outputTextureOptions.internalFormat == GL_RGBA, @"The output texture format for this filter must be GL_RGBA."); - NSAssert(self.outputTextureOptions.type == GL_UNSIGNED_BYTE, @"The type of the output texture of this filter must be GL_UNSIGNED_BYTE."); - - NSUInteger numberOfCorners = 0; - CGSize imageSize = nonMaximumSuppressionFilter.outputFrameSize; - - unsigned int imageByteSize = imageSize.width * imageSize.height * 4; - - if (rawImagePixels == NULL) - { - rawImagePixels = (GLubyte *)malloc(imageByteSize); - cornersArray = calloc(512 * 2, sizeof(GLfloat)); - } - - glReadPixels(0, 0, (int)imageSize.width, (int)imageSize.height, GL_RGBA, GL_UNSIGNED_BYTE, rawImagePixels); - - CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); - - unsigned int imageWidth = imageSize.width * 4; - - unsigned int currentByte = 0; - unsigned int cornerStorageIndex = 0; - while (currentByte < imageByteSize) - { - GLubyte colorByte = rawImagePixels[currentByte]; - - if (colorByte > 0) - { - unsigned int xCoordinate = currentByte % imageWidth; - unsigned int yCoordinate = currentByte / imageWidth; - - cornersArray[cornerStorageIndex++] = (CGFloat)(xCoordinate / 4) / imageSize.width; - cornersArray[cornerStorageIndex++] = (CGFloat)(yCoordinate) / imageSize.height; - numberOfCorners++; - - numberOfCorners = MIN(numberOfCorners, 511); - cornerStorageIndex = MIN(cornerStorageIndex, 1021); - } - currentByte +=4; - } - - CFAbsoluteTime currentFrameTime = (CFAbsoluteTimeGetCurrent() - startTime); - NSLog(@"Processing time : %f ms", 1000.0 * currentFrameTime); - - if (cornersDetectedBlock != NULL) - { - cornersDetectedBlock(cornersArray, numberOfCorners, frameTime); - } -} - -- (BOOL)wantsMonochromeInput; -{ -// return YES; - return NO; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setBlurRadiusInPixels:(CGFloat)newValue; -{ - blurFilter.blurRadiusInPixels = newValue; -} - -- (CGFloat)blurRadiusInPixels; -{ - return blurFilter.blurRadiusInPixels; -} - -- (void)setSensitivity:(CGFloat)newValue; -{ - _sensitivity = newValue; - [harrisCornerDetectionFilter setFloat:newValue forUniformName:@"sensitivity"]; -} - -- (void)setThreshold:(CGFloat)newValue; -{ - nonMaximumSuppressionFilter.threshold = newValue; -} - -- (CGFloat)threshold; -{ - return nonMaximumSuppressionFilter.threshold; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHazeFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHazeFilter.h deleted file mode 100755 index eb3fbca6..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHazeFilter.h +++ /dev/null @@ -1,29 +0,0 @@ -#import "GPUImageFilter.h" - -/* - * The haze filter can be used to add or remove haze (similar to a UV filter) - * - * @author Alaric Cole - * @creationDate 03/10/12 - * - */ - -/** The haze filter can be used to add or remove haze - - This is similar to a UV filter - */ -@interface GPUImageHazeFilter : GPUImageFilter -{ - GLint distanceUniform; - GLint slopeUniform; -} - -/** Strength of the color applied. Default 0. Values between -.3 and .3 are best - */ -@property(readwrite, nonatomic) CGFloat distance; - -/** Amount of color change. Default 0. Values between -.3 and .3 are best - */ -@property(readwrite, nonatomic) CGFloat slope; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHazeFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHazeFilter.m deleted file mode 100755 index f90fc22f..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHazeFilter.m +++ /dev/null @@ -1,96 +0,0 @@ -#import "GPUImageHazeFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageHazeFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform lowp float hazeDistance; - uniform highp float slope; - - void main() - { - //todo reconsider precision modifiers - highp vec4 color = vec4(1.0);//todo reimplement as a parameter - - highp float d = textureCoordinate.y * slope + hazeDistance; - - highp vec4 c = texture2D(inputImageTexture, textureCoordinate) ; // consider using unpremultiply - - c = (c - d * color) / (1.0 -d); - - gl_FragColor = c; //consider using premultiply(c); - } -); -#else -NSString *const kGPUImageHazeFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform float hazeDistance; - uniform float slope; - - void main() - { - //todo reconsider precision modifiers - vec4 color = vec4(1.0);//todo reimplement as a parameter - - float d = textureCoordinate.y * slope + hazeDistance; - - vec4 c = texture2D(inputImageTexture, textureCoordinate) ; // consider using unpremultiply - - c = (c - d * color) / (1.0 -d); - - gl_FragColor = c; //consider using premultiply(c); - } -); -#endif - - - - -@implementation GPUImageHazeFilter - -@synthesize distance = _distance; -@synthesize slope = _slope; -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageHazeFragmentShaderString])) - { - return nil; - } - - distanceUniform = [filterProgram uniformIndex:@"hazeDistance"]; - slopeUniform = [filterProgram uniformIndex:@"slope"]; - - self.distance = 0.2; - self.slope = 0.0; - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setDistance:(CGFloat)newValue; -{ - _distance = newValue; - - [self setFloat:_distance forUniform:distanceUniform program:filterProgram]; -} - -- (void)setSlope:(CGFloat)newValue; -{ - _slope = newValue; - - [self setFloat:_slope forUniform:slopeUniform program:filterProgram]; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHighPassFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHighPassFilter.h deleted file mode 100644 index 263d8df1..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHighPassFilter.h +++ /dev/null @@ -1,14 +0,0 @@ -#import "GPUImageFilterGroup.h" -#import "GPUImageLowPassFilter.h" -#import "GPUImageDifferenceBlendFilter.h" - -@interface GPUImageHighPassFilter : GPUImageFilterGroup -{ - GPUImageLowPassFilter *lowPassFilter; - GPUImageDifferenceBlendFilter *differenceBlendFilter; -} - -// This controls the degree by which the previous accumulated frames are blended and then subtracted from the current one. This ranges from 0.0 to 1.0, with a default of 0.5. -@property(readwrite, nonatomic) CGFloat filterStrength; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHighPassFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHighPassFilter.m deleted file mode 100644 index 511240d8..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHighPassFilter.m +++ /dev/null @@ -1,46 +0,0 @@ -#import "GPUImageHighPassFilter.h" - -@implementation GPUImageHighPassFilter - -@synthesize filterStrength; - -- (id)init; -{ - if (!(self = [super init])) - { - return nil; - } - - // Start with a low pass filter to define the component to be removed - lowPassFilter = [[GPUImageLowPassFilter alloc] init]; - [self addFilter:lowPassFilter]; - - // Take the difference of the current frame from the low pass filtered result to get the high pass - differenceBlendFilter = [[GPUImageDifferenceBlendFilter alloc] init]; - [self addFilter:differenceBlendFilter]; - - // Texture location 0 needs to be the original image for the difference blend - [lowPassFilter addTarget:differenceBlendFilter atTextureLocation:1]; - - self.initialFilters = [NSArray arrayWithObjects:lowPassFilter, differenceBlendFilter, nil]; - self.terminalFilter = differenceBlendFilter; - - self.filterStrength = 0.5; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setFilterStrength:(CGFloat)newValue; -{ - lowPassFilter.filterStrength = newValue; -} - -- (CGFloat)filterStrength; -{ - return lowPassFilter.filterStrength; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHighlightShadowFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHighlightShadowFilter.h deleted file mode 100644 index 35791298..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHighlightShadowFilter.h +++ /dev/null @@ -1,20 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageHighlightShadowFilter : GPUImageFilter -{ - GLint shadowsUniform, highlightsUniform; -} - -/** - * 0 - 1, increase to lighten shadows. - * @default 0 - */ -@property(readwrite, nonatomic) CGFloat shadows; - -/** - * 0 - 1, decrease to darken highlights. - * @default 1 - */ -@property(readwrite, nonatomic) CGFloat highlights; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHighlightShadowFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHighlightShadowFilter.m deleted file mode 100644 index aa92b740..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHighlightShadowFilter.m +++ /dev/null @@ -1,93 +0,0 @@ -#import "GPUImageHighlightShadowFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageHighlightShadowFragmentShaderString = SHADER_STRING -( -uniform sampler2D inputImageTexture; -varying highp vec2 textureCoordinate; - -uniform lowp float shadows; -uniform lowp float highlights; - -const mediump vec3 luminanceWeighting = vec3(0.3, 0.3, 0.3); - -void main() -{ - lowp vec4 source = texture2D(inputImageTexture, textureCoordinate); - mediump float luminance = dot(source.rgb, luminanceWeighting); - - mediump float shadow = clamp((pow(luminance, 1.0/(shadows+1.0)) + (-0.76)*pow(luminance, 2.0/(shadows+1.0))) - luminance, 0.0, 1.0); - mediump float highlight = clamp((1.0 - (pow(1.0-luminance, 1.0/(2.0-highlights)) + (-0.8)*pow(1.0-luminance, 2.0/(2.0-highlights)))) - luminance, -1.0, 0.0); - lowp vec3 result = vec3(0.0, 0.0, 0.0) + ((luminance + shadow + highlight) - 0.0) * ((source.rgb - vec3(0.0, 0.0, 0.0))/(luminance - 0.0)); - - gl_FragColor = vec4(result.rgb, source.a); -} -); -#else -NSString *const kGPUImageHighlightShadowFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - varying vec2 textureCoordinate; - - uniform float shadows; - uniform float highlights; - - const vec3 luminanceWeighting = vec3(0.3, 0.3, 0.3); - - void main() - { - vec4 source = texture2D(inputImageTexture, textureCoordinate); - float luminance = dot(source.rgb, luminanceWeighting); - - float shadow = clamp((pow(luminance, 1.0/(shadows+1.0)) + (-0.76)*pow(luminance, 2.0/(shadows+1.0))) - luminance, 0.0, 1.0); - float highlight = clamp((1.0 - (pow(1.0-luminance, 1.0/(2.0-highlights)) + (-0.8)*pow(1.0-luminance, 2.0/(2.0-highlights)))) - luminance, -1.0, 0.0); - vec3 result = vec3(0.0, 0.0, 0.0) + ((luminance + shadow + highlight) - 0.0) * ((source.rgb - vec3(0.0, 0.0, 0.0))/(luminance - 0.0)); - - gl_FragColor = vec4(result.rgb, source.a); - } -); -#endif - -@implementation GPUImageHighlightShadowFilter - -@synthesize shadows = _shadows; -@synthesize highlights = _highlights; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageHighlightShadowFragmentShaderString])) - { - return nil; - } - - shadowsUniform = [filterProgram uniformIndex:@"shadows"]; - highlightsUniform = [filterProgram uniformIndex:@"highlights"]; - - self.shadows = 0.0; - self.highlights = 1.0; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setShadows:(CGFloat)newValue; -{ - _shadows = newValue; - - [self setFloat:_shadows forUniform:shadowsUniform program:filterProgram]; -} - -- (void)setHighlights:(CGFloat)newValue; -{ - _highlights = newValue; - - [self setFloat:_highlights forUniform:highlightsUniform program:filterProgram]; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramEqualizationFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramEqualizationFilter.h deleted file mode 100644 index 2b71cda0..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramEqualizationFilter.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// GPUImageHistogramEqualizationFilter.h -// FilterShowcase -// -// Created by Adam Marcus on 19/08/2014. -// Copyright (c) 2014 Sunset Lake Software LLC. All rights reserved. -// - -#import "GPUImageFilterGroup.h" -#import "GPUImageHistogramFilter.h" -#import "GPUImageRawDataOutput.h" -#import "GPUImageRawDataInput.h" -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageHistogramEqualizationFilter : GPUImageFilterGroup -{ - GPUImageHistogramFilter *histogramFilter; - GPUImageRawDataOutput *rawDataOutputFilter; - GPUImageRawDataInput *rawDataInputFilter; -} - -@property(readwrite, nonatomic) NSUInteger downsamplingFactor; - -- (id)initWithHistogramType:(GPUImageHistogramType)newHistogramType; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramEqualizationFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramEqualizationFilter.m deleted file mode 100644 index 7d6b9a2d..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramEqualizationFilter.m +++ /dev/null @@ -1,307 +0,0 @@ -// -// GPUImageHistogramEqualizationFilter.m -// FilterShowcase -// -// Created by Adam Marcus on 19/08/2014. -// Copyright (c) 2014 Sunset Lake Software LLC. All rights reserved. -// - -#import "GPUImageHistogramEqualizationFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageRedHistogramEqualizationFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - lowp float redCurveValue = texture2D(inputImageTexture2, vec2(textureColor.r, 0.0)).r; - - gl_FragColor = vec4(redCurveValue, textureColor.g, textureColor.b, textureColor.a); - } - ); -#else -NSString *const kGPUImageRedHistogramEqualizationFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - float redCurveValue = texture2D(inputImageTexture2, vec2(textureColor.r, 0.0)).r; - - gl_FragColor = vec4(redCurveValue, textureColor.g, textureColor.b, textureColor.a); - } - ); -#endif - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageGreenHistogramEqualizationFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - lowp float greenCurveValue = texture2D(inputImageTexture2, vec2(textureColor.g, 0.0)).g; - - gl_FragColor = vec4(textureColor.r, greenCurveValue, textureColor.b, textureColor.a); - } - ); -#else -NSString *const kGPUImageGreenHistogramEqualizationFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - float greenCurveValue = texture2D(inputImageTexture2, vec2(textureColor.g, 0.0)).g; - - gl_FragColor = vec4(textureColor.r, greenCurveValue, textureColor.b, textureColor.a); - } - ); -#endif - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageBlueHistogramEqualizationFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - lowp float blueCurveValue = texture2D(inputImageTexture2, vec2(textureColor.b, 0.0)).b; - - gl_FragColor = vec4(textureColor.r, textureColor.g, blueCurveValue, textureColor.a); - } - ); -#else -NSString *const kGPUImageBlueHistogramEqualizationFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - float blueCurveValue = texture2D(inputImageTexture2, vec2(textureColor.b, 0.0)).b; - - gl_FragColor = vec4(textureColor.r, textureColor.g, blueCurveValue, textureColor.a); - } - ); -#endif - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageRGBHistogramEqualizationFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - lowp float redCurveValue = texture2D(inputImageTexture2, vec2(textureColor.r, 0.0)).r; - lowp float greenCurveValue = texture2D(inputImageTexture2, vec2(textureColor.g, 0.0)).g; - lowp float blueCurveValue = texture2D(inputImageTexture2, vec2(textureColor.b, 0.0)).b; - - gl_FragColor = vec4(redCurveValue, greenCurveValue, blueCurveValue, textureColor.a); - } - ); -#else -NSString *const kGPUImageRGBHistogramEqualizationFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - float redCurveValue = texture2D(inputImageTexture2, vec2(textureColor.r, 0.0)).r; - float greenCurveValue = texture2D(inputImageTexture2, vec2(textureColor.g, 0.0)).g; - float blueCurveValue = texture2D(inputImageTexture2, vec2(textureColor.b, 0.0)).b; - - gl_FragColor = vec4(redCurveValue, greenCurveValue, blueCurveValue, textureColor.a); - } - ); -#endif - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageLuminanceHistogramEqualizationFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - const lowp vec3 W = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - lowp float luminance = dot(textureColor.rgb, W); - lowp float newLuminance = texture2D(inputImageTexture2, vec2(luminance, 0.0)).r; - lowp float deltaLuminance = newLuminance - luminance; - - lowp float red = clamp(textureColor.r + deltaLuminance, 0.0, 1.0); - lowp float green = clamp(textureColor.g + deltaLuminance, 0.0, 1.0); - lowp float blue = clamp(textureColor.b + deltaLuminance, 0.0, 1.0); - - gl_FragColor = vec4(red, green, blue, textureColor.a); - } - ); -#else -NSString *const kGPUImageLuminanceHistogramEqualizationFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - const vec3 W = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - float luminance = dot(textureColor.rgb, W); - float newLuminance = texture2D(inputImageTexture2, vec2(luminance, 0.0)).r; - float deltaLuminance = newLuminance - luminance; - - float red = clamp(textureColor.r + deltaLuminance, 0.0, 1.0); - float green = clamp(textureColor.g + deltaLuminance, 0.0, 1.0); - float blue = clamp(textureColor.b + deltaLuminance, 0.0, 1.0); - - gl_FragColor = vec4(red, green, blue, textureColor.a); - } - ); -#endif - -@implementation GPUImageHistogramEqualizationFilter - -@synthesize downsamplingFactor = _downsamplingFactor; - -#pragma mark - -#pragma mark Initialization - -- (id)init; -{ - if (!(self = [self initWithHistogramType:kGPUImageHistogramRGB])) - { - return nil; - } - - return self; -} - -- (id)initWithHistogramType:(GPUImageHistogramType)newHistogramType -{ - if (!(self = [super init])) - { - return nil; - } - - histogramFilter = [[GPUImageHistogramFilter alloc] initWithHistogramType:newHistogramType]; - [self addFilter:histogramFilter]; - - GLubyte dummyInput[4 * 256]; // NB: No way to initialise GPUImageRawDataInput without providing bytes - rawDataInputFilter = [[GPUImageRawDataInput alloc] initWithBytes:dummyInput size:CGSizeMake(256.0, 1.0) pixelFormat:GPUPixelFormatBGRA type:GPUPixelTypeUByte]; - rawDataOutputFilter = [[GPUImageRawDataOutput alloc] initWithImageSize:CGSizeMake(256.0, 3.0) resultsInBGRAFormat:YES]; - - __unsafe_unretained GPUImageRawDataOutput *_rawDataOutputFilter = rawDataOutputFilter; - __unsafe_unretained GPUImageRawDataInput *_rawDataInputFilter = rawDataInputFilter; - [rawDataOutputFilter setNewFrameAvailableBlock:^{ - - unsigned int histogramBins[3][256]; - - [_rawDataOutputFilter lockFramebufferForReading]; - - GLubyte *data = [_rawDataOutputFilter rawBytesForImage]; - data += [_rawDataOutputFilter bytesPerRowInOutput]; - - histogramBins[0][0] = *data++; - histogramBins[1][0] = *data++; - histogramBins[2][0] = *data++; - data++; - - for (unsigned int x = 1; x < 256; x++) { - histogramBins[0][x] = histogramBins[0][x-1] + *data++; - histogramBins[1][x] = histogramBins[1][x-1] + *data++; - histogramBins[2][x] = histogramBins[2][x-1] + *data++; - data++; - } - - [_rawDataOutputFilter unlockFramebufferAfterReading]; - - GLubyte colorMapping[4 * 256]; - GLubyte *_colorMapping = colorMapping; - - for (unsigned int x = 0; x < 256; x++) { - *_colorMapping++ = (GLubyte) (((histogramBins[0][x] - histogramBins[0][0]) * 255) / histogramBins[0][255]); - *_colorMapping++ = (GLubyte) (((histogramBins[1][x] - histogramBins[1][0]) * 255) / histogramBins[1][255]); - *_colorMapping++ = (GLubyte) (((histogramBins[2][x] - histogramBins[2][0]) * 255) / histogramBins[2][255]); - *_colorMapping++ = 255; - } - - _colorMapping = colorMapping; - [_rawDataInputFilter updateDataFromBytes:_colorMapping size:CGSizeMake(256.0, 1.0)]; - [_rawDataInputFilter processData]; - }]; - [histogramFilter addTarget:rawDataOutputFilter]; - - NSString *fragmentShader = nil; - switch (newHistogramType) { - case kGPUImageHistogramRed: - fragmentShader = kGPUImageRedHistogramEqualizationFragmentShaderString; - break; - case kGPUImageHistogramGreen: - fragmentShader = kGPUImageGreenHistogramEqualizationFragmentShaderString; - break; - case kGPUImageHistogramBlue: - fragmentShader = kGPUImageBlueHistogramEqualizationFragmentShaderString; - break; - default: - case kGPUImageHistogramRGB: - fragmentShader = kGPUImageRGBHistogramEqualizationFragmentShaderString; - break; - case kGPUImageHistogramLuminance: - fragmentShader = kGPUImageLuminanceHistogramEqualizationFragmentShaderString; - break; - } - GPUImageFilter *equalizationFilter = [[GPUImageTwoInputFilter alloc] initWithFragmentShaderFromString:fragmentShader]; - [rawDataInputFilter addTarget:equalizationFilter atTextureLocation:1]; - - [self addFilter:equalizationFilter]; - - self.initialFilters = [NSArray arrayWithObjects:histogramFilter, equalizationFilter, nil]; - self.terminalFilter = equalizationFilter; - - self.downsamplingFactor = 16; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setDownsamplingFactor:(NSUInteger)newValue; -{ - if (_downsamplingFactor != newValue) - { - _downsamplingFactor = newValue; - histogramFilter.downsamplingFactor = newValue; - } -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramFilter.h deleted file mode 100755 index 32004bf7..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramFilter.h +++ /dev/null @@ -1,22 +0,0 @@ -#import "GPUImageFilter.h" - -typedef enum { kGPUImageHistogramRed, kGPUImageHistogramGreen, kGPUImageHistogramBlue, kGPUImageHistogramRGB, kGPUImageHistogramLuminance} GPUImageHistogramType; - -@interface GPUImageHistogramFilter : GPUImageFilter -{ - GPUImageHistogramType histogramType; - - GLubyte *vertexSamplingCoordinates; - - GLProgram *secondFilterProgram, *thirdFilterProgram; - GLint secondFilterPositionAttribute, thirdFilterPositionAttribute; -} - -// Rather than sampling every pixel, this dictates what fraction of the image is sampled. By default, this is 16 with a minimum of 1. -@property(readwrite, nonatomic) NSUInteger downsamplingFactor; - -// Initialization and teardown -- (id)initWithHistogramType:(GPUImageHistogramType)newHistogramType; -- (void)initializeSecondaryAttributes; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramFilter.m deleted file mode 100755 index bb7acce7..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramFilter.m +++ /dev/null @@ -1,341 +0,0 @@ -#import "GPUImageHistogramFilter.h" - -// Unlike other filters, this one uses a grid of GL_POINTs to sample the incoming image in a grid. A custom vertex shader reads the color in the texture at its position -// and outputs a bin position in the final histogram as the vertex position. That point is then written into the image of the histogram using translucent pixels. -// The degree of translucency is controlled by the scalingFactor, which lets you adjust the dynamic range of the histogram. The histogram can only be generated for one -// color channel or luminance value at a time. -// -// This is based on this implementation: http://www.shaderwrangler.com/publications/histogram/histogram_cameraready.pdf -// -// Or at least that's how it would work if iOS could read from textures in a vertex shader, which it can't. Therefore, I read the texture data down from the -// incoming frame and process the texture colors as vertices. - -NSString *const kGPUImageRedHistogramSamplingVertexShaderString = SHADER_STRING -( - attribute vec4 position; - - varying vec3 colorFactor; - - void main() - { - colorFactor = vec3(1.0, 0.0, 0.0); - gl_Position = vec4(-1.0 + (position.x * 0.0078125), 0.0, 0.0, 1.0); - gl_PointSize = 1.0; - } -); - -NSString *const kGPUImageGreenHistogramSamplingVertexShaderString = SHADER_STRING -( - attribute vec4 position; - - varying vec3 colorFactor; - - void main() - { - colorFactor = vec3(0.0, 1.0, 0.0); - gl_Position = vec4(-1.0 + (position.y * 0.0078125), 0.0, 0.0, 1.0); - gl_PointSize = 1.0; - } -); - -NSString *const kGPUImageBlueHistogramSamplingVertexShaderString = SHADER_STRING -( - attribute vec4 position; - - varying vec3 colorFactor; - - void main() - { - colorFactor = vec3(0.0, 0.0, 1.0); - gl_Position = vec4(-1.0 + (position.z * 0.0078125), 0.0, 0.0, 1.0); - gl_PointSize = 1.0; - } -); - -NSString *const kGPUImageLuminanceHistogramSamplingVertexShaderString = SHADER_STRING -( - attribute vec4 position; - - varying vec3 colorFactor; - - const vec3 W = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - float luminance = dot(position.xyz, W); - - colorFactor = vec3(1.0, 1.0, 1.0); - gl_Position = vec4(-1.0 + (luminance * 0.0078125), 0.0, 0.0, 1.0); - gl_PointSize = 1.0; - } -); - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageHistogramAccumulationFragmentShaderString = SHADER_STRING -( - const lowp float scalingFactor = 1.0 / 256.0; - - varying lowp vec3 colorFactor; - - void main() - { - gl_FragColor = vec4(colorFactor * scalingFactor , 1.0); - } -); -#else -NSString *const kGPUImageHistogramAccumulationFragmentShaderString = SHADER_STRING -( - const float scalingFactor = 1.0 / 256.0; - - varying vec3 colorFactor; - - void main() - { - gl_FragColor = vec4(colorFactor * scalingFactor , 1.0); - } -); -#endif - -@implementation GPUImageHistogramFilter - -@synthesize downsamplingFactor = _downsamplingFactor; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithHistogramType:(GPUImageHistogramType)newHistogramType; -{ - switch (newHistogramType) - { - case kGPUImageHistogramRed: - { - if (!(self = [super initWithVertexShaderFromString:kGPUImageRedHistogramSamplingVertexShaderString fragmentShaderFromString:kGPUImageHistogramAccumulationFragmentShaderString])) - { - return nil; - } - }; break; - case kGPUImageHistogramGreen: - { - if (!(self = [super initWithVertexShaderFromString:kGPUImageGreenHistogramSamplingVertexShaderString fragmentShaderFromString:kGPUImageHistogramAccumulationFragmentShaderString])) - { - return nil; - } - }; break; - case kGPUImageHistogramBlue: - { - if (!(self = [super initWithVertexShaderFromString:kGPUImageBlueHistogramSamplingVertexShaderString fragmentShaderFromString:kGPUImageHistogramAccumulationFragmentShaderString])) - { - return nil; - } - }; break; - case kGPUImageHistogramLuminance: - { - if (!(self = [super initWithVertexShaderFromString:kGPUImageLuminanceHistogramSamplingVertexShaderString fragmentShaderFromString:kGPUImageHistogramAccumulationFragmentShaderString])) - { - return nil; - } - }; break; - case kGPUImageHistogramRGB: - { - if (!(self = [super initWithVertexShaderFromString:kGPUImageRedHistogramSamplingVertexShaderString fragmentShaderFromString:kGPUImageHistogramAccumulationFragmentShaderString])) - { - return nil; - } - - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext useImageProcessingContext]; - - secondFilterProgram = [[GPUImageContext sharedImageProcessingContext] programForVertexShaderString:kGPUImageGreenHistogramSamplingVertexShaderString fragmentShaderString:kGPUImageHistogramAccumulationFragmentShaderString]; - thirdFilterProgram = [[GPUImageContext sharedImageProcessingContext] programForVertexShaderString:kGPUImageBlueHistogramSamplingVertexShaderString fragmentShaderString:kGPUImageHistogramAccumulationFragmentShaderString]; - - if (!secondFilterProgram.initialized) - { - [self initializeSecondaryAttributes]; - - if (![secondFilterProgram link]) - { - NSString *progLog = [secondFilterProgram programLog]; - NSLog(@"Program link log: %@", progLog); - NSString *fragLog = [secondFilterProgram fragmentShaderLog]; - NSLog(@"Fragment shader compile log: %@", fragLog); - NSString *vertLog = [secondFilterProgram vertexShaderLog]; - NSLog(@"Vertex shader compile log: %@", vertLog); - filterProgram = nil; - NSAssert(NO, @"Filter shader link failed"); - - } - - [GPUImageContext setActiveShaderProgram:secondFilterProgram]; - - glEnableVertexAttribArray(secondFilterPositionAttribute); - - if (![thirdFilterProgram link]) - { - NSString *progLog = [secondFilterProgram programLog]; - NSLog(@"Program link log: %@", progLog); - NSString *fragLog = [secondFilterProgram fragmentShaderLog]; - NSLog(@"Fragment shader compile log: %@", fragLog); - NSString *vertLog = [secondFilterProgram vertexShaderLog]; - NSLog(@"Vertex shader compile log: %@", vertLog); - filterProgram = nil; - NSAssert(NO, @"Filter shader link failed"); - } - } - - secondFilterPositionAttribute = [secondFilterProgram attributeIndex:@"position"]; - - - thirdFilterPositionAttribute = [thirdFilterProgram attributeIndex:@"position"]; - [GPUImageContext setActiveShaderProgram:thirdFilterProgram]; - - glEnableVertexAttribArray(thirdFilterPositionAttribute); - }); - }; break; - } - - histogramType = newHistogramType; - - self.downsamplingFactor = 16; - - return self; -} - -- (id)init; -{ - if (!(self = [self initWithHistogramType:kGPUImageHistogramRGB])) - { - return nil; - } - - return self; -} - -- (void)initializeSecondaryAttributes; -{ - [secondFilterProgram addAttribute:@"position"]; - [thirdFilterProgram addAttribute:@"position"]; -} - -- (void)dealloc; -{ - if (vertexSamplingCoordinates != NULL && ![GPUImageContext supportsFastTextureUpload]) - { - free(vertexSamplingCoordinates); - } -} - -#pragma mark - -#pragma mark Rendering - -- (CGSize)sizeOfFBO; -{ - return CGSizeMake(256.0, 3.0); -} - -- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex; -{ - [self renderToTextureWithVertices:NULL textureCoordinates:NULL]; - - [self informTargetsAboutNewFrameAtTime:frameTime]; -} - -- (CGSize)outputFrameSize; -{ - return [self sizeOfFBO]; -} - -- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex; -{ - if (self.preventRendering) - { - return; - } - - inputTextureSize = newSize; -} - -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -{ - inputRotation = kGPUImageNoRotation; -} - -- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates; -{ - // we need a normal color texture for this filter - NSAssert(self.outputTextureOptions.internalFormat == GL_RGBA, @"The output texture format for this filter must be GL_RGBA."); - NSAssert(self.outputTextureOptions.type == GL_UNSIGNED_BYTE, @"The type of the output texture of this filter must be GL_UNSIGNED_BYTE."); - - if (self.preventRendering) - { - [firstInputFramebuffer unlock]; - return; - } - - [GPUImageContext useImageProcessingContext]; - - if ([GPUImageContext supportsFastTextureUpload]) - { - glFinish(); - vertexSamplingCoordinates = [firstInputFramebuffer byteBuffer]; - } else { - if (vertexSamplingCoordinates == NULL) - { - vertexSamplingCoordinates = calloc(inputTextureSize.width * inputTextureSize.height * 4, sizeof(GLubyte)); - } - glReadPixels(0, 0, inputTextureSize.width, inputTextureSize.height, GL_RGBA, GL_UNSIGNED_BYTE, vertexSamplingCoordinates); - } - - outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:[self sizeOfFBO] textureOptions:self.outputTextureOptions onlyTexture:NO]; - [outputFramebuffer activateFramebuffer]; - if (usingNextFrameForImageCapture) - { - [outputFramebuffer lock]; - } - - [GPUImageContext setActiveShaderProgram:filterProgram]; - - glClearColor(0.0, 0.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_ONE, GL_ONE); - glEnable(GL_BLEND); - - glVertexAttribPointer(filterPositionAttribute, 4, GL_UNSIGNED_BYTE, 0, ((unsigned int)_downsamplingFactor - 1) * 4, vertexSamplingCoordinates); - glDrawArrays(GL_POINTS, 0, inputTextureSize.width * inputTextureSize.height / (CGFloat)_downsamplingFactor); - - if (histogramType == kGPUImageHistogramRGB) - { - [GPUImageContext setActiveShaderProgram:secondFilterProgram]; - - glVertexAttribPointer(secondFilterPositionAttribute, 4, GL_UNSIGNED_BYTE, 0, ((unsigned int)_downsamplingFactor - 1) * 4, vertexSamplingCoordinates); - glDrawArrays(GL_POINTS, 0, inputTextureSize.width * inputTextureSize.height / (CGFloat)_downsamplingFactor); - - [GPUImageContext setActiveShaderProgram:thirdFilterProgram]; - - glVertexAttribPointer(thirdFilterPositionAttribute, 4, GL_UNSIGNED_BYTE, 0, ((unsigned int)_downsamplingFactor - 1) * 4, vertexSamplingCoordinates); - glDrawArrays(GL_POINTS, 0, inputTextureSize.width * inputTextureSize.height / (CGFloat)_downsamplingFactor); - } - - glDisable(GL_BLEND); - [firstInputFramebuffer unlock]; - - if (usingNextFrameForImageCapture) - { - dispatch_semaphore_signal(imageCaptureSemaphore); - } -} - -#pragma mark - -#pragma mark Accessors - -//- (void)setScalingFactor:(CGFloat)newValue; -//{ -// _scalingFactor = newValue; -// -// [GPUImageContext useImageProcessingContext]; -// [filterProgram use]; -// glUniform1f(scalingFactorUniform, _scalingFactor); -//} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramGenerator.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramGenerator.h deleted file mode 100755 index f80c50f3..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramGenerator.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageHistogramGenerator : GPUImageFilter -{ - GLint backgroundColorUniform; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramGenerator.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramGenerator.m deleted file mode 100755 index 703795df..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHistogramGenerator.m +++ /dev/null @@ -1,87 +0,0 @@ -#import "GPUImageHistogramGenerator.h" - -NSString *const kGPUImageHistogramGeneratorVertexShaderString = SHADER_STRING -( - attribute vec4 position; - attribute vec4 inputTextureCoordinate; - - varying vec2 textureCoordinate; - varying float height; - - void main() - { - gl_Position = position; - textureCoordinate = vec2(inputTextureCoordinate.x, 0.5); - height = 1.0 - inputTextureCoordinate.y; - } -); - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageHistogramGeneratorFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp float height; - - uniform sampler2D inputImageTexture; - uniform lowp vec4 backgroundColor; - - void main() - { - lowp vec3 colorChannels = texture2D(inputImageTexture, textureCoordinate).rgb; - lowp vec4 heightTest = vec4(step(height, colorChannels), 1.0); - gl_FragColor = mix(backgroundColor, heightTest, heightTest.r + heightTest.g + heightTest.b); - } -); -#else -NSString *const kGPUImageHistogramGeneratorFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying float height; - - uniform sampler2D inputImageTexture; - uniform vec4 backgroundColor; - - void main() - { - vec3 colorChannels = texture2D(inputImageTexture, textureCoordinate).rgb; - vec4 heightTest = vec4(step(height, colorChannels), 1.0); - gl_FragColor = mix(backgroundColor, heightTest, heightTest.r + heightTest.g + heightTest.b); - } -); -#endif - -@implementation GPUImageHistogramGenerator - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithVertexShaderFromString:kGPUImageHistogramGeneratorVertexShaderString fragmentShaderFromString:kGPUImageHistogramGeneratorFragmentShaderString])) - { - return nil; - } - - backgroundColorUniform = [filterProgram uniformIndex:@"backgroundColor"]; - - [self setBackgroundColorRed:0.0 green:0.0 blue:0.0 alpha:0.0]; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setBackgroundColorRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent alpha:(GLfloat)alphaComponent; -{ -// GLfloat backgroundColor[4]; -// backgroundColor[0] = redComponent; -// backgroundColor[1] = greenComponent; -// backgroundColor[2] = blueComponent; -// backgroundColor[3] = alphaComponent; - GPUVector4 backgroundColor = {redComponent, greenComponent, blueComponent, alphaComponent}; - - [self setVec4:backgroundColor forUniform:backgroundColorUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHoughTransformLineDetector.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHoughTransformLineDetector.h deleted file mode 100644 index 3ab6977f..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHoughTransformLineDetector.h +++ /dev/null @@ -1,49 +0,0 @@ -#import "GPUImageFilterGroup.h" -#import "GPUImageThresholdEdgeDetectionFilter.h" -#import "GPUImageParallelCoordinateLineTransformFilter.h" -#import "GPUImageThresholdedNonMaximumSuppressionFilter.h" -#import "GPUImageCannyEdgeDetectionFilter.h" - -// This applies a Hough transform to detect lines in a scene. It starts with a thresholded Sobel edge detection pass, -// then takes those edge points in and applies a Hough transform to convert them to lines. The intersection of these lines -// is then determined via blending and accumulation, and a non-maximum suppression filter is applied to find local maxima. -// These local maxima are then converted back into lines in normal space and returned via a callback block. -// -// Rather than using one of the standard Hough transform types, this filter uses parallel coordinate space which is far more efficient -// to rasterize on a GPU. -// -// This approach is based entirely on the PC lines process developed by the Graph@FIT research group at the Brno University of Technology -// and described in their publications: -// -// M. Dubská, J. Havel, and A. Herout. Real-Time Detection of Lines using Parallel Coordinates and OpenGL. Proceedings of SCCG 2011, Bratislava, SK, p. 7. -// http://medusa.fit.vutbr.cz/public/data/papers/2011-SCCG-Dubska-Real-Time-Line-Detection-Using-PC-and-OpenGL.pdf -// M. Dubská, J. Havel, and A. Herout. PClines — Line detection using parallel coordinates. 2011 IEEE Conference on Computer Vision and Pattern Recognition (CVPR), p. 1489- 1494. -// http://medusa.fit.vutbr.cz/public/data/papers/2011-CVPR-Dubska-PClines.pdf - -//#define DEBUGLINEDETECTION - -@interface GPUImageHoughTransformLineDetector : GPUImageFilterGroup -{ - GPUImageOutput *thresholdEdgeDetectionFilter; - -// GPUImageThresholdEdgeDetectionFilter *thresholdEdgeDetectionFilter; - GPUImageParallelCoordinateLineTransformFilter *parallelCoordinateLineTransformFilter; - GPUImageThresholdedNonMaximumSuppressionFilter *nonMaximumSuppressionFilter; - - GLfloat *linesArray; - GLubyte *rawImagePixels; -} - -// A threshold value for which a point is detected as belonging to an edge for determining lines. Default is 0.9. -@property(readwrite, nonatomic) CGFloat edgeThreshold; - -// A threshold value for which a local maximum is detected as belonging to a line in parallel coordinate space. Default is 0.20. -@property(readwrite, nonatomic) CGFloat lineDetectionThreshold; - -// This block is called on the detection of lines, usually on every processed frame. A C array containing normalized slopes and intercepts in m, b pairs (y=mx+b) is passed in, along with a count of the number of lines detected and the current timestamp of the video frame -@property(nonatomic, copy) void(^linesDetectedBlock)(GLfloat* lineArray, NSUInteger linesDetected, CMTime frameTime); - -// These images are only enabled when built with DEBUGLINEDETECTION defined, and are used to examine the intermediate states of the Hough transform -@property(nonatomic, readonly, strong) NSMutableArray *intermediateImages; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHoughTransformLineDetector.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHoughTransformLineDetector.m deleted file mode 100644 index 8289eb80..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHoughTransformLineDetector.m +++ /dev/null @@ -1,241 +0,0 @@ -#import "GPUImageHoughTransformLineDetector.h" - -@interface GPUImageHoughTransformLineDetector() - -- (void)extractLineParametersFromImageAtFrameTime:(CMTime)frameTime; - -@end - -@implementation GPUImageHoughTransformLineDetector - -@synthesize linesDetectedBlock; -@synthesize edgeThreshold; -@synthesize lineDetectionThreshold; -@synthesize intermediateImages = _intermediateImages; - -- (id)init; -{ - if (!(self = [super init])) - { - return nil; - } - - // First pass: do edge detection and threshold that to just have white pixels for edges -// if ([GPUImageContext deviceSupportsFramebufferReads]) -// if ([GPUImageContext deviceSupportsFramebufferReads]) -// { -// thresholdEdgeDetectionFilter = [[GPUImageThresholdEdgeDetectionFilter alloc] init]; -// thresholdEdgeDetectionFilter = [[GPUImageSobelEdgeDetectionFilter alloc] init]; -// [(GPUImageThresholdEdgeDetectionFilter *)thresholdEdgeDetectionFilter setThreshold:0.07]; -// [(GPUImageThresholdEdgeDetectionFilter *)thresholdEdgeDetectionFilter setEdgeStrength:0.25]; -// [(GPUImageThresholdEdgeDetectionFilter *)thresholdEdgeDetectionFilter setEdgeStrength:1.0]; -// thresholdEdgeDetectionFilter = [[GPUImageCannyEdgeDetectionFilter alloc] init]; -// } -// else -// { - thresholdEdgeDetectionFilter = [[GPUImageCannyEdgeDetectionFilter alloc] init]; -// } - [self addFilter:thresholdEdgeDetectionFilter]; - - // Second pass: extract the white points and draw representative lines in parallel coordinate space - parallelCoordinateLineTransformFilter = [[GPUImageParallelCoordinateLineTransformFilter alloc] init]; - [self addFilter:parallelCoordinateLineTransformFilter]; - - // Third pass: apply non-maximum suppression - if ([GPUImageContext deviceSupportsFramebufferReads]) - { - nonMaximumSuppressionFilter = [[GPUImageThresholdedNonMaximumSuppressionFilter alloc] initWithPackedColorspace:YES]; - } - else - { - nonMaximumSuppressionFilter = [[GPUImageThresholdedNonMaximumSuppressionFilter alloc] initWithPackedColorspace:NO]; - } - [self addFilter:nonMaximumSuppressionFilter]; - - __unsafe_unretained GPUImageHoughTransformLineDetector *weakSelf = self; -#ifdef DEBUGLINEDETECTION - _intermediateImages = [[NSMutableArray alloc] init]; - __unsafe_unretained NSMutableArray *weakIntermediateImages = _intermediateImages; - -// __unsafe_unretained GPUImageOutput *weakEdgeDetectionFilter = thresholdEdgeDetectionFilter; -// [thresholdEdgeDetectionFilter setFrameProcessingCompletionBlock:^(GPUImageOutput *filter, CMTime frameTime){ -// [weakIntermediateImages removeAllObjects]; -// UIImage *intermediateImage = [weakEdgeDetectionFilter imageFromCurrentFramebuffer]; -// [weakIntermediateImages addObject:intermediateImage]; -// }]; -// -// __unsafe_unretained GPUImageOutput *weakParallelCoordinateLineTransformFilter = parallelCoordinateLineTransformFilter; -// [parallelCoordinateLineTransformFilter setFrameProcessingCompletionBlock:^(GPUImageOutput *filter, CMTime frameTime){ -// UIImage *intermediateImage = [weakParallelCoordinateLineTransformFilter imageFromCurrentFramebuffer]; -// [weakIntermediateImages addObject:intermediateImage]; -// }]; - - __unsafe_unretained GPUImageOutput *weakNonMaximumSuppressionFilter = nonMaximumSuppressionFilter; - [nonMaximumSuppressionFilter setFrameProcessingCompletionBlock:^(GPUImageOutput *filter, CMTime frameTime){ - UIImage *intermediateImage = [weakNonMaximumSuppressionFilter imageFromCurrentFramebuffer]; - [weakIntermediateImages addObject:intermediateImage]; - - [weakSelf extractLineParametersFromImageAtFrameTime:frameTime]; - }]; -#else - [nonMaximumSuppressionFilter setFrameProcessingCompletionBlock:^(GPUImageOutput *filter, CMTime frameTime) { - [weakSelf extractLineParametersFromImageAtFrameTime:frameTime]; - }]; -#endif - - [thresholdEdgeDetectionFilter addTarget:parallelCoordinateLineTransformFilter]; - [parallelCoordinateLineTransformFilter addTarget:nonMaximumSuppressionFilter]; - - self.initialFilters = [NSArray arrayWithObjects:thresholdEdgeDetectionFilter, nil]; - // self.terminalFilter = colorPackingFilter; - self.terminalFilter = nonMaximumSuppressionFilter; - -// self.edgeThreshold = 0.95; - self.lineDetectionThreshold = 0.12; - - return self; -} - -- (void)dealloc; -{ - free(rawImagePixels); - free(linesArray); -} - -#pragma mark - -#pragma mark Corner extraction - -- (void)extractLineParametersFromImageAtFrameTime:(CMTime)frameTime; -{ - // we need a normal color texture for this filter - NSAssert(self.outputTextureOptions.internalFormat == GL_RGBA, @"The output texture format for this filter must be GL_RGBA."); - NSAssert(self.outputTextureOptions.type == GL_UNSIGNED_BYTE, @"The type of the output texture of this filter must be GL_UNSIGNED_BYTE."); - - NSUInteger numberOfLines = 0; - CGSize imageSize = nonMaximumSuppressionFilter.outputFrameSize; - - unsigned int imageByteSize = imageSize.width * imageSize.height * 4; - - if (rawImagePixels == NULL) - { - rawImagePixels = (GLubyte *)malloc(imageByteSize); - linesArray = calloc(1024 * 2, sizeof(GLfloat)); - } - - glReadPixels(0, 0, (int)imageSize.width, (int)imageSize.height, GL_RGBA, GL_UNSIGNED_BYTE, rawImagePixels); - -// CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); - - unsigned int imageWidth = imageSize.width * 4; - - unsigned int currentByte = 0; - unsigned int cornerStorageIndex = 0; - unsigned long lineStrengthCounter = 0; - while (currentByte < imageByteSize) - { - GLubyte colorByte = rawImagePixels[currentByte]; -// NSLog(@"(%d,%d): [%d,%d,%d,%d]", xCoordinate, yCoordinate, rawImagePixels[currentByte], rawImagePixels[currentByte+1], rawImagePixels[currentByte+2], rawImagePixels[currentByte+3]); -// NSLog(@"[%d,%d,%d,%d]", rawImagePixels[currentByte], rawImagePixels[currentByte+1], rawImagePixels[currentByte+2], rawImagePixels[currentByte+3]); - - if (colorByte > 0) - { - unsigned int xCoordinate = currentByte % imageWidth; - unsigned int yCoordinate = currentByte / imageWidth; - - lineStrengthCounter += colorByte; -// NSLog(@"(%d,%d): [%d,%d,%d,%d]", xCoordinate, yCoordinate, rawImagePixels[currentByte], rawImagePixels[currentByte+1], rawImagePixels[currentByte+2], rawImagePixels[currentByte+3]); - - CGFloat normalizedXCoordinate = -1.0 + 2.0 * (CGFloat)(xCoordinate / 4) / imageSize.width; - CGFloat normalizedYCoordinate = -1.0 + 2.0 * (CGFloat)(yCoordinate) / imageSize.height; - - if (normalizedXCoordinate < 0.0) - { - // T space - // m = -1 - d/u - // b = d * v/u - if (normalizedXCoordinate > -0.05) // Test for the case right near the X axis, stamp the X intercept instead of the Y - { - linesArray[cornerStorageIndex++] = 100000.0; - linesArray[cornerStorageIndex++] = normalizedYCoordinate; - } - else - { - linesArray[cornerStorageIndex++] = -1.0 - 1.0 / normalizedXCoordinate; - linesArray[cornerStorageIndex++] = 1.0 * normalizedYCoordinate / normalizedXCoordinate; - } - } - else - { - // S space - // m = 1 - d/u - // b = d * v/u - if (normalizedXCoordinate < 0.05) // Test for the case right near the X axis, stamp the X intercept instead of the Y - { - linesArray[cornerStorageIndex++] = 100000.0; - linesArray[cornerStorageIndex++] = normalizedYCoordinate; - } - else - { - linesArray[cornerStorageIndex++] = 1.0 - 1.0 / normalizedXCoordinate; - linesArray[cornerStorageIndex++] = 1.0 * normalizedYCoordinate / normalizedXCoordinate; - } - } - - numberOfLines++; - - numberOfLines = MIN(numberOfLines, 1023); - cornerStorageIndex = MIN(cornerStorageIndex, 2040); - } - currentByte +=4; - } - -// CFAbsoluteTime currentFrameTime = (CFAbsoluteTimeGetCurrent() - startTime); -// NSLog(@"Processing time : %f ms", 1000.0 * currentFrameTime); - - if (linesDetectedBlock != NULL) - { - linesDetectedBlock(linesArray, numberOfLines, frameTime); - } -} - -- (BOOL)wantsMonochromeInput; -{ -// return YES; - return NO; -} - -#pragma mark - -#pragma mark Accessors - -//- (void)setEdgeThreshold:(CGFloat)newValue; -//{ -// [(GPUImageCannyEdgeDetectionFilter *)thresholdEdgeDetectionFilter setThreshold:newValue]; -//} -// -//- (CGFloat)edgeThreshold; -//{ -// return [(GPUImageCannyEdgeDetectionFilter *)thresholdEdgeDetectionFilter threshold]; -//} - -- (void)setLineDetectionThreshold:(CGFloat)newValue; -{ - nonMaximumSuppressionFilter.threshold = newValue; -} - -- (CGFloat)lineDetectionThreshold; -{ - return nonMaximumSuppressionFilter.threshold; -} - -#ifdef DEBUGLINEDETECTION -- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex; -{ -// [thresholdEdgeDetectionFilter useNextFrameForImageCapture]; -// [parallelCoordinateLineTransformFilter useNextFrameForImageCapture]; - [nonMaximumSuppressionFilter useNextFrameForImageCapture]; - - [super newFrameReadyAtTime:frameTime atIndex:textureIndex]; -} -#endif - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHueBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHueBlendFilter.h deleted file mode 100644 index 4399ffcf..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHueBlendFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageHueBlendFilter : GPUImageTwoInputFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHueBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHueBlendFilter.m deleted file mode 100644 index f9dfbbb8..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHueBlendFilter.m +++ /dev/null @@ -1,212 +0,0 @@ -#import "GPUImageHueBlendFilter.h" - -/** - * Hue blend mode based upon pseudo code from the PDF specification. - */ -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageHueBlendFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - highp float lum(lowp vec3 c) { - return dot(c, vec3(0.3, 0.59, 0.11)); - } - - lowp vec3 clipcolor(lowp vec3 c) { - highp float l = lum(c); - lowp float n = min(min(c.r, c.g), c.b); - lowp float x = max(max(c.r, c.g), c.b); - - if (n < 0.0) { - c.r = l + ((c.r - l) * l) / (l - n); - c.g = l + ((c.g - l) * l) / (l - n); - c.b = l + ((c.b - l) * l) / (l - n); - } - if (x > 1.0) { - c.r = l + ((c.r - l) * (1.0 - l)) / (x - l); - c.g = l + ((c.g - l) * (1.0 - l)) / (x - l); - c.b = l + ((c.b - l) * (1.0 - l)) / (x - l); - } - - return c; - } - - lowp vec3 setlum(lowp vec3 c, highp float l) { - highp float d = l - lum(c); - c = c + vec3(d); - return clipcolor(c); - } - - highp float sat(lowp vec3 c) { - lowp float n = min(min(c.r, c.g), c.b); - lowp float x = max(max(c.r, c.g), c.b); - return x - n; - } - - lowp float mid(lowp float cmin, lowp float cmid, lowp float cmax, highp float s) { - return ((cmid - cmin) * s) / (cmax - cmin); - } - - lowp vec3 setsat(lowp vec3 c, highp float s) { - if (c.r > c.g) { - if (c.r > c.b) { - if (c.g > c.b) { - /* g is mid, b is min */ - c.g = mid(c.b, c.g, c.r, s); - c.b = 0.0; - } else { - /* b is mid, g is min */ - c.b = mid(c.g, c.b, c.r, s); - c.g = 0.0; - } - c.r = s; - } else { - /* b is max, r is mid, g is min */ - c.r = mid(c.g, c.r, c.b, s); - c.b = s; - c.r = 0.0; - } - } else if (c.r > c.b) { - /* g is max, r is mid, b is min */ - c.r = mid(c.b, c.r, c.g, s); - c.g = s; - c.b = 0.0; - } else if (c.g > c.b) { - /* g is max, b is mid, r is min */ - c.b = mid(c.r, c.b, c.g, s); - c.g = s; - c.r = 0.0; - } else if (c.b > c.g) { - /* b is max, g is mid, r is min */ - c.g = mid(c.r, c.g, c.b, s); - c.b = s; - c.r = 0.0; - } else { - c = vec3(0.0); - } - return c; - } - - void main() - { - highp vec4 baseColor = texture2D(inputImageTexture, textureCoordinate); - highp vec4 overlayColor = texture2D(inputImageTexture2, textureCoordinate2); - - gl_FragColor = vec4(baseColor.rgb * (1.0 - overlayColor.a) + setlum(setsat(overlayColor.rgb, sat(baseColor.rgb)), lum(baseColor.rgb)) * overlayColor.a, baseColor.a); - } -); -#else -NSString *const kGPUImageHueBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - float lum(vec3 c) { - return dot(c, vec3(0.3, 0.59, 0.11)); - } - - vec3 clipcolor(vec3 c) { - float l = lum(c); - float n = min(min(c.r, c.g), c.b); - float x = max(max(c.r, c.g), c.b); - - if (n < 0.0) { - c.r = l + ((c.r - l) * l) / (l - n); - c.g = l + ((c.g - l) * l) / (l - n); - c.b = l + ((c.b - l) * l) / (l - n); - } - if (x > 1.0) { - c.r = l + ((c.r - l) * (1.0 - l)) / (x - l); - c.g = l + ((c.g - l) * (1.0 - l)) / (x - l); - c.b = l + ((c.b - l) * (1.0 - l)) / (x - l); - } - - return c; - } - - vec3 setlum(vec3 c, float l) { - float d = l - lum(c); - c = c + vec3(d); - return clipcolor(c); - } - - float sat(vec3 c) { - float n = min(min(c.r, c.g), c.b); - float x = max(max(c.r, c.g), c.b); - return x - n; - } - - float mid(float cmin, float cmid, float cmax, float s) { - return ((cmid - cmin) * s) / (cmax - cmin); - } - - vec3 setsat(vec3 c, float s) { - if (c.r > c.g) { - if (c.r > c.b) { - if (c.g > c.b) { - /* g is mid, b is min */ - c.g = mid(c.b, c.g, c.r, s); - c.b = 0.0; - } else { - /* b is mid, g is min */ - c.b = mid(c.g, c.b, c.r, s); - c.g = 0.0; - } - c.r = s; - } else { - /* b is max, r is mid, g is min */ - c.r = mid(c.g, c.r, c.b, s); - c.b = s; - c.r = 0.0; - } - } else if (c.r > c.b) { - /* g is max, r is mid, b is min */ - c.r = mid(c.b, c.r, c.g, s); - c.g = s; - c.b = 0.0; - } else if (c.g > c.b) { - /* g is max, b is mid, r is min */ - c.b = mid(c.r, c.b, c.g, s); - c.g = s; - c.r = 0.0; - } else if (c.b > c.g) { - /* b is max, g is mid, r is min */ - c.g = mid(c.r, c.g, c.b, s); - c.b = s; - c.r = 0.0; - } else { - c = vec3(0.0); - } - return c; - } - - void main() - { - vec4 baseColor = texture2D(inputImageTexture, textureCoordinate); - vec4 overlayColor = texture2D(inputImageTexture2, textureCoordinate2); - - gl_FragColor = vec4(baseColor.rgb * (1.0 - overlayColor.a) + setlum(setsat(overlayColor.rgb, sat(baseColor.rgb)), lum(baseColor.rgb)) * overlayColor.a, baseColor.a); - } -); -#endif - -@implementation GPUImageHueBlendFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageHueBlendFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHueFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHueFilter.h deleted file mode 100644 index eef24651..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHueFilter.h +++ /dev/null @@ -1,11 +0,0 @@ - -#import "GPUImageFilter.h" - -@interface GPUImageHueFilter : GPUImageFilter -{ - GLint hueAdjustUniform; - -} -@property (nonatomic, readwrite) CGFloat hue; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHueFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHueFilter.m deleted file mode 100644 index 5b42c86d..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageHueFilter.m +++ /dev/null @@ -1,123 +0,0 @@ - -#import "GPUImageHueFilter.h" - -// Adapted from http://stackoverflow.com/questions/9234724/how-to-change-hue-of-a-texture-with-glsl - see for code and discussion -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageHueFragmentShaderString = SHADER_STRING -( - precision highp float; - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform mediump float hueAdjust; - const highp vec4 kRGBToYPrime = vec4 (0.299, 0.587, 0.114, 0.0); - const highp vec4 kRGBToI = vec4 (0.595716, -0.274453, -0.321263, 0.0); - const highp vec4 kRGBToQ = vec4 (0.211456, -0.522591, 0.31135, 0.0); - - const highp vec4 kYIQToR = vec4 (1.0, 0.9563, 0.6210, 0.0); - const highp vec4 kYIQToG = vec4 (1.0, -0.2721, -0.6474, 0.0); - const highp vec4 kYIQToB = vec4 (1.0, -1.1070, 1.7046, 0.0); - - void main () - { - // Sample the input pixel - highp vec4 color = texture2D(inputImageTexture, textureCoordinate); - - // Convert to YIQ - highp float YPrime = dot (color, kRGBToYPrime); - highp float I = dot (color, kRGBToI); - highp float Q = dot (color, kRGBToQ); - - // Calculate the hue and chroma - highp float hue = atan (Q, I); - highp float chroma = sqrt (I * I + Q * Q); - - // Make the user's adjustments - hue += (-hueAdjust); //why negative rotation? - - // Convert back to YIQ - Q = chroma * sin (hue); - I = chroma * cos (hue); - - // Convert back to RGB - highp vec4 yIQ = vec4 (YPrime, I, Q, 0.0); - color.r = dot (yIQ, kYIQToR); - color.g = dot (yIQ, kYIQToG); - color.b = dot (yIQ, kYIQToB); - - // Save the result - gl_FragColor = color; - } -); -#else -NSString *const kGPUImageHueFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float hueAdjust; - const vec4 kRGBToYPrime = vec4 (0.299, 0.587, 0.114, 0.0); - const vec4 kRGBToI = vec4 (0.595716, -0.274453, -0.321263, 0.0); - const vec4 kRGBToQ = vec4 (0.211456, -0.522591, 0.31135, 0.0); - - const vec4 kYIQToR = vec4 (1.0, 0.9563, 0.6210, 0.0); - const vec4 kYIQToG = vec4 (1.0, -0.2721, -0.6474, 0.0); - const vec4 kYIQToB = vec4 (1.0, -1.1070, 1.7046, 0.0); - - void main () - { - // Sample the input pixel - vec4 color = texture2D(inputImageTexture, textureCoordinate); - - // Convert to YIQ - float YPrime = dot (color, kRGBToYPrime); - float I = dot (color, kRGBToI); - float Q = dot (color, kRGBToQ); - - // Calculate the hue and chroma - float hue = atan (Q, I); - float chroma = sqrt (I * I + Q * Q); - - // Make the user's adjustments - hue += (-hueAdjust); //why negative rotation? - - // Convert back to YIQ - Q = chroma * sin (hue); - I = chroma * cos (hue); - - // Convert back to RGB - vec4 yIQ = vec4 (YPrime, I, Q, 0.0); - color.r = dot (yIQ, kYIQToR); - color.g = dot (yIQ, kYIQToG); - color.b = dot (yIQ, kYIQToB); - - // Save the result - gl_FragColor = color; - } -); -#endif - -@implementation GPUImageHueFilter -@synthesize hue; - -- (id)init -{ - if(! (self = [super initWithFragmentShaderFromString:kGPUImageHueFragmentShaderString]) ) - { - return nil; - } - - hueAdjustUniform = [filterProgram uniformIndex:@"hueAdjust"]; - self.hue = 90; - - return self; -} - -- (void)setHue:(CGFloat)newHue -{ - // Convert degrees to radians for hue rotation - hue = fmodf(newHue, 360.0) * M_PI/180; - [self setFloat:hue forUniform:hueAdjustUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageJFAVoronoiFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageJFAVoronoiFilter.h deleted file mode 100644 index 4c50cc37..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageJFAVoronoiFilter.h +++ /dev/null @@ -1,17 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageJFAVoronoiFilter : GPUImageFilter -{ - GLuint secondFilterOutputTexture; - GLuint secondFilterFramebuffer; - - - GLint sampleStepUniform; - GLint sizeUniform; - NSUInteger numPasses; - -} - -@property (nonatomic, readwrite) CGSize sizeInPixels; - -@end \ No newline at end of file diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageJFAVoronoiFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageJFAVoronoiFilter.m deleted file mode 100644 index 15835917..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageJFAVoronoiFilter.m +++ /dev/null @@ -1,446 +0,0 @@ -// adapted from unitzeroone - http://unitzeroone.com/labs/jfavoronoi/ - -#import "GPUImageJFAVoronoiFilter.h" - -// The shaders are mostly taken from UnitZeroOne's WebGL example here: -// http://unitzeroone.com/blog/2011/03/22/jump-flood-voronoi-for-webgl/ - -NSString *const kGPUImageJFAVoronoiVertexShaderString = SHADER_STRING -( - attribute vec4 position; - attribute vec4 inputTextureCoordinate; - - uniform float sampleStep; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - void main() - { - gl_Position = position; - - vec2 widthStep = vec2(sampleStep, 0.0); - vec2 heightStep = vec2(0.0, sampleStep); - vec2 widthHeightStep = vec2(sampleStep); - vec2 widthNegativeHeightStep = vec2(sampleStep, -sampleStep); - - textureCoordinate = inputTextureCoordinate.xy; - leftTextureCoordinate = inputTextureCoordinate.xy - widthStep; - rightTextureCoordinate = inputTextureCoordinate.xy + widthStep; - - topTextureCoordinate = inputTextureCoordinate.xy - heightStep; - topLeftTextureCoordinate = inputTextureCoordinate.xy - widthHeightStep; - topRightTextureCoordinate = inputTextureCoordinate.xy + widthNegativeHeightStep; - - bottomTextureCoordinate = inputTextureCoordinate.xy + heightStep; - bottomLeftTextureCoordinate = inputTextureCoordinate.xy - widthNegativeHeightStep; - bottomRightTextureCoordinate = inputTextureCoordinate.xy + widthHeightStep; - } - ); - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageJFAVoronoiFragmentShaderString = SHADER_STRING -( - - precision highp float; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - uniform vec2 size; - //varying vec2 textureCoordinate; - //uniform float sampleStep; - - vec2 getCoordFromColor(vec4 color) -{ - float z = color.z * 256.0; - float yoff = floor(z / 8.0); - float xoff = mod(z, 8.0); - float x = color.x*256.0 + xoff*256.0; - float y = color.y*256.0 + yoff*256.0; - return vec2(x,y) / size; -} - - void main(void) { - - vec2 sub; - vec4 dst; - vec4 local = texture2D(inputImageTexture, textureCoordinate); - vec4 sam; - float l; - float smallestDist; - if(local.a == 0.0){ - - smallestDist = dot(1.0,1.0); - }else{ - sub = getCoordFromColor(local)-textureCoordinate; - smallestDist = dot(sub,sub); - } - dst = local; - - - sam = texture2D(inputImageTexture, topRightTextureCoordinate); - if(sam.a == 1.0){ - sub = (getCoordFromColor(sam)-textureCoordinate); - l = dot(sub,sub); - if(l < smallestDist){ - smallestDist = l; - dst = sam; - } - } - - sam = texture2D(inputImageTexture, topTextureCoordinate); - if(sam.a == 1.0){ - sub = (getCoordFromColor(sam)-textureCoordinate); - l = dot(sub,sub); - if(l < smallestDist){ - smallestDist = l; - dst = sam; - } - } - - sam = texture2D(inputImageTexture, topLeftTextureCoordinate); - if(sam.a == 1.0){ - sub = (getCoordFromColor(sam)-textureCoordinate); - l = dot(sub,sub); - if(l < smallestDist){ - smallestDist = l; - dst = sam; - } - } - - sam = texture2D(inputImageTexture, bottomRightTextureCoordinate); - if(sam.a == 1.0){ - sub = (getCoordFromColor(sam)-textureCoordinate); - l = dot(sub,sub); - if(l < smallestDist){ - smallestDist = l; - dst = sam; - } - } - - sam = texture2D(inputImageTexture, bottomTextureCoordinate); - if(sam.a == 1.0){ - sub = (getCoordFromColor(sam)-textureCoordinate); - l = dot(sub,sub); - if(l < smallestDist){ - smallestDist = l; - dst = sam; - } - } - - sam = texture2D(inputImageTexture, bottomLeftTextureCoordinate); - if(sam.a == 1.0){ - sub = (getCoordFromColor(sam)-textureCoordinate); - l = dot(sub,sub); - if(l < smallestDist){ - smallestDist = l; - dst = sam; - } - } - - sam = texture2D(inputImageTexture, leftTextureCoordinate); - if(sam.a == 1.0){ - sub = (getCoordFromColor(sam)-textureCoordinate); - l = dot(sub,sub); - if(l < smallestDist){ - smallestDist = l; - dst = sam; - } - } - - sam = texture2D(inputImageTexture, rightTextureCoordinate); - if(sam.a == 1.0){ - sub = (getCoordFromColor(sam)-textureCoordinate); - l = dot(sub,sub); - if(l < smallestDist){ - smallestDist = l; - dst = sam; - } - } - gl_FragColor = dst; - } -); -#else -NSString *const kGPUImageJFAVoronoiFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - uniform vec2 size; - //varying vec2 textureCoordinate; - //uniform float sampleStep; - - vec2 getCoordFromColor(vec4 color) -{ - float z = color.z * 256.0; - float yoff = floor(z / 8.0); - float xoff = mod(z, 8.0); - float x = color.x*256.0 + xoff*256.0; - float y = color.y*256.0 + yoff*256.0; - return vec2(x,y) / size; -} - - void main(void) { - - vec2 sub; - vec4 dst; - vec4 local = texture2D(inputImageTexture, textureCoordinate); - vec4 sam; - float l; - float smallestDist; - if(local.a == 0.0){ - - smallestDist = dot(1.0,1.0); - }else{ - sub = getCoordFromColor(local)-textureCoordinate; - smallestDist = dot(sub,sub); - } - dst = local; - - - sam = texture2D(inputImageTexture, topRightTextureCoordinate); - if(sam.a == 1.0){ - sub = (getCoordFromColor(sam)-textureCoordinate); - l = dot(sub,sub); - if(l < smallestDist){ - smallestDist = l; - dst = sam; - } - } - - sam = texture2D(inputImageTexture, topTextureCoordinate); - if(sam.a == 1.0){ - sub = (getCoordFromColor(sam)-textureCoordinate); - l = dot(sub,sub); - if(l < smallestDist){ - smallestDist = l; - dst = sam; - } - } - - sam = texture2D(inputImageTexture, topLeftTextureCoordinate); - if(sam.a == 1.0){ - sub = (getCoordFromColor(sam)-textureCoordinate); - l = dot(sub,sub); - if(l < smallestDist){ - smallestDist = l; - dst = sam; - } - } - - sam = texture2D(inputImageTexture, bottomRightTextureCoordinate); - if(sam.a == 1.0){ - sub = (getCoordFromColor(sam)-textureCoordinate); - l = dot(sub,sub); - if(l < smallestDist){ - smallestDist = l; - dst = sam; - } - } - - sam = texture2D(inputImageTexture, bottomTextureCoordinate); - if(sam.a == 1.0){ - sub = (getCoordFromColor(sam)-textureCoordinate); - l = dot(sub,sub); - if(l < smallestDist){ - smallestDist = l; - dst = sam; - } - } - - sam = texture2D(inputImageTexture, bottomLeftTextureCoordinate); - if(sam.a == 1.0){ - sub = (getCoordFromColor(sam)-textureCoordinate); - l = dot(sub,sub); - if(l < smallestDist){ - smallestDist = l; - dst = sam; - } - } - - sam = texture2D(inputImageTexture, leftTextureCoordinate); - if(sam.a == 1.0){ - sub = (getCoordFromColor(sam)-textureCoordinate); - l = dot(sub,sub); - if(l < smallestDist){ - smallestDist = l; - dst = sam; - } - } - - sam = texture2D(inputImageTexture, rightTextureCoordinate); - if(sam.a == 1.0){ - sub = (getCoordFromColor(sam)-textureCoordinate); - l = dot(sub,sub); - if(l < smallestDist){ - smallestDist = l; - dst = sam; - } - } - gl_FragColor = dst; - } -); -#endif - -@interface GPUImageJFAVoronoiFilter() { - int currentPass; -} - - -@end - -@implementation GPUImageJFAVoronoiFilter - -@synthesize sizeInPixels = _sizeInPixels; - -- (id)init; -{ - if (!(self = [super initWithVertexShaderFromString:kGPUImageJFAVoronoiVertexShaderString fragmentShaderFromString:kGPUImageJFAVoronoiFragmentShaderString])) - { - - NSLog(@"nil returned"); - return nil; - - } - - sampleStepUniform = [filterProgram uniformIndex:@"sampleStep"]; - sizeUniform = [filterProgram uniformIndex:@"size"]; - //[self disableSecondFrameCheck]; - - return self; -} - --(void)setSizeInPixels:(CGSize)sizeInPixels { - _sizeInPixels = sizeInPixels; - - //validate that it's a power of 2 - - float width = log2(sizeInPixels.width); - float height = log2(sizeInPixels.height); - - if (width != height) { - NSLog(@"Voronoi point texture must be square"); - return; - } - if (width != floor(width) || height != floor(height)) { - NSLog(@"Voronoi point texture must be a power of 2. Texture size: %f, %f", sizeInPixels.width, sizeInPixels.height); - return; - } - glUniform2f(sizeUniform, _sizeInPixels.width, _sizeInPixels.height); -} - -#pragma mark - -#pragma mark Managing the display FBOs - --(NSUInteger)nextPowerOfTwo:(CGPoint)input { - NSUInteger val; - if (input.x > input.y) { - val = (NSUInteger)input.x; - } else { - val = (NSUInteger)input.y; - } - - val--; - val = (val >> 1) | val; - val = (val >> 2) | val; - val = (val >> 4) | val; - val = (val >> 8) | val; - val = (val >> 16) | val; - val++; - return val; -} - -//- (void)setOutputFBO; -//{ -// if (currentPass % 2 == 1) { -// [self setSecondFilterFBO]; -// } else { -// [self setFilterFBO]; -// } -// -//} - -- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates; -{ - // Run the first stage of the two-pass filter - [GPUImageContext setActiveShaderProgram:filterProgram]; - currentPass = 0; - - outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:[self sizeOfFBO] textureOptions:self.outputTextureOptions onlyTexture:NO]; - [outputFramebuffer activateFramebuffer]; - - glActiveTexture(GL_TEXTURE2); - - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - - glUniform1f(sampleStepUniform, 0.5); - - glUniform2f(sizeUniform, _sizeInPixels.width, _sizeInPixels.height); - - glBindTexture(GL_TEXTURE_2D, [firstInputFramebuffer texture]); - - glUniform1i(filterInputTextureUniform, 2); - - glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, vertices); - glVertexAttribPointer(filterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - for (int pass = 1; pass <= numPasses + 1; pass++) { - currentPass = pass; -// [self setOutputFBO]; - - //glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - - glActiveTexture(GL_TEXTURE2); - if (pass % 2 == 0) { - glBindTexture(GL_TEXTURE_2D, secondFilterOutputTexture); - } else { - glBindTexture(GL_TEXTURE_2D, [outputFramebuffer texture]); - } - glUniform1i(filterInputTextureUniform, 2); - - float step = pow(2.0, numPasses - pass) / pow(2.0, numPasses); - glUniform1f(sampleStepUniform, step); - glUniform2f(sizeUniform, _sizeInPixels.width, _sizeInPixels.height); - - glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, vertices); - glVertexAttribPointer(filterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - } -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageKuwaharaFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageKuwaharaFilter.h deleted file mode 100755 index 4fb0bce8..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageKuwaharaFilter.h +++ /dev/null @@ -1,13 +0,0 @@ -#import "GPUImageFilter.h" - -/** Kuwahara image abstraction, drawn from the work of Kyprianidis, et. al. in their publication "Anisotropic Kuwahara Filtering on the GPU" within the GPU Pro collection. This produces an oil-painting-like image, but it is extremely computationally expensive, so it can take seconds to render a frame on an iPad 2. This might be best used for still images. - */ -@interface GPUImageKuwaharaFilter : GPUImageFilter -{ - GLint radiusUniform; -} - -/// The radius to sample from when creating the brush-stroke effect, with a default of 3. The larger the radius, the slower the filter. -@property(readwrite, nonatomic) NSUInteger radius; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageKuwaharaFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageKuwaharaFilter.m deleted file mode 100755 index 9061dbf3..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageKuwaharaFilter.m +++ /dev/null @@ -1,223 +0,0 @@ -#import "GPUImageKuwaharaFilter.h" - -// Sourced from Kyprianidis, J. E., Kang, H., and Doellner, J. "Anisotropic Kuwahara Filtering on the GPU," GPU Pro p.247 (2010). -// -// Original header: -// -// Anisotropic Kuwahara Filtering on the GPU -// by Jan Eric Kyprianidis - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageKuwaharaFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - uniform sampler2D inputImageTexture; - uniform int radius; - - precision highp float; - - const vec2 src_size = vec2 (1.0 / 768.0, 1.0 / 1024.0); - - void main (void) - { - vec2 uv = textureCoordinate; - float n = float((radius + 1) * (radius + 1)); - int i; int j; - vec3 m0 = vec3(0.0); vec3 m1 = vec3(0.0); vec3 m2 = vec3(0.0); vec3 m3 = vec3(0.0); - vec3 s0 = vec3(0.0); vec3 s1 = vec3(0.0); vec3 s2 = vec3(0.0); vec3 s3 = vec3(0.0); - vec3 c; - - for (j = -radius; j <= 0; ++j) { - for (i = -radius; i <= 0; ++i) { - c = texture2D(inputImageTexture, uv + vec2(i,j) * src_size).rgb; - m0 += c; - s0 += c * c; - } - } - - for (j = -radius; j <= 0; ++j) { - for (i = 0; i <= radius; ++i) { - c = texture2D(inputImageTexture, uv + vec2(i,j) * src_size).rgb; - m1 += c; - s1 += c * c; - } - } - - for (j = 0; j <= radius; ++j) { - for (i = 0; i <= radius; ++i) { - c = texture2D(inputImageTexture, uv + vec2(i,j) * src_size).rgb; - m2 += c; - s2 += c * c; - } - } - - for (j = 0; j <= radius; ++j) { - for (i = -radius; i <= 0; ++i) { - c = texture2D(inputImageTexture, uv + vec2(i,j) * src_size).rgb; - m3 += c; - s3 += c * c; - } - } - - - float min_sigma2 = 1e+2; - m0 /= n; - s0 = abs(s0 / n - m0 * m0); - - float sigma2 = s0.r + s0.g + s0.b; - if (sigma2 < min_sigma2) { - min_sigma2 = sigma2; - gl_FragColor = vec4(m0, 1.0); - } - - m1 /= n; - s1 = abs(s1 / n - m1 * m1); - - sigma2 = s1.r + s1.g + s1.b; - if (sigma2 < min_sigma2) { - min_sigma2 = sigma2; - gl_FragColor = vec4(m1, 1.0); - } - - m2 /= n; - s2 = abs(s2 / n - m2 * m2); - - sigma2 = s2.r + s2.g + s2.b; - if (sigma2 < min_sigma2) { - min_sigma2 = sigma2; - gl_FragColor = vec4(m2, 1.0); - } - - m3 /= n; - s3 = abs(s3 / n - m3 * m3); - - sigma2 = s3.r + s3.g + s3.b; - if (sigma2 < min_sigma2) { - min_sigma2 = sigma2; - gl_FragColor = vec4(m3, 1.0); - } - } -); -#else -NSString *const kGPUImageKuwaharaFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - uniform sampler2D inputImageTexture; - uniform int radius; - - const vec2 src_size = vec2 (1.0 / 768.0, 1.0 / 1024.0); - - void main (void) - { - vec2 uv = textureCoordinate; - float n = float((radius + 1) * (radius + 1)); - int i; int j; - vec3 m0 = vec3(0.0); vec3 m1 = vec3(0.0); vec3 m2 = vec3(0.0); vec3 m3 = vec3(0.0); - vec3 s0 = vec3(0.0); vec3 s1 = vec3(0.0); vec3 s2 = vec3(0.0); vec3 s3 = vec3(0.0); - vec3 c; - - for (j = -radius; j <= 0; ++j) { - for (i = -radius; i <= 0; ++i) { - c = texture2D(inputImageTexture, uv + vec2(i,j) * src_size).rgb; - m0 += c; - s0 += c * c; - } - } - - for (j = -radius; j <= 0; ++j) { - for (i = 0; i <= radius; ++i) { - c = texture2D(inputImageTexture, uv + vec2(i,j) * src_size).rgb; - m1 += c; - s1 += c * c; - } - } - - for (j = 0; j <= radius; ++j) { - for (i = 0; i <= radius; ++i) { - c = texture2D(inputImageTexture, uv + vec2(i,j) * src_size).rgb; - m2 += c; - s2 += c * c; - } - } - - for (j = 0; j <= radius; ++j) { - for (i = -radius; i <= 0; ++i) { - c = texture2D(inputImageTexture, uv + vec2(i,j) * src_size).rgb; - m3 += c; - s3 += c * c; - } - } - - - float min_sigma2 = 1e+2; - m0 /= n; - s0 = abs(s0 / n - m0 * m0); - - float sigma2 = s0.r + s0.g + s0.b; - if (sigma2 < min_sigma2) { - min_sigma2 = sigma2; - gl_FragColor = vec4(m0, 1.0); - } - - m1 /= n; - s1 = abs(s1 / n - m1 * m1); - - sigma2 = s1.r + s1.g + s1.b; - if (sigma2 < min_sigma2) { - min_sigma2 = sigma2; - gl_FragColor = vec4(m1, 1.0); - } - - m2 /= n; - s2 = abs(s2 / n - m2 * m2); - - sigma2 = s2.r + s2.g + s2.b; - if (sigma2 < min_sigma2) { - min_sigma2 = sigma2; - gl_FragColor = vec4(m2, 1.0); - } - - m3 /= n; - s3 = abs(s3 / n - m3 * m3); - - sigma2 = s3.r + s3.g + s3.b; - if (sigma2 < min_sigma2) { - min_sigma2 = sigma2; - gl_FragColor = vec4(m3, 1.0); - } - } -); -#endif - -@implementation GPUImageKuwaharaFilter - -@synthesize radius = _radius; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageKuwaharaFragmentShaderString])) - { - return nil; - } - - radiusUniform = [filterProgram uniformIndex:@"radius"]; - - self.radius = 3; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setRadius:(NSUInteger)newValue; -{ - _radius = newValue; - - [self setInteger:(GLint)_radius forUniform:radiusUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageKuwaharaRadius3Filter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageKuwaharaRadius3Filter.h deleted file mode 100644 index c4591b81..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageKuwaharaRadius3Filter.h +++ /dev/null @@ -1,8 +0,0 @@ -// -// GPUImageKuwaharaRadius3Filter.h - -#import "GPUImageFilter.h" - -@interface GPUImageKuwaharaRadius3Filter : GPUImageFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageKuwaharaRadius3Filter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageKuwaharaRadius3Filter.m deleted file mode 100644 index 98b092c6..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageKuwaharaRadius3Filter.m +++ /dev/null @@ -1,547 +0,0 @@ -#import "GPUImageKuwaharaRadius3Filter.h" - -// Sourced from Kyprianidis, J. E., Kang, H., and Doellner, J. "Anisotropic Kuwahara Filtering on the GPU," GPU Pro p.247 (2010). -// -// Original header: -// -// Anisotropic Kuwahara Filtering on the GPU -// by Jan Eric Kyprianidis - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageKuwaharaRadius3FragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - uniform sampler2D inputImageTexture; - - precision highp float; - - const vec2 src_size = vec2 (1.0 / 768.0, 1.0 / 1024.0); - - void main (void) - { - vec2 uv = textureCoordinate; - float n = float(16); // radius is assumed to be 3 - vec3 m0 = vec3(0.0); vec3 m1 = vec3(0.0); vec3 m2 = vec3(0.0); vec3 m3 = vec3(0.0); - vec3 s0 = vec3(0.0); vec3 s1 = vec3(0.0); vec3 s2 = vec3(0.0); vec3 s3 = vec3(0.0); - vec3 c; - vec3 cSq; - - c = texture2D(inputImageTexture, uv + vec2(-3,-3) * src_size).rgb; - m0 += c; - s0 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-3,-2) * src_size).rgb; - m0 += c; - s0 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-3,-1) * src_size).rgb; - m0 += c; - s0 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-3,0) * src_size).rgb; - cSq = c * c; - m0 += c; - s0 += cSq; - m1 += c; - s1 += cSq; - - c = texture2D(inputImageTexture, uv + vec2(-2,-3) * src_size).rgb; - m0 += c; - s0 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-2,-2) * src_size).rgb; - m0 += c; - s0 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-2,-1) * src_size).rgb; - m0 += c; - s0 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-2,0) * src_size).rgb; - cSq = c * c; - m0 += c; - s0 += cSq; - m1 += c; - s1 += cSq; - - c = texture2D(inputImageTexture, uv + vec2(-1,-3) * src_size).rgb; - m0 += c; - s0 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-1,-2) * src_size).rgb; - m0 += c; - s0 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-1,-1) * src_size).rgb; - m0 += c; - s0 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-1,0) * src_size).rgb; - cSq = c * c; - m0 += c; - s0 += cSq; - m1 += c; - s1 += cSq; - - c = texture2D(inputImageTexture, uv + vec2(0,-3) * src_size).rgb; - cSq = c * c; - m0 += c; - s0 += cSq; - m3 += c; - s3 += cSq; - c = texture2D(inputImageTexture, uv + vec2(0,-2) * src_size).rgb; - cSq = c * c; - m0 += c; - s0 += cSq; - m3 += c; - s3 += cSq; - c = texture2D(inputImageTexture, uv + vec2(0,-1) * src_size).rgb; - cSq = c * c; - m0 += c; - s0 += cSq; - m3 += c; - s3 += cSq; - c = texture2D(inputImageTexture, uv + vec2(0,0) * src_size).rgb; - cSq = c * c; - m0 += c; - s0 += cSq; - m1 += c; - s1 += cSq; - m2 += c; - s2 += cSq; - m3 += c; - s3 += cSq; - - c = texture2D(inputImageTexture, uv + vec2(-3,3) * src_size).rgb; - m1 += c; - s1 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-3,2) * src_size).rgb; - m1 += c; - s1 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-3,1) * src_size).rgb; - m1 += c; - s1 += c * c; - - c = texture2D(inputImageTexture, uv + vec2(-2,3) * src_size).rgb; - m1 += c; - s1 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-2,2) * src_size).rgb; - m1 += c; - s1 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-2,1) * src_size).rgb; - m1 += c; - s1 += c * c; - - c = texture2D(inputImageTexture, uv + vec2(-1,3) * src_size).rgb; - m1 += c; - s1 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-1,2) * src_size).rgb; - m1 += c; - s1 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-1,1) * src_size).rgb; - m1 += c; - s1 += c * c; - - c = texture2D(inputImageTexture, uv + vec2(0,3) * src_size).rgb; - cSq = c * c; - m1 += c; - s1 += cSq; - m2 += c; - s2 += cSq; - c = texture2D(inputImageTexture, uv + vec2(0,2) * src_size).rgb; - cSq = c * c; - m1 += c; - s1 += cSq; - m2 += c; - s2 += cSq; - c = texture2D(inputImageTexture, uv + vec2(0,1) * src_size).rgb; - cSq = c * c; - m1 += c; - s1 += cSq; - m2 += c; - s2 += cSq; - - c = texture2D(inputImageTexture, uv + vec2(3,3) * src_size).rgb; - m2 += c; - s2 += c * c; - c = texture2D(inputImageTexture, uv + vec2(3,2) * src_size).rgb; - m2 += c; - s2 += c * c; - c = texture2D(inputImageTexture, uv + vec2(3,1) * src_size).rgb; - m2 += c; - s2 += c * c; - c = texture2D(inputImageTexture, uv + vec2(3,0) * src_size).rgb; - cSq = c * c; - m2 += c; - s2 += cSq; - m3 += c; - s3 += cSq; - - c = texture2D(inputImageTexture, uv + vec2(2,3) * src_size).rgb; - m2 += c; - s2 += c * c; - c = texture2D(inputImageTexture, uv + vec2(2,2) * src_size).rgb; - m2 += c; - s2 += c * c; - c = texture2D(inputImageTexture, uv + vec2(2,1) * src_size).rgb; - m2 += c; - s2 += c * c; - c = texture2D(inputImageTexture, uv + vec2(2,0) * src_size).rgb; - cSq = c * c; - m2 += c; - s2 += cSq; - m3 += c; - s3 += cSq; - - c = texture2D(inputImageTexture, uv + vec2(1,3) * src_size).rgb; - m2 += c; - s2 += c * c; - c = texture2D(inputImageTexture, uv + vec2(1,2) * src_size).rgb; - m2 += c; - s2 += c * c; - c = texture2D(inputImageTexture, uv + vec2(1,1) * src_size).rgb; - m2 += c; - s2 += c * c; - c = texture2D(inputImageTexture, uv + vec2(1,0) * src_size).rgb; - cSq = c * c; - m2 += c; - s2 += cSq; - m3 += c; - s3 += cSq; - - c = texture2D(inputImageTexture, uv + vec2(3,-3) * src_size).rgb; - m3 += c; - s3 += c * c; - c = texture2D(inputImageTexture, uv + vec2(3,-2) * src_size).rgb; - m3 += c; - s3 += c * c; - c = texture2D(inputImageTexture, uv + vec2(3,-1) * src_size).rgb; - m3 += c; - s3 += c * c; - - c = texture2D(inputImageTexture, uv + vec2(2,-3) * src_size).rgb; - m3 += c; - s3 += c * c; - c = texture2D(inputImageTexture, uv + vec2(2,-2) * src_size).rgb; - m3 += c; - s3 += c * c; - c = texture2D(inputImageTexture, uv + vec2(2,-1) * src_size).rgb; - m3 += c; - s3 += c * c; - - c = texture2D(inputImageTexture, uv + vec2(1,-3) * src_size).rgb; - m3 += c; - s3 += c * c; - c = texture2D(inputImageTexture, uv + vec2(1,-2) * src_size).rgb; - m3 += c; - s3 += c * c; - c = texture2D(inputImageTexture, uv + vec2(1,-1) * src_size).rgb; - m3 += c; - s3 += c * c; - - float min_sigma2 = 1e+2; - m0 /= n; - s0 = abs(s0 / n - m0 * m0); - - float sigma2 = s0.r + s0.g + s0.b; - if (sigma2 < min_sigma2) { - min_sigma2 = sigma2; - gl_FragColor = vec4(m0, 1.0); - } - - m1 /= n; - s1 = abs(s1 / n - m1 * m1); - - sigma2 = s1.r + s1.g + s1.b; - if (sigma2 < min_sigma2) { - min_sigma2 = sigma2; - gl_FragColor = vec4(m1, 1.0); - } - - m2 /= n; - s2 = abs(s2 / n - m2 * m2); - - sigma2 = s2.r + s2.g + s2.b; - if (sigma2 < min_sigma2) { - min_sigma2 = sigma2; - gl_FragColor = vec4(m2, 1.0); - } - - m3 /= n; - s3 = abs(s3 / n - m3 * m3); - - sigma2 = s3.r + s3.g + s3.b; - if (sigma2 < min_sigma2) { - min_sigma2 = sigma2; - gl_FragColor = vec4(m3, 1.0); - } - } -); -#else -NSString *const kGPUImageKuwaharaRadius3FragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - uniform sampler2D inputImageTexture; - - const vec2 src_size = vec2 (1.0 / 768.0, 1.0 / 1024.0); - - void main (void) - { - vec2 uv = textureCoordinate; - float n = float(16); // radius is assumed to be 3 - vec3 m0 = vec3(0.0); vec3 m1 = vec3(0.0); vec3 m2 = vec3(0.0); vec3 m3 = vec3(0.0); - vec3 s0 = vec3(0.0); vec3 s1 = vec3(0.0); vec3 s2 = vec3(0.0); vec3 s3 = vec3(0.0); - vec3 c; - vec3 cSq; - - c = texture2D(inputImageTexture, uv + vec2(-3,-3) * src_size).rgb; - m0 += c; - s0 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-3,-2) * src_size).rgb; - m0 += c; - s0 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-3,-1) * src_size).rgb; - m0 += c; - s0 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-3,0) * src_size).rgb; - cSq = c * c; - m0 += c; - s0 += cSq; - m1 += c; - s1 += cSq; - - c = texture2D(inputImageTexture, uv + vec2(-2,-3) * src_size).rgb; - m0 += c; - s0 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-2,-2) * src_size).rgb; - m0 += c; - s0 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-2,-1) * src_size).rgb; - m0 += c; - s0 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-2,0) * src_size).rgb; - cSq = c * c; - m0 += c; - s0 += cSq; - m1 += c; - s1 += cSq; - - c = texture2D(inputImageTexture, uv + vec2(-1,-3) * src_size).rgb; - m0 += c; - s0 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-1,-2) * src_size).rgb; - m0 += c; - s0 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-1,-1) * src_size).rgb; - m0 += c; - s0 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-1,0) * src_size).rgb; - cSq = c * c; - m0 += c; - s0 += cSq; - m1 += c; - s1 += cSq; - - c = texture2D(inputImageTexture, uv + vec2(0,-3) * src_size).rgb; - cSq = c * c; - m0 += c; - s0 += cSq; - m3 += c; - s3 += cSq; - c = texture2D(inputImageTexture, uv + vec2(0,-2) * src_size).rgb; - cSq = c * c; - m0 += c; - s0 += cSq; - m3 += c; - s3 += cSq; - c = texture2D(inputImageTexture, uv + vec2(0,-1) * src_size).rgb; - cSq = c * c; - m0 += c; - s0 += cSq; - m3 += c; - s3 += cSq; - c = texture2D(inputImageTexture, uv + vec2(0,0) * src_size).rgb; - cSq = c * c; - m0 += c; - s0 += cSq; - m1 += c; - s1 += cSq; - m2 += c; - s2 += cSq; - m3 += c; - s3 += cSq; - - c = texture2D(inputImageTexture, uv + vec2(-3,3) * src_size).rgb; - m1 += c; - s1 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-3,2) * src_size).rgb; - m1 += c; - s1 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-3,1) * src_size).rgb; - m1 += c; - s1 += c * c; - - c = texture2D(inputImageTexture, uv + vec2(-2,3) * src_size).rgb; - m1 += c; - s1 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-2,2) * src_size).rgb; - m1 += c; - s1 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-2,1) * src_size).rgb; - m1 += c; - s1 += c * c; - - c = texture2D(inputImageTexture, uv + vec2(-1,3) * src_size).rgb; - m1 += c; - s1 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-1,2) * src_size).rgb; - m1 += c; - s1 += c * c; - c = texture2D(inputImageTexture, uv + vec2(-1,1) * src_size).rgb; - m1 += c; - s1 += c * c; - - c = texture2D(inputImageTexture, uv + vec2(0,3) * src_size).rgb; - cSq = c * c; - m1 += c; - s1 += cSq; - m2 += c; - s2 += cSq; - c = texture2D(inputImageTexture, uv + vec2(0,2) * src_size).rgb; - cSq = c * c; - m1 += c; - s1 += cSq; - m2 += c; - s2 += cSq; - c = texture2D(inputImageTexture, uv + vec2(0,1) * src_size).rgb; - cSq = c * c; - m1 += c; - s1 += cSq; - m2 += c; - s2 += cSq; - - c = texture2D(inputImageTexture, uv + vec2(3,3) * src_size).rgb; - m2 += c; - s2 += c * c; - c = texture2D(inputImageTexture, uv + vec2(3,2) * src_size).rgb; - m2 += c; - s2 += c * c; - c = texture2D(inputImageTexture, uv + vec2(3,1) * src_size).rgb; - m2 += c; - s2 += c * c; - c = texture2D(inputImageTexture, uv + vec2(3,0) * src_size).rgb; - cSq = c * c; - m2 += c; - s2 += cSq; - m3 += c; - s3 += cSq; - - c = texture2D(inputImageTexture, uv + vec2(2,3) * src_size).rgb; - m2 += c; - s2 += c * c; - c = texture2D(inputImageTexture, uv + vec2(2,2) * src_size).rgb; - m2 += c; - s2 += c * c; - c = texture2D(inputImageTexture, uv + vec2(2,1) * src_size).rgb; - m2 += c; - s2 += c * c; - c = texture2D(inputImageTexture, uv + vec2(2,0) * src_size).rgb; - cSq = c * c; - m2 += c; - s2 += cSq; - m3 += c; - s3 += cSq; - - c = texture2D(inputImageTexture, uv + vec2(1,3) * src_size).rgb; - m2 += c; - s2 += c * c; - c = texture2D(inputImageTexture, uv + vec2(1,2) * src_size).rgb; - m2 += c; - s2 += c * c; - c = texture2D(inputImageTexture, uv + vec2(1,1) * src_size).rgb; - m2 += c; - s2 += c * c; - c = texture2D(inputImageTexture, uv + vec2(1,0) * src_size).rgb; - cSq = c * c; - m2 += c; - s2 += cSq; - m3 += c; - s3 += cSq; - - c = texture2D(inputImageTexture, uv + vec2(3,-3) * src_size).rgb; - m3 += c; - s3 += c * c; - c = texture2D(inputImageTexture, uv + vec2(3,-2) * src_size).rgb; - m3 += c; - s3 += c * c; - c = texture2D(inputImageTexture, uv + vec2(3,-1) * src_size).rgb; - m3 += c; - s3 += c * c; - - c = texture2D(inputImageTexture, uv + vec2(2,-3) * src_size).rgb; - m3 += c; - s3 += c * c; - c = texture2D(inputImageTexture, uv + vec2(2,-2) * src_size).rgb; - m3 += c; - s3 += c * c; - c = texture2D(inputImageTexture, uv + vec2(2,-1) * src_size).rgb; - m3 += c; - s3 += c * c; - - c = texture2D(inputImageTexture, uv + vec2(1,-3) * src_size).rgb; - m3 += c; - s3 += c * c; - c = texture2D(inputImageTexture, uv + vec2(1,-2) * src_size).rgb; - m3 += c; - s3 += c * c; - c = texture2D(inputImageTexture, uv + vec2(1,-1) * src_size).rgb; - m3 += c; - s3 += c * c; - - float min_sigma2 = 1e+2; - m0 /= n; - s0 = abs(s0 / n - m0 * m0); - - float sigma2 = s0.r + s0.g + s0.b; - if (sigma2 < min_sigma2) { - min_sigma2 = sigma2; - gl_FragColor = vec4(m0, 1.0); - } - - m1 /= n; - s1 = abs(s1 / n - m1 * m1); - - sigma2 = s1.r + s1.g + s1.b; - if (sigma2 < min_sigma2) { - min_sigma2 = sigma2; - gl_FragColor = vec4(m1, 1.0); - } - - m2 /= n; - s2 = abs(s2 / n - m2 * m2); - - sigma2 = s2.r + s2.g + s2.b; - if (sigma2 < min_sigma2) { - min_sigma2 = sigma2; - gl_FragColor = vec4(m2, 1.0); - } - - m3 /= n; - s3 = abs(s3 / n - m3 * m3); - - sigma2 = s3.r + s3.g + s3.b; - if (sigma2 < min_sigma2) { - min_sigma2 = sigma2; - gl_FragColor = vec4(m3, 1.0); - } - } -); -#endif - -@implementation GPUImageKuwaharaRadius3Filter - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageKuwaharaRadius3FragmentShaderString])) - { - return nil; - } - - return self; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLanczosResamplingFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLanczosResamplingFilter.h deleted file mode 100644 index 5d7409f5..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLanczosResamplingFilter.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "GPUImageTwoPassTextureSamplingFilter.h" - -@interface GPUImageLanczosResamplingFilter : GPUImageTwoPassTextureSamplingFilter - -@property(readwrite, nonatomic) CGSize originalImageSize; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLanczosResamplingFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLanczosResamplingFilter.m deleted file mode 100644 index a655f486..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLanczosResamplingFilter.m +++ /dev/null @@ -1,239 +0,0 @@ -#import "GPUImageLanczosResamplingFilter.h" - -NSString *const kGPUImageLanczosVertexShaderString = SHADER_STRING -( - attribute vec4 position; - attribute vec2 inputTextureCoordinate; - - uniform float texelWidthOffset; - uniform float texelHeightOffset; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepLeftTextureCoordinate; - varying vec2 twoStepsLeftTextureCoordinate; - varying vec2 threeStepsLeftTextureCoordinate; - varying vec2 fourStepsLeftTextureCoordinate; - varying vec2 oneStepRightTextureCoordinate; - varying vec2 twoStepsRightTextureCoordinate; - varying vec2 threeStepsRightTextureCoordinate; - varying vec2 fourStepsRightTextureCoordinate; - - void main() - { - gl_Position = position; - - vec2 firstOffset = vec2(texelWidthOffset, texelHeightOffset); - vec2 secondOffset = vec2(2.0 * texelWidthOffset, 2.0 * texelHeightOffset); - vec2 thirdOffset = vec2(3.0 * texelWidthOffset, 3.0 * texelHeightOffset); - vec2 fourthOffset = vec2(4.0 * texelWidthOffset, 4.0 * texelHeightOffset); - - centerTextureCoordinate = inputTextureCoordinate; - oneStepLeftTextureCoordinate = inputTextureCoordinate - firstOffset; - twoStepsLeftTextureCoordinate = inputTextureCoordinate - secondOffset; - threeStepsLeftTextureCoordinate = inputTextureCoordinate - thirdOffset; - fourStepsLeftTextureCoordinate = inputTextureCoordinate - fourthOffset; - oneStepRightTextureCoordinate = inputTextureCoordinate + firstOffset; - twoStepsRightTextureCoordinate = inputTextureCoordinate + secondOffset; - threeStepsRightTextureCoordinate = inputTextureCoordinate + thirdOffset; - fourStepsRightTextureCoordinate = inputTextureCoordinate + fourthOffset; - } -); - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageLanczosFragmentShaderString = SHADER_STRING -( - precision highp float; - - uniform sampler2D inputImageTexture; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepLeftTextureCoordinate; - varying vec2 twoStepsLeftTextureCoordinate; - varying vec2 threeStepsLeftTextureCoordinate; - varying vec2 fourStepsLeftTextureCoordinate; - varying vec2 oneStepRightTextureCoordinate; - varying vec2 twoStepsRightTextureCoordinate; - varying vec2 threeStepsRightTextureCoordinate; - varying vec2 fourStepsRightTextureCoordinate; - - // sinc(x) * sinc(x/a) = (a * sin(pi * x) * sin(pi * x / a)) / (pi^2 * x^2) - // Assuming a Lanczos constant of 2.0, and scaling values to max out at x = +/- 1.5 - - void main() - { - lowp vec4 fragmentColor = texture2D(inputImageTexture, centerTextureCoordinate) * 0.38026; - - fragmentColor += texture2D(inputImageTexture, oneStepLeftTextureCoordinate) * 0.27667; - fragmentColor += texture2D(inputImageTexture, oneStepRightTextureCoordinate) * 0.27667; - - fragmentColor += texture2D(inputImageTexture, twoStepsLeftTextureCoordinate) * 0.08074; - fragmentColor += texture2D(inputImageTexture, twoStepsRightTextureCoordinate) * 0.08074; - - fragmentColor += texture2D(inputImageTexture, threeStepsLeftTextureCoordinate) * -0.02612; - fragmentColor += texture2D(inputImageTexture, threeStepsRightTextureCoordinate) * -0.02612; - - fragmentColor += texture2D(inputImageTexture, fourStepsLeftTextureCoordinate) * -0.02143; - fragmentColor += texture2D(inputImageTexture, fourStepsRightTextureCoordinate) * -0.02143; - - gl_FragColor = fragmentColor; - } -); -#else -NSString *const kGPUImageLanczosFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepLeftTextureCoordinate; - varying vec2 twoStepsLeftTextureCoordinate; - varying vec2 threeStepsLeftTextureCoordinate; - varying vec2 fourStepsLeftTextureCoordinate; - varying vec2 oneStepRightTextureCoordinate; - varying vec2 twoStepsRightTextureCoordinate; - varying vec2 threeStepsRightTextureCoordinate; - varying vec2 fourStepsRightTextureCoordinate; - - // sinc(x) * sinc(x/a) = (a * sin(pi * x) * sin(pi * x / a)) / (pi^2 * x^2) - // Assuming a Lanczos constant of 2.0, and scaling values to max out at x = +/- 1.5 - - void main() - { - vec4 fragmentColor = texture2D(inputImageTexture, centerTextureCoordinate) * 0.38026; - - fragmentColor += texture2D(inputImageTexture, oneStepLeftTextureCoordinate) * 0.27667; - fragmentColor += texture2D(inputImageTexture, oneStepRightTextureCoordinate) * 0.27667; - - fragmentColor += texture2D(inputImageTexture, twoStepsLeftTextureCoordinate) * 0.08074; - fragmentColor += texture2D(inputImageTexture, twoStepsRightTextureCoordinate) * 0.08074; - - fragmentColor += texture2D(inputImageTexture, threeStepsLeftTextureCoordinate) * -0.02612; - fragmentColor += texture2D(inputImageTexture, threeStepsRightTextureCoordinate) * -0.02612; - - fragmentColor += texture2D(inputImageTexture, fourStepsLeftTextureCoordinate) * -0.02143; - fragmentColor += texture2D(inputImageTexture, fourStepsRightTextureCoordinate) * -0.02143; - - gl_FragColor = fragmentColor; - } -); -#endif - -@implementation GPUImageLanczosResamplingFilter - -@synthesize originalImageSize = _originalImageSize; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFirstStageVertexShaderFromString:kGPUImageLanczosVertexShaderString firstStageFragmentShaderFromString:kGPUImageLanczosFragmentShaderString secondStageVertexShaderFromString:kGPUImageLanczosVertexShaderString secondStageFragmentShaderFromString:kGPUImageLanczosFragmentShaderString])) - { - return nil; - } - - return self; -} - -// Base texture sampling offset on the input image, not the final size -- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex; -{ - self.originalImageSize = newSize; - [super setInputSize:newSize atIndex:textureIndex]; -} - -- (void)setupFilterForSize:(CGSize)filterFrameSize; -{ - runSynchronouslyOnVideoProcessingQueue(^{ - // The first pass through the framebuffer may rotate the inbound image, so need to account for that by changing up the kernel ordering for that pass - if (GPUImageRotationSwapsWidthAndHeight(inputRotation)) - { - verticalPassTexelWidthOffset = 1.0 / _originalImageSize.height; - verticalPassTexelHeightOffset = 0.0; - } - else - { - verticalPassTexelWidthOffset = 0.0; - verticalPassTexelHeightOffset = 1.0 / _originalImageSize.height; - } - - horizontalPassTexelWidthOffset = 1.0 / _originalImageSize.width; - horizontalPassTexelHeightOffset = 0.0; - }); -} - - -- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates; -{ - if (self.preventRendering) - { - [firstInputFramebuffer unlock]; - return; - } - - [GPUImageContext setActiveShaderProgram:filterProgram]; - - CGSize currentFBOSize = [self sizeOfFBO]; - if (GPUImageRotationSwapsWidthAndHeight(inputRotation)) - { - currentFBOSize.height = self.originalImageSize.height; - } - else - { - currentFBOSize.width = self.originalImageSize.width; - } - outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:currentFBOSize textureOptions:self.outputTextureOptions onlyTexture:NO]; - [outputFramebuffer activateFramebuffer]; - - [self setUniformsForProgramAtIndex:0]; - - glClearColor(backgroundColorRed, backgroundColorGreen, backgroundColorBlue, backgroundColorAlpha); - glClear(GL_COLOR_BUFFER_BIT); - - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, [firstInputFramebuffer texture]); - - glUniform1i(filterInputTextureUniform, 2); - - glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, vertices); - glVertexAttribPointer(filterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - [firstInputFramebuffer unlock]; - - // Run the second stage of the two-pass filter - [GPUImageContext setActiveShaderProgram:secondFilterProgram]; - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D, 0); - secondOutputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:[self sizeOfFBO] textureOptions:self.outputTextureOptions onlyTexture:NO]; - [secondOutputFramebuffer activateFramebuffer]; - if (usingNextFrameForImageCapture) - { - [secondOutputFramebuffer lock]; - } - - [self setUniformsForProgramAtIndex:1]; - - glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D, [outputFramebuffer texture]); - glVertexAttribPointer(secondFilterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, [[self class] textureCoordinatesForRotation:kGPUImageNoRotation]); - - glUniform1i(secondFilterInputTextureUniform, 3); - - glVertexAttribPointer(secondFilterPositionAttribute, 2, GL_FLOAT, 0, 0, vertices); - - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - [outputFramebuffer unlock]; - outputFramebuffer = nil; - if (usingNextFrameForImageCapture) - { - dispatch_semaphore_signal(imageCaptureSemaphore); - } -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLaplacianFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLaplacianFilter.h deleted file mode 100644 index 267c1bab..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLaplacianFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImage3x3ConvolutionFilter.h" - -@interface GPUImageLaplacianFilter : GPUImage3x3ConvolutionFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLaplacianFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLaplacianFilter.m deleted file mode 100644 index 98b78509..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLaplacianFilter.m +++ /dev/null @@ -1,115 +0,0 @@ -#import "GPUImageLaplacianFilter.h" -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageLaplacianFragmentShaderString = SHADER_STRING -( - precision highp float; - - uniform sampler2D inputImageTexture; - - uniform mediump mat3 convolutionMatrix; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - void main() - { - mediump vec3 bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate).rgb; - mediump vec3 bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate).rgb; - mediump vec3 bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate).rgb; - mediump vec4 centerColor = texture2D(inputImageTexture, textureCoordinate); - mediump vec3 leftColor = texture2D(inputImageTexture, leftTextureCoordinate).rgb; - mediump vec3 rightColor = texture2D(inputImageTexture, rightTextureCoordinate).rgb; - mediump vec3 topColor = texture2D(inputImageTexture, topTextureCoordinate).rgb; - mediump vec3 topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate).rgb; - mediump vec3 topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate).rgb; - - mediump vec3 resultColor = topLeftColor * convolutionMatrix[0][0] + topColor * convolutionMatrix[0][1] + topRightColor * convolutionMatrix[0][2]; - resultColor += leftColor * convolutionMatrix[1][0] + centerColor.rgb * convolutionMatrix[1][1] + rightColor * convolutionMatrix[1][2]; - resultColor += bottomLeftColor * convolutionMatrix[2][0] + bottomColor * convolutionMatrix[2][1] + bottomRightColor * convolutionMatrix[2][2]; - - // Normalize the results to allow for negative gradients in the 0.0-1.0 colorspace - resultColor = resultColor + 0.5; - - gl_FragColor = vec4(resultColor, centerColor.a); - } -); -#else -NSString *const kGPUImageLaplacianFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - - uniform mat3 convolutionMatrix; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - void main() - { - vec3 bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate).rgb; - vec3 bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate).rgb; - vec3 bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate).rgb; - vec4 centerColor = texture2D(inputImageTexture, textureCoordinate); - vec3 leftColor = texture2D(inputImageTexture, leftTextureCoordinate).rgb; - vec3 rightColor = texture2D(inputImageTexture, rightTextureCoordinate).rgb; - vec3 topColor = texture2D(inputImageTexture, topTextureCoordinate).rgb; - vec3 topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate).rgb; - vec3 topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate).rgb; - - vec3 resultColor = topLeftColor * convolutionMatrix[0][0] + topColor * convolutionMatrix[0][1] + topRightColor * convolutionMatrix[0][2]; - resultColor += leftColor * convolutionMatrix[1][0] + centerColor.rgb * convolutionMatrix[1][1] + rightColor * convolutionMatrix[1][2]; - resultColor += bottomLeftColor * convolutionMatrix[2][0] + bottomColor * convolutionMatrix[2][1] + bottomRightColor * convolutionMatrix[2][2]; - - // Normalize the results to allow for negative gradients in the 0.0-1.0 colorspace - resultColor = resultColor + 0.5; - - gl_FragColor = vec4(resultColor, centerColor.a); - } -); -#endif - -@implementation GPUImageLaplacianFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageLaplacianFragmentShaderString])) - { - return nil; - } - - GPUMatrix3x3 newConvolutionMatrix; - newConvolutionMatrix.one.one = 0.5; - newConvolutionMatrix.one.two = 1.0; - newConvolutionMatrix.one.three = 0.5; - - newConvolutionMatrix.two.one = 1.0; - newConvolutionMatrix.two.two = -6.0; - newConvolutionMatrix.two.three = 1.0; - - newConvolutionMatrix.three.one = 0.5; - newConvolutionMatrix.three.two = 1.0; - newConvolutionMatrix.three.three = 0.5; - - self.convolutionKernel = newConvolutionMatrix; - - return self; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLevelsFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLevelsFilter.h deleted file mode 100644 index d0948fbf..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLevelsFilter.h +++ /dev/null @@ -1,45 +0,0 @@ -#import "GPUImageFilter.h" - -/** - * Levels like Photoshop. - * - * The min, max, minOut and maxOut parameters are floats in the range [0, 1]. - * If you have parameters from Photoshop in the range [0, 255] you must first - * convert them to be [0, 1]. - * The gamma/mid parameter is a float >= 0. This matches the value from Photoshop. - * - * If you want to apply levels to RGB as well as individual channels you need to use - * this filter twice - first for the individual channels and then for all channels. - */ -@interface GPUImageLevelsFilter : GPUImageFilter -{ - GLint minUniform; - GLint midUniform; - GLint maxUniform; - GLint minOutputUniform; - GLint maxOutputUniform; - - GPUVector3 minVector, midVector, maxVector, minOutputVector, maxOutputVector; -} - -/** Set levels for the red channel */ -- (void)setRedMin:(CGFloat)min gamma:(CGFloat)mid max:(CGFloat)max minOut:(CGFloat)minOut maxOut:(CGFloat)maxOut; - -- (void)setRedMin:(CGFloat)min gamma:(CGFloat)mid max:(CGFloat)max; - -/** Set levels for the green channel */ -- (void)setGreenMin:(CGFloat)min gamma:(CGFloat)mid max:(CGFloat)max minOut:(CGFloat)minOut maxOut:(CGFloat)maxOut; - -- (void)setGreenMin:(CGFloat)min gamma:(CGFloat)mid max:(CGFloat)max; - -/** Set levels for the blue channel */ -- (void)setBlueMin:(CGFloat)min gamma:(CGFloat)mid max:(CGFloat)max minOut:(CGFloat)minOut maxOut:(CGFloat)maxOut; - -- (void)setBlueMin:(CGFloat)min gamma:(CGFloat)mid max:(CGFloat)max; - -/** Set levels for all channels at once */ -- (void)setMin:(CGFloat)min gamma:(CGFloat)mid max:(CGFloat)max minOut:(CGFloat)minOut maxOut:(CGFloat)maxOut; -- (void)setMin:(CGFloat)min gamma:(CGFloat)mid max:(CGFloat)max; - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLevelsFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLevelsFilter.m deleted file mode 100644 index 158815fd..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLevelsFilter.m +++ /dev/null @@ -1,152 +0,0 @@ -#import "GPUImageLevelsFilter.h" - -/* - ** Gamma correction - ** Details: http://blog.mouaif.org/2009/01/22/photoshop-gamma-correction-shader/ - */ - -#define GammaCorrection(color, gamma) pow(color, 1.0 / gamma) - -/* - ** Levels control (input (+gamma), output) - ** Details: http://blog.mouaif.org/2009/01/28/levels-control-shader/ - */ - -#define LevelsControlInputRange(color, minInput, maxInput) min(max(color - minInput, vec3(0.0)) / (maxInput - minInput), vec3(1.0)) -#define LevelsControlInput(color, minInput, gamma, maxInput) GammaCorrection(LevelsControlInputRange(color, minInput, maxInput), gamma) -#define LevelsControlOutputRange(color, minOutput, maxOutput) mix(minOutput, maxOutput, color) -#define LevelsControl(color, minInput, gamma, maxInput, minOutput, maxOutput) LevelsControlOutputRange(LevelsControlInput(color, minInput, gamma, maxInput), minOutput, maxOutput) - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageLevelsFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform mediump vec3 levelMinimum; - uniform mediump vec3 levelMiddle; - uniform mediump vec3 levelMaximum; - uniform mediump vec3 minOutput; - uniform mediump vec3 maxOutput; - - void main() - { - mediump vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - gl_FragColor = vec4(LevelsControl(textureColor.rgb, levelMinimum, levelMiddle, levelMaximum, minOutput, maxOutput), textureColor.a); - } -); -#else -NSString *const kGPUImageLevelsFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform vec3 levelMinimum; - uniform vec3 levelMiddle; - uniform vec3 levelMaximum; - uniform vec3 minOutput; - uniform vec3 maxOutput; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - gl_FragColor = vec4(LevelsControl(textureColor.rgb, levelMinimum, levelMiddle, levelMaximum, minOutput, maxOutput), textureColor.a); - } -); -#endif - -@implementation GPUImageLevelsFilter - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageLevelsFragmentShaderString])) - { - return nil; - } - - minUniform = [filterProgram uniformIndex:@"levelMinimum"]; - midUniform = [filterProgram uniformIndex:@"levelMiddle"]; - maxUniform = [filterProgram uniformIndex:@"levelMaximum"]; - minOutputUniform = [filterProgram uniformIndex:@"minOutput"]; - maxOutputUniform = [filterProgram uniformIndex:@"maxOutput"]; - - [self setRedMin:0.0 gamma:1.0 max:1.0 minOut:0.0 maxOut:1.0]; - [self setGreenMin:0.0 gamma:1.0 max:1.0 minOut:0.0 maxOut:1.0]; - [self setBlueMin:0.0 gamma:1.0 max:1.0 minOut:0.0 maxOut:1.0]; - - return self; -} - -#pragma mark - -#pragma mark Helpers - -- (void)updateUniforms { - [self setVec3:minVector forUniform:minUniform program:filterProgram]; - [self setVec3:midVector forUniform:midUniform program:filterProgram]; - [self setVec3:maxVector forUniform:maxUniform program:filterProgram]; - [self setVec3:minOutputVector forUniform:minOutputUniform program:filterProgram]; - [self setVec3:maxOutputVector forUniform:maxOutputUniform program:filterProgram]; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setMin:(CGFloat)min gamma:(CGFloat)mid max:(CGFloat)max minOut:(CGFloat)minOut maxOut:(CGFloat)maxOut { - [self setRedMin:min gamma:mid max:max minOut:minOut maxOut:maxOut]; - [self setGreenMin:min gamma:mid max:max minOut:minOut maxOut:maxOut]; - [self setBlueMin:min gamma:mid max:max minOut:minOut maxOut:maxOut]; -} - -- (void)setMin:(CGFloat)min gamma:(CGFloat)mid max:(CGFloat)max { - [self setMin:min gamma:mid max:max minOut:0.0 maxOut:1.0]; -} - -- (void)setRedMin:(CGFloat)min gamma:(CGFloat)mid max:(CGFloat)max minOut:(CGFloat)minOut maxOut:(CGFloat)maxOut { - minVector.one = min; - midVector.one = mid; - maxVector.one = max; - minOutputVector.one = minOut; - maxOutputVector.one = maxOut; - - [self updateUniforms]; -} - -- (void)setRedMin:(CGFloat)min gamma:(CGFloat)mid max:(CGFloat)max { - [self setRedMin:min gamma:mid max:max minOut:0.0 maxOut:1.0]; -} - -- (void)setGreenMin:(CGFloat)min gamma:(CGFloat)mid max:(CGFloat)max minOut:(CGFloat)minOut maxOut:(CGFloat)maxOut { - minVector.two = min; - midVector.two = mid; - maxVector.two = max; - minOutputVector.two = minOut; - maxOutputVector.two = maxOut; - - [self updateUniforms]; -} - -- (void)setGreenMin:(CGFloat)min gamma:(CGFloat)mid max:(CGFloat)max { - [self setGreenMin:min gamma:mid max:max minOut:0.0 maxOut:1.0]; -} - -- (void)setBlueMin:(CGFloat)min gamma:(CGFloat)mid max:(CGFloat)max minOut:(CGFloat)minOut maxOut:(CGFloat)maxOut { - minVector.three = min; - midVector.three = mid; - maxVector.three = max; - minOutputVector.three = minOut; - maxOutputVector.three = maxOut; - - [self updateUniforms]; -} - -- (void)setBlueMin:(CGFloat)min gamma:(CGFloat)mid max:(CGFloat)max { - [self setBlueMin:min gamma:mid max:max minOut:0.0 maxOut:1.0]; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLightenBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLightenBlendFilter.h deleted file mode 100755 index b0287c13..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLightenBlendFilter.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -/// Blends two images by taking the maximum value of each color component between the images -@interface GPUImageLightenBlendFilter : GPUImageTwoInputFilter -{ -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLightenBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLightenBlendFilter.m deleted file mode 100755 index 2bbd4b20..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLightenBlendFilter.m +++ /dev/null @@ -1,52 +0,0 @@ -#import "GPUImageLightenBlendFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageLightenBlendFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - lowp vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2); - - gl_FragColor = max(textureColor, textureColor2); - } -); -#else -NSString *const kGPUImageLightenBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2); - - gl_FragColor = max(textureColor, textureColor2); - } - ); -#endif - -@implementation GPUImageLightenBlendFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageLightenBlendFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLineGenerator.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLineGenerator.h deleted file mode 100644 index 4c467366..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLineGenerator.h +++ /dev/null @@ -1,18 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageLineGenerator : GPUImageFilter -{ - GLint lineWidthUniform, lineColorUniform; - GLfloat *lineCoordinates; -} - -// The width of the displayed lines, in pixels. The default is 1. -@property(readwrite, nonatomic) CGFloat lineWidth; - -// The color of the lines is specified using individual red, green, and blue components (normalized to 1.0). The default is green: (0.0, 1.0, 0.0). -- (void)setLineColorRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent; - -// Rendering -- (void)renderLinesFromArray:(GLfloat *)lineSlopeAndIntercepts count:(NSUInteger)numberOfLines frameTime:(CMTime)frameTime; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLineGenerator.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLineGenerator.m deleted file mode 100644 index 85d93bee..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLineGenerator.m +++ /dev/null @@ -1,164 +0,0 @@ -#import "GPUImageLineGenerator.h" - -NSString *const kGPUImageLineGeneratorVertexShaderString = SHADER_STRING -( - attribute vec4 position; - - void main() - { - gl_Position = position; - } -); - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageLineGeneratorFragmentShaderString = SHADER_STRING -( - uniform lowp vec3 lineColor; - - void main() - { - gl_FragColor = vec4(lineColor, 1.0); - } -); -#else -NSString *const kGPUImageLineGeneratorFragmentShaderString = SHADER_STRING -( - uniform vec3 lineColor; - - void main() - { - gl_FragColor = vec4(lineColor, 1.0); - } -); -#endif - -@interface GPUImageLineGenerator() - -- (void)generateLineCoordinates; - -@end - -@implementation GPUImageLineGenerator - -@synthesize lineWidth = _lineWidth; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithVertexShaderFromString:kGPUImageLineGeneratorVertexShaderString fragmentShaderFromString:kGPUImageLineGeneratorFragmentShaderString])) - { - return nil; - } - - runSynchronouslyOnVideoProcessingQueue(^{ - lineWidthUniform = [filterProgram uniformIndex:@"lineWidth"]; - lineColorUniform = [filterProgram uniformIndex:@"lineColor"]; - - self.lineWidth = 1.0; - [self setLineColorRed:0.0 green:1.0 blue:0.0]; - }); - - return self; -} - -- (void)dealloc -{ - if (lineCoordinates) - { - free(lineCoordinates); - } -} - -#pragma mark - -#pragma mark Rendering - -- (void)generateLineCoordinates; -{ - lineCoordinates = calloc(1024 * 4, sizeof(GLfloat)); -} - -- (void)renderLinesFromArray:(GLfloat *)lineSlopeAndIntercepts count:(NSUInteger)numberOfLines frameTime:(CMTime)frameTime; -{ - if (self.preventRendering) - { - return; - } - - if (lineCoordinates == NULL) - { - [self generateLineCoordinates]; - } - - // Iterate through and generate vertices from the slopes and intercepts - NSUInteger currentVertexIndex = 0; - NSUInteger currentLineIndex = 0; - NSUInteger maxLineIndex = numberOfLines *2; - while(currentLineIndex < maxLineIndex) - { - GLfloat slope = lineSlopeAndIntercepts[currentLineIndex++]; - GLfloat intercept = lineSlopeAndIntercepts[currentLineIndex++]; - - if (slope > 9000.0) // Vertical line - { - lineCoordinates[currentVertexIndex++] = intercept; - lineCoordinates[currentVertexIndex++] = -1.0; - lineCoordinates[currentVertexIndex++] = intercept; - lineCoordinates[currentVertexIndex++] = 1.0; - } - else - { - lineCoordinates[currentVertexIndex++] = -1.0; - lineCoordinates[currentVertexIndex++] = slope * -1.0 + intercept; - lineCoordinates[currentVertexIndex++] = 1.0; - lineCoordinates[currentVertexIndex++] = slope * 1.0 + intercept; - } - } - - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext setActiveShaderProgram:filterProgram]; - - outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:[self sizeOfFBO] textureOptions:self.outputTextureOptions onlyTexture:NO]; - [outputFramebuffer activateFramebuffer]; - - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_ONE, GL_ONE); - glEnable(GL_BLEND); - - glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, lineCoordinates); - glDrawArrays(GL_LINES, 0, ((unsigned int)numberOfLines * 2)); - - glDisable(GL_BLEND); - - [self informTargetsAboutNewFrameAtTime:frameTime]; - }); -} - -- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates; -{ - // Prevent rendering of the frame by normal means -} - -#pragma mark - -#pragma mark Accessors - -- (void)setLineWidth:(CGFloat)newValue; -{ - _lineWidth = newValue; - [GPUImageContext setActiveShaderProgram:filterProgram]; - glLineWidth(newValue); -} - -- (void)setLineColorRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent; -{ - GPUVector3 lineColor = {redComponent, greenComponent, blueComponent}; - - [self setVec3:lineColor forUniform:lineColorUniform program:filterProgram]; -} - - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLinearBurnBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLinearBurnBlendFilter.h deleted file mode 100644 index 7e5e415c..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLinearBurnBlendFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageLinearBurnBlendFilter : GPUImageTwoInputFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLinearBurnBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLinearBurnBlendFilter.m deleted file mode 100644 index 47031967..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLinearBurnBlendFilter.m +++ /dev/null @@ -1,51 +0,0 @@ -#import "GPUImageLinearBurnBlendFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageLinearBurnBlendFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - mediump vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - mediump vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2); - - gl_FragColor = vec4(clamp(textureColor.rgb + textureColor2.rgb - vec3(1.0), vec3(0.0), vec3(1.0)), textureColor.a); - } -); -#else -NSString *const kGPUImageLinearBurnBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2); - - gl_FragColor = vec4(clamp(textureColor.rgb + textureColor2.rgb - vec3(1.0), vec3(0.0), vec3(1.0)), textureColor.a); - } -); -#endif - -@implementation GPUImageLinearBurnBlendFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageLinearBurnBlendFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLocalBinaryPatternFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLocalBinaryPatternFilter.h deleted file mode 100644 index 431dbbd4..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLocalBinaryPatternFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImage3x3TextureSamplingFilter.h" - -@interface GPUImageLocalBinaryPatternFilter : GPUImage3x3TextureSamplingFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLocalBinaryPatternFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLocalBinaryPatternFilter.m deleted file mode 100644 index 1ee1f8d9..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLocalBinaryPatternFilter.m +++ /dev/null @@ -1,123 +0,0 @@ -#import "GPUImageLocalBinaryPatternFilter.h" - -// This is based on "Accelerating image recognition on mobile devices using GPGPU" by Miguel Bordallo Lopez, Henri Nykanen, Jari Hannuksela, Olli Silven and Markku Vehvilainen -// http://www.ee.oulu.fi/~jhannuks/publications/SPIE2011a.pdf - -// Right pixel is the most significant bit, traveling clockwise to get to the upper right, which is the least significant -// If the external pixel is greater than or equal to the center, set to 1, otherwise 0 -// -// 2 1 0 -// 3 7 -// 4 5 6 - -// 01101101 -// 76543210 - -@implementation GPUImageLocalBinaryPatternFilter - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageLocalBinaryPatternFragmentShaderString = SHADER_STRING -( - precision highp float; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - lowp float centerIntensity = texture2D(inputImageTexture, textureCoordinate).r; - lowp float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - lowp float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r; - lowp float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - lowp float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - lowp float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r; - lowp float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r; - lowp float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r; - lowp float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r; - - lowp float byteTally = 1.0 / 255.0 * step(centerIntensity, topRightIntensity); - byteTally += 2.0 / 255.0 * step(centerIntensity, topIntensity); - byteTally += 4.0 / 255.0 * step(centerIntensity, topLeftIntensity); - byteTally += 8.0 / 255.0 * step(centerIntensity, leftIntensity); - byteTally += 16.0 / 255.0 * step(centerIntensity, bottomLeftIntensity); - byteTally += 32.0 / 255.0 * step(centerIntensity, bottomIntensity); - byteTally += 64.0 / 255.0 * step(centerIntensity, bottomRightIntensity); - byteTally += 128.0 / 255.0 * step(centerIntensity, rightIntensity); - - // TODO: Replace the above with a dot product and two vec4s - // TODO: Apply step to a matrix, rather than individually - - gl_FragColor = vec4(byteTally, byteTally, byteTally, 1.0); - } -); -#else -NSString *const kGPUImageLocalBinaryPatternFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - float centerIntensity = texture2D(inputImageTexture, textureCoordinate).r; - float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r; - float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r; - float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r; - float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r; - float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r; - - float byteTally = 1.0 / 255.0 * step(centerIntensity, topRightIntensity); - byteTally += 2.0 / 255.0 * step(centerIntensity, topIntensity); - byteTally += 4.0 / 255.0 * step(centerIntensity, topLeftIntensity); - byteTally += 8.0 / 255.0 * step(centerIntensity, leftIntensity); - byteTally += 16.0 / 255.0 * step(centerIntensity, bottomLeftIntensity); - byteTally += 32.0 / 255.0 * step(centerIntensity, bottomIntensity); - byteTally += 64.0 / 255.0 * step(centerIntensity, bottomRightIntensity); - byteTally += 128.0 / 255.0 * step(centerIntensity, rightIntensity); - - // TODO: Replace the above with a dot product and two vec4s - // TODO: Apply step to a matrix, rather than individually - - gl_FragColor = vec4(byteTally, byteTally, byteTally, 1.0); - } -); -#endif - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageLocalBinaryPatternFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLookupFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLookupFilter.h deleted file mode 100644 index 23ebde2b..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLookupFilter.h +++ /dev/null @@ -1,34 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageLookupFilter : GPUImageTwoInputFilter -{ - GLint intensityUniform; -} - -// How To Use: -// 1) Use your favourite photo editing application to apply a filter to lookup.png from GPUImage/framework/Resources. -// For this to work properly each pixel color must not depend on other pixels (e.g. blur will not work). -// If you need more complex filter you can create as many lookup tables as required. -// E.g. color_balance_lookup_1.png -> GPUImageGaussianBlurFilter -> color_balance_lookup_2.png -// 2) Use you new lookup.png file as a second input for GPUImageLookupFilter. - -// See GPUImageAmatorkaFilter, GPUImageMissEtikateFilter, and GPUImageSoftEleganceFilter for example. - -// Additional Info: -// Lookup texture is organised as 8x8 quads of 64x64 pixels representing all possible RGB colors: -//for (int by = 0; by < 8; by++) { -// for (int bx = 0; bx < 8; bx++) { -// for (int g = 0; g < 64; g++) { -// for (int r = 0; r < 64; r++) { -// image.setPixel(r + bx * 64, g + by * 64, qRgb((int)(r * 255.0 / 63.0 + 0.5), -// (int)(g * 255.0 / 63.0 + 0.5), -// (int)((bx + by * 8.0) * 255.0 / 63.0 + 0.5))); -// } -// } -// } -//} - -// Opacity/intensity of lookup filter ranges from 0.0 to 1.0, with 1.0 as the normal setting -@property(readwrite, nonatomic) CGFloat intensity; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLookupFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLookupFilter.m deleted file mode 100644 index c098392b..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLookupFilter.m +++ /dev/null @@ -1,115 +0,0 @@ -#import "GPUImageLookupFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageLookupFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; // TODO: This is not used - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; // lookup texture - - uniform lowp float intensity; - - void main() - { - highp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - highp float blueColor = textureColor.b * 63.0; - - highp vec2 quad1; - quad1.y = floor(floor(blueColor) / 8.0); - quad1.x = floor(blueColor) - (quad1.y * 8.0); - - highp vec2 quad2; - quad2.y = floor(ceil(blueColor) / 8.0); - quad2.x = ceil(blueColor) - (quad2.y * 8.0); - - highp vec2 texPos1; - texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r); - texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g); - - highp vec2 texPos2; - texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r); - texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g); - - lowp vec4 newColor1 = texture2D(inputImageTexture2, texPos1); - lowp vec4 newColor2 = texture2D(inputImageTexture2, texPos2); - - lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor)); - gl_FragColor = mix(textureColor, vec4(newColor.rgb, textureColor.w), intensity); - } -); -#else -NSString *const kGPUImageLookupFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; // TODO: This is not used - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; // lookup texture - - uniform float intensity; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - float blueColor = textureColor.b * 63.0; - - vec2 quad1; - quad1.y = floor(floor(blueColor) / 8.0); - quad1.x = floor(blueColor) - (quad1.y * 8.0); - - vec2 quad2; - quad2.y = floor(ceil(blueColor) / 8.0); - quad2.x = ceil(blueColor) - (quad2.y * 8.0); - - vec2 texPos1; - texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r); - texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g); - - vec2 texPos2; - texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r); - texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g); - - vec4 newColor1 = texture2D(inputImageTexture2, texPos1); - vec4 newColor2 = texture2D(inputImageTexture2, texPos2); - - vec4 newColor = mix(newColor1, newColor2, fract(blueColor)); - gl_FragColor = mix(textureColor, vec4(newColor.rgb, textureColor.w), intensity); - } -); -#endif - -@implementation GPUImageLookupFilter - -@synthesize intensity = _intensity; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - intensityUniform = [filterProgram uniformIndex:@"intensity"]; - self.intensity = 1.0f; - - if (!(self = [super initWithFragmentShaderFromString:kGPUImageLookupFragmentShaderString])) - { - return nil; - } - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setIntensity:(CGFloat)intensity -{ - _intensity = intensity; - - [self setFloat:_intensity forUniform:intensityUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLowPassFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLowPassFilter.h deleted file mode 100644 index be5c397e..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLowPassFilter.h +++ /dev/null @@ -1,14 +0,0 @@ -#import "GPUImageFilterGroup.h" -#import "GPUImageBuffer.h" -#import "GPUImageDissolveBlendFilter.h" - -@interface GPUImageLowPassFilter : GPUImageFilterGroup -{ - GPUImageBuffer *bufferFilter; - GPUImageDissolveBlendFilter *dissolveBlendFilter; -} - -// This controls the degree by which the previous accumulated frames are blended with the current one. This ranges from 0.0 to 1.0, with a default of 0.5. -@property(readwrite, nonatomic) CGFloat filterStrength; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLowPassFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLowPassFilter.m deleted file mode 100644 index 39ca08f6..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLowPassFilter.m +++ /dev/null @@ -1,61 +0,0 @@ -#import "GPUImageLowPassFilter.h" - -@implementation GPUImageLowPassFilter - -@synthesize filterStrength; - -- (id)init; -{ - if (!(self = [super init])) - { - return nil; - } - - // Take in the frame and blend it with the previous one - dissolveBlendFilter = [[GPUImageDissolveBlendFilter alloc] init]; - [self addFilter:dissolveBlendFilter]; - - // Buffer the result to be fed back into the blend - bufferFilter = [[GPUImageBuffer alloc] init]; - [self addFilter:bufferFilter]; - - // Texture location 0 needs to be the original image for the dissolve blend - [bufferFilter addTarget:dissolveBlendFilter atTextureLocation:1]; - [dissolveBlendFilter addTarget:bufferFilter]; - - [dissolveBlendFilter disableSecondFrameCheck]; - - // To prevent double updating of this filter, disable updates from the sharp image side - // self.inputFilterToIgnoreForUpdates = unsharpMaskFilter; - - self.initialFilters = [NSArray arrayWithObject:dissolveBlendFilter]; - self.terminalFilter = dissolveBlendFilter; - - self.filterStrength = 0.5; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setFilterStrength:(CGFloat)newValue; -{ - dissolveBlendFilter.mix = newValue; -} - -- (CGFloat)filterStrength; -{ - return dissolveBlendFilter.mix; -} - -- (void)addTarget:(id)newTarget atTextureLocation:(NSInteger)textureLocation; -{ - [self.terminalFilter addTarget:newTarget atTextureLocation:textureLocation]; - //if use GPUImagePipline,will cause self.termainlFilter removeAllTargets,so need add bufferFilter back - if (self.terminalFilter == dissolveBlendFilter && ![self.terminalFilter.targets containsObject:bufferFilter]) { - [self.terminalFilter addTarget:bufferFilter atTextureLocation:1]; - } -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminanceRangeFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminanceRangeFilter.h deleted file mode 100644 index 5a310370..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminanceRangeFilter.h +++ /dev/null @@ -1,12 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageLuminanceRangeFilter : GPUImageFilter -{ - GLint rangeReductionUniform; -} - -/** The degree to reduce the luminance range, from 0.0 to 1.0. Default is 0.6. - */ -@property(readwrite, nonatomic) CGFloat rangeReductionFactor; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminanceRangeFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminanceRangeFilter.m deleted file mode 100644 index 5122c958..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminanceRangeFilter.m +++ /dev/null @@ -1,76 +0,0 @@ -#import "GPUImageLuminanceRangeFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageLuminanceRangeFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform lowp float rangeReduction; - - // Values from "Graphics Shaders: Theory and Practice" by Bailey and Cunningham - const mediump vec3 luminanceWeighting = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - mediump float luminance = dot(textureColor.rgb, luminanceWeighting); - mediump float luminanceRatio = ((0.5 - luminance) * rangeReduction); - - gl_FragColor = vec4((textureColor.rgb) + (luminanceRatio), textureColor.w); - } -); -#else -NSString *const kGPUImageLuminanceRangeFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float rangeReduction; - - // Values from "Graphics Shaders: Theory and Practice" by Bailey and Cunningham - const vec3 luminanceWeighting = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - float luminance = dot(textureColor.rgb, luminanceWeighting); - float luminanceRatio = ((0.5 - luminance) * rangeReduction); - - gl_FragColor = vec4((textureColor.rgb) + (luminanceRatio), textureColor.w); - } -); -#endif - -@implementation GPUImageLuminanceRangeFilter - -@synthesize rangeReductionFactor = _rangeReductionFactor; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageLuminanceRangeFragmentShaderString])) - { - return nil; - } - - rangeReductionUniform = [filterProgram uniformIndex:@"rangeReduction"]; - self.rangeReductionFactor = 0.6; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setRangeReductionFactor:(CGFloat)newValue; -{ - _rangeReductionFactor = newValue; - - [self setFloat:_rangeReductionFactor forUniform:rangeReductionUniform program:filterProgram]; -} - - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminanceThresholdFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminanceThresholdFilter.h deleted file mode 100755 index 0abb9a1e..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminanceThresholdFilter.h +++ /dev/null @@ -1,14 +0,0 @@ -#import "GPUImageFilter.h" - -/** Pixels with a luminance above the threshold will appear white, and those below will be black - */ -@interface GPUImageLuminanceThresholdFilter : GPUImageFilter -{ - GLint thresholdUniform; -} - -/** Anything above this luminance will be white, and anything below black. Ranges from 0.0 to 1.0, with 0.5 as the default - */ -@property(readwrite, nonatomic) CGFloat threshold; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminanceThresholdFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminanceThresholdFilter.m deleted file mode 100755 index 368b8fbe..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminanceThresholdFilter.m +++ /dev/null @@ -1,74 +0,0 @@ -#import "GPUImageLuminanceThresholdFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageLuminanceThresholdFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform highp float threshold; - - const highp vec3 W = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - highp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - highp float luminance = dot(textureColor.rgb, W); - highp float thresholdResult = step(threshold, luminance); - - gl_FragColor = vec4(vec3(thresholdResult), textureColor.w); - } -); -#else -NSString *const kGPUImageLuminanceThresholdFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float threshold; - - const vec3 W = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - float luminance = dot(textureColor.rgb, W); - float thresholdResult = step(threshold, luminance); - - gl_FragColor = vec4(vec3(thresholdResult), textureColor.w); - } -); -#endif - -@implementation GPUImageLuminanceThresholdFilter - -@synthesize threshold = _threshold; - -#pragma mark - -#pragma mark Initialization - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageLuminanceThresholdFragmentShaderString])) - { - return nil; - } - - thresholdUniform = [filterProgram uniformIndex:@"threshold"]; - self.threshold = 0.5; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setThreshold:(CGFloat)newValue; -{ - _threshold = newValue; - - [self setFloat:_threshold forUniform:thresholdUniform program:filterProgram]; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminosity.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminosity.h deleted file mode 100644 index b2d2458f..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminosity.h +++ /dev/null @@ -1,17 +0,0 @@ -#import "GPUImageAverageColor.h" - -@interface GPUImageLuminosity : GPUImageAverageColor -{ - GLProgram *secondFilterProgram; - GLint secondFilterPositionAttribute, secondFilterTextureCoordinateAttribute; - GLint secondFilterInputTextureUniform, secondFilterInputTextureUniform2; - GLint secondFilterTexelWidthUniform, secondFilterTexelHeightUniform; -} - -// This block is called on the completion of color averaging for a frame -@property(nonatomic, copy) void(^luminosityProcessingFinishedBlock)(CGFloat luminosity, CMTime frameTime); - -- (void)extractLuminosityAtFrameTime:(CMTime)frameTime; -- (void)initializeSecondaryAttributes; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminosity.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminosity.m deleted file mode 100644 index 37f374ab..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminosity.m +++ /dev/null @@ -1,329 +0,0 @@ -#import "GPUImageLuminosity.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageInitialLuminosityFragmentShaderString = SHADER_STRING -( - precision highp float; - - uniform sampler2D inputImageTexture; - - varying highp vec2 outputTextureCoordinate; - - varying highp vec2 upperLeftInputTextureCoordinate; - varying highp vec2 upperRightInputTextureCoordinate; - varying highp vec2 lowerLeftInputTextureCoordinate; - varying highp vec2 lowerRightInputTextureCoordinate; - - const highp vec3 W = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - highp float upperLeftLuminance = dot(texture2D(inputImageTexture, upperLeftInputTextureCoordinate).rgb, W); - highp float upperRightLuminance = dot(texture2D(inputImageTexture, upperRightInputTextureCoordinate).rgb, W); - highp float lowerLeftLuminance = dot(texture2D(inputImageTexture, lowerLeftInputTextureCoordinate).rgb, W); - highp float lowerRightLuminance = dot(texture2D(inputImageTexture, lowerRightInputTextureCoordinate).rgb, W); - - highp float luminosity = 0.25 * (upperLeftLuminance + upperRightLuminance + lowerLeftLuminance + lowerRightLuminance); - gl_FragColor = vec4(luminosity, luminosity, luminosity, 1.0); - } -); - -NSString *const kGPUImageLuminosityFragmentShaderString = SHADER_STRING -( - precision highp float; - - uniform sampler2D inputImageTexture; - - varying highp vec2 outputTextureCoordinate; - - varying highp vec2 upperLeftInputTextureCoordinate; - varying highp vec2 upperRightInputTextureCoordinate; - varying highp vec2 lowerLeftInputTextureCoordinate; - varying highp vec2 lowerRightInputTextureCoordinate; - - void main() - { - highp float upperLeftLuminance = texture2D(inputImageTexture, upperLeftInputTextureCoordinate).r; - highp float upperRightLuminance = texture2D(inputImageTexture, upperRightInputTextureCoordinate).r; - highp float lowerLeftLuminance = texture2D(inputImageTexture, lowerLeftInputTextureCoordinate).r; - highp float lowerRightLuminance = texture2D(inputImageTexture, lowerRightInputTextureCoordinate).r; - - highp float luminosity = 0.25 * (upperLeftLuminance + upperRightLuminance + lowerLeftLuminance + lowerRightLuminance); - gl_FragColor = vec4(luminosity, luminosity, luminosity, 1.0); - } -); -#else -NSString *const kGPUImageInitialLuminosityFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - - varying vec2 outputTextureCoordinate; - - varying vec2 upperLeftInputTextureCoordinate; - varying vec2 upperRightInputTextureCoordinate; - varying vec2 lowerLeftInputTextureCoordinate; - varying vec2 lowerRightInputTextureCoordinate; - - const vec3 W = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - float upperLeftLuminance = dot(texture2D(inputImageTexture, upperLeftInputTextureCoordinate).rgb, W); - float upperRightLuminance = dot(texture2D(inputImageTexture, upperRightInputTextureCoordinate).rgb, W); - float lowerLeftLuminance = dot(texture2D(inputImageTexture, lowerLeftInputTextureCoordinate).rgb, W); - float lowerRightLuminance = dot(texture2D(inputImageTexture, lowerRightInputTextureCoordinate).rgb, W); - - float luminosity = 0.25 * (upperLeftLuminance + upperRightLuminance + lowerLeftLuminance + lowerRightLuminance); - gl_FragColor = vec4(luminosity, luminosity, luminosity, 1.0); - } -); - -NSString *const kGPUImageLuminosityFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - - varying vec2 outputTextureCoordinate; - - varying vec2 upperLeftInputTextureCoordinate; - varying vec2 upperRightInputTextureCoordinate; - varying vec2 lowerLeftInputTextureCoordinate; - varying vec2 lowerRightInputTextureCoordinate; - - void main() - { - float upperLeftLuminance = texture2D(inputImageTexture, upperLeftInputTextureCoordinate).r; - float upperRightLuminance = texture2D(inputImageTexture, upperRightInputTextureCoordinate).r; - float lowerLeftLuminance = texture2D(inputImageTexture, lowerLeftInputTextureCoordinate).r; - float lowerRightLuminance = texture2D(inputImageTexture, lowerRightInputTextureCoordinate).r; - - float luminosity = 0.25 * (upperLeftLuminance + upperRightLuminance + lowerLeftLuminance + lowerRightLuminance); - gl_FragColor = vec4(luminosity, luminosity, luminosity, 1.0); - } -); -#endif - -@implementation GPUImageLuminosity - -@synthesize luminosityProcessingFinishedBlock = _luminosityProcessingFinishedBlock; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithVertexShaderFromString:kGPUImageColorAveragingVertexShaderString fragmentShaderFromString:kGPUImageInitialLuminosityFragmentShaderString])) - { - return nil; - } - - texelWidthUniform = [filterProgram uniformIndex:@"texelWidth"]; - texelHeightUniform = [filterProgram uniformIndex:@"texelHeight"]; - - __unsafe_unretained GPUImageLuminosity *weakSelf = self; - [self setFrameProcessingCompletionBlock:^(GPUImageOutput *filter, CMTime frameTime) { - [weakSelf extractLuminosityAtFrameTime:frameTime]; - }]; - - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext useImageProcessingContext]; - - secondFilterProgram = [[GPUImageContext sharedImageProcessingContext] programForVertexShaderString:kGPUImageColorAveragingVertexShaderString fragmentShaderString:kGPUImageLuminosityFragmentShaderString]; - - if (!secondFilterProgram.initialized) - { - [self initializeSecondaryAttributes]; - - if (![secondFilterProgram link]) - { - NSString *progLog = [secondFilterProgram programLog]; - NSLog(@"Program link log: %@", progLog); - NSString *fragLog = [secondFilterProgram fragmentShaderLog]; - NSLog(@"Fragment shader compile log: %@", fragLog); - NSString *vertLog = [secondFilterProgram vertexShaderLog]; - NSLog(@"Vertex shader compile log: %@", vertLog); - filterProgram = nil; - NSAssert(NO, @"Filter shader link failed"); - } - } - - secondFilterPositionAttribute = [secondFilterProgram attributeIndex:@"position"]; - secondFilterTextureCoordinateAttribute = [secondFilterProgram attributeIndex:@"inputTextureCoordinate"]; - secondFilterInputTextureUniform = [secondFilterProgram uniformIndex:@"inputImageTexture"]; // This does assume a name of "inputImageTexture" for the fragment shader - secondFilterInputTextureUniform2 = [secondFilterProgram uniformIndex:@"inputImageTexture2"]; // This does assume a name of "inputImageTexture2" for second input texture in the fragment shader - - secondFilterTexelWidthUniform = [secondFilterProgram uniformIndex:@"texelWidth"]; - secondFilterTexelHeightUniform = [secondFilterProgram uniformIndex:@"texelHeight"]; - - [GPUImageContext setActiveShaderProgram:secondFilterProgram]; - - glEnableVertexAttribArray(secondFilterPositionAttribute); - glEnableVertexAttribArray(secondFilterTextureCoordinateAttribute); - }); - - return self; -} - -- (void)initializeSecondaryAttributes; -{ - [secondFilterProgram addAttribute:@"position"]; - [secondFilterProgram addAttribute:@"inputTextureCoordinate"]; -} - -/* -- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates; -{ - if (self.preventRendering) - { - [firstInputFramebuffer unlock]; - return; - } - - // Do an initial render pass that both convert to luminance and reduces - [GPUImageContext setActiveShaderProgram:filterProgram]; - - glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, vertices); - glVertexAttribPointer(filterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates); - - GLuint currentFramebuffer = [[stageFramebuffers objectAtIndex:0] intValue]; - glBindFramebuffer(GL_FRAMEBUFFER, currentFramebuffer); - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - CGSize currentStageSize = [[stageSizes objectAtIndex:0] CGSizeValue]; -#else - NSSize currentStageSize = [[stageSizes objectAtIndex:0] sizeValue]; -#endif - glViewport(0, 0, (int)currentStageSize.width, (int)currentStageSize.height); - - GLuint currentTexture = [firstInputFramebuffer texture]; - - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, currentTexture); - - glUniform1i(filterInputTextureUniform, 2); - - glUniform1f(texelWidthUniform, 0.5 / currentStageSize.width); - glUniform1f(texelHeightUniform, 0.5 / currentStageSize.height); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - currentTexture = [[stageTextures objectAtIndex:0] intValue]; - - // Just perform reductions from this point on - [GPUImageContext setActiveShaderProgram:secondFilterProgram]; - glVertexAttribPointer(secondFilterPositionAttribute, 2, GL_FLOAT, 0, 0, vertices); - glVertexAttribPointer(secondFilterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates); - - NSUInteger numberOfStageFramebuffers = [stageFramebuffers count]; - for (NSUInteger currentStage = 1; currentStage < numberOfStageFramebuffers; currentStage++) - { - currentFramebuffer = [[stageFramebuffers objectAtIndex:currentStage] intValue]; - glBindFramebuffer(GL_FRAMEBUFFER, currentFramebuffer); - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - currentStageSize = [[stageSizes objectAtIndex:currentStage] CGSizeValue]; -#else - currentStageSize = [[stageSizes objectAtIndex:currentStage] sizeValue]; -#endif - glViewport(0, 0, (int)currentStageSize.width, (int)currentStageSize.height); - - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, currentTexture); - - glUniform1i(secondFilterInputTextureUniform, 2); - - glUniform1f(secondFilterTexelWidthUniform, 0.5 / currentStageSize.width); - glUniform1f(secondFilterTexelHeightUniform, 0.5 / currentStageSize.height); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - currentTexture = [[stageTextures objectAtIndex:currentStage] intValue]; - -// NSUInteger totalBytesForImage = (int)currentStageSize.width * (int)currentStageSize.height * 4; -// GLubyte *rawImagePixels2 = (GLubyte *)malloc(totalBytesForImage); -// glReadPixels(0, 0, (int)currentStageSize.width, (int)currentStageSize.height, GL_RGBA, GL_UNSIGNED_BYTE, rawImagePixels2); -// CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, rawImagePixels2, totalBytesForImage, NULL); -// CGColorSpaceRef defaultRGBColorSpace = CGColorSpaceCreateDeviceRGB(); -// -// CGFloat currentRedTotal = 0.0f, currentGreenTotal = 0.0f, currentBlueTotal = 0.0f, currentAlphaTotal = 0.0f; -// NSUInteger totalNumberOfPixels = totalBytesForImage / 4; -// -// for (NSUInteger currentPixel = 0; currentPixel < totalNumberOfPixels; currentPixel++) -// { -// currentRedTotal += (CGFloat)rawImagePixels2[(currentPixel * 4)] / 255.0f; -// currentGreenTotal += (CGFloat)rawImagePixels2[(currentPixel * 4) + 1] / 255.0f; -// currentBlueTotal += (CGFloat)rawImagePixels2[(currentPixel * 4 + 2)] / 255.0f; -// currentAlphaTotal += (CGFloat)rawImagePixels2[(currentPixel * 4) + 3] / 255.0f; -// } -// -// NSLog(@"Stage %d average image red: %f, green: %f, blue: %f, alpha: %f", currentStage, currentRedTotal / (CGFloat)totalNumberOfPixels, currentGreenTotal / (CGFloat)totalNumberOfPixels, currentBlueTotal / (CGFloat)totalNumberOfPixels, currentAlphaTotal / (CGFloat)totalNumberOfPixels); -// -// -// CGImageRef cgImageFromBytes = CGImageCreate((int)currentStageSize.width, (int)currentStageSize.height, 8, 32, 4 * (int)currentStageSize.width, defaultRGBColorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaLast, dataProvider, NULL, NO, kCGRenderingIntentDefault); -// -// UIImage *imageToSave = [UIImage imageWithCGImage:cgImageFromBytes]; -// -// NSData *dataForPNGFile = UIImagePNGRepresentation(imageToSave); -// -// NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); -// NSString *documentsDirectory = [paths objectAtIndex:0]; -// -// NSString *imageName = [NSString stringWithFormat:@"AverageLevel%d.png", currentStage]; -// NSError *error = nil; -// if (![dataForPNGFile writeToFile:[documentsDirectory stringByAppendingPathComponent:imageName] options:NSAtomicWrite error:&error]) -// { -// return; -// } - } - - [firstInputFramebuffer unlock]; -} - */ - -#pragma mark - -#pragma mark Callbacks - -- (void)extractLuminosityAtFrameTime:(CMTime)frameTime; -{ - runSynchronouslyOnVideoProcessingQueue(^{ - - // we need a normal color texture for this filter - NSAssert(self.outputTextureOptions.internalFormat == GL_RGBA, @"The output texture format for this filter must be GL_RGBA."); - NSAssert(self.outputTextureOptions.type == GL_UNSIGNED_BYTE, @"The type of the output texture of this filter must be GL_UNSIGNED_BYTE."); - - NSUInteger totalNumberOfPixels = round(finalStageSize.width * finalStageSize.height); - - if (rawImagePixels == NULL) - { - rawImagePixels = (GLubyte *)malloc(totalNumberOfPixels * 4); - } - - [GPUImageContext useImageProcessingContext]; - [outputFramebuffer activateFramebuffer]; - - glReadPixels(0, 0, (int)finalStageSize.width, (int)finalStageSize.height, GL_RGBA, GL_UNSIGNED_BYTE, rawImagePixels); - - NSUInteger luminanceTotal = 0; - NSUInteger byteIndex = 0; - for (NSUInteger currentPixel = 0; currentPixel < totalNumberOfPixels; currentPixel++) - { - luminanceTotal += rawImagePixels[byteIndex]; - byteIndex += 4; - } - - CGFloat normalizedLuminosityTotal = (CGFloat)luminanceTotal / (CGFloat)totalNumberOfPixels / 255.0; - - if (_luminosityProcessingFinishedBlock != NULL) - { - _luminosityProcessingFinishedBlock(normalizedLuminosityTotal, frameTime); - } - }); -} - - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminosityBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminosityBlendFilter.h deleted file mode 100644 index 03b5e4c9..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminosityBlendFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageLuminosityBlendFilter : GPUImageTwoInputFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminosityBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminosityBlendFilter.m deleted file mode 100644 index 7e399746..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageLuminosityBlendFilter.m +++ /dev/null @@ -1,113 +0,0 @@ -#import "GPUImageLuminosityBlendFilter.h" - -/** - * Luminosity blend mode based upon pseudo code from the PDF specification. - */ -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageLuminosityBlendFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - highp float lum(lowp vec3 c) { - return dot(c, vec3(0.3, 0.59, 0.11)); - } - - lowp vec3 clipcolor(lowp vec3 c) { - highp float l = lum(c); - lowp float n = min(min(c.r, c.g), c.b); - lowp float x = max(max(c.r, c.g), c.b); - - if (n < 0.0) { - c.r = l + ((c.r - l) * l) / (l - n); - c.g = l + ((c.g - l) * l) / (l - n); - c.b = l + ((c.b - l) * l) / (l - n); - } - if (x > 1.0) { - c.r = l + ((c.r - l) * (1.0 - l)) / (x - l); - c.g = l + ((c.g - l) * (1.0 - l)) / (x - l); - c.b = l + ((c.b - l) * (1.0 - l)) / (x - l); - } - - return c; - } - - lowp vec3 setlum(lowp vec3 c, highp float l) { - highp float d = l - lum(c); - c = c + vec3(d); - return clipcolor(c); - } - - void main() - { - highp vec4 baseColor = texture2D(inputImageTexture, textureCoordinate); - highp vec4 overlayColor = texture2D(inputImageTexture2, textureCoordinate2); - - gl_FragColor = vec4(baseColor.rgb * (1.0 - overlayColor.a) + setlum(baseColor.rgb, lum(overlayColor.rgb)) * overlayColor.a, baseColor.a); - } -); -#else -NSString *const kGPUImageLuminosityBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - float lum(vec3 c) { - return dot(c, vec3(0.3, 0.59, 0.11)); - } - - vec3 clipcolor(vec3 c) { - float l = lum(c); - float n = min(min(c.r, c.g), c.b); - float x = max(max(c.r, c.g), c.b); - - if (n < 0.0) { - c.r = l + ((c.r - l) * l) / (l - n); - c.g = l + ((c.g - l) * l) / (l - n); - c.b = l + ((c.b - l) * l) / (l - n); - } - if (x > 1.0) { - c.r = l + ((c.r - l) * (1.0 - l)) / (x - l); - c.g = l + ((c.g - l) * (1.0 - l)) / (x - l); - c.b = l + ((c.b - l) * (1.0 - l)) / (x - l); - } - - return c; - } - - vec3 setlum(vec3 c, float l) { - float d = l - lum(c); - c = c + vec3(d); - return clipcolor(c); - } - - void main() - { - vec4 baseColor = texture2D(inputImageTexture, textureCoordinate); - vec4 overlayColor = texture2D(inputImageTexture2, textureCoordinate2); - - gl_FragColor = vec4(baseColor.rgb * (1.0 - overlayColor.a) + setlum(baseColor.rgb, lum(overlayColor.rgb)) * overlayColor.a, baseColor.a); - } -); -#endif - - -@implementation GPUImageLuminosityBlendFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageLuminosityBlendFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMaskFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMaskFilter.h deleted file mode 100755 index 94cf0648..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMaskFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageMaskFilter : GPUImageTwoInputFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMaskFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMaskFilter.m deleted file mode 100755 index 24503b3b..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMaskFilter.m +++ /dev/null @@ -1,76 +0,0 @@ -#import "GPUImageMaskFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageMaskShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - lowp vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2); - - //Averages mask's the RGB values, and scales that value by the mask's alpha - // - //The dot product should take fewer cycles than doing an average normally - // - //Typical/ideal case, R,G, and B will be the same, and Alpha will be 1.0 - lowp float newAlpha = dot(textureColor2.rgb, vec3(.33333334, .33333334, .33333334)) * textureColor2.a; - - gl_FragColor = vec4(textureColor.xyz, newAlpha); -// gl_FragColor = vec4(textureColor2); - } -); -#else -NSString *const kGPUImageMaskShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2); - - //Averages mask's the RGB values, and scales that value by the mask's alpha - // - //The dot product should take fewer cycles than doing an average normally - // - //Typical/ideal case, R,G, and B will be the same, and Alpha will be 1.0 - float newAlpha = dot(textureColor2.rgb, vec3(.33333334, .33333334, .33333334)) * textureColor2.a; - - gl_FragColor = vec4(textureColor.xyz, newAlpha); - // gl_FragColor = vec4(textureColor2); - } -); -#endif - -@implementation GPUImageMaskFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageMaskShaderString])) - { - return nil; - } - - return self; -} - -- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates; -{ - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - [super renderToTextureWithVertices:vertices textureCoordinates:textureCoordinates]; - glDisable(GL_BLEND); -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMedianFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMedianFilter.h deleted file mode 100644 index 80225789..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMedianFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImage3x3TextureSamplingFilter.h" - -@interface GPUImageMedianFilter : GPUImage3x3TextureSamplingFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMedianFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMedianFilter.m deleted file mode 100644 index 78c11805..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMedianFilter.m +++ /dev/null @@ -1,178 +0,0 @@ -#import "GPUImageMedianFilter.h" - -/* - 3x3 median filter, adapted from "A Fast, Small-Radius GPU Median Filter" by Morgan McGuire in ShaderX6 - http://graphics.cs.williams.edu/papers/MedianShaderX6/ - - Morgan McGuire and Kyle Whitson - Williams College - - Register allocation tips by Victor Huang Xiaohuang - University of Illinois at Urbana-Champaign - - http://graphics.cs.williams.edu - - - Copyright (c) Morgan McGuire and Williams College, 2006 - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageMedianFragmentShaderString = SHADER_STRING -( - precision highp float; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - -#define s2(a, b) temp = a; a = min(a, b); b = max(temp, b); -#define mn3(a, b, c) s2(a, b); s2(a, c); -#define mx3(a, b, c) s2(b, c); s2(a, c); - -#define mnmx3(a, b, c) mx3(a, b, c); s2(a, b); // 3 exchanges -#define mnmx4(a, b, c, d) s2(a, b); s2(c, d); s2(a, c); s2(b, d); // 4 exchanges -#define mnmx5(a, b, c, d, e) s2(a, b); s2(c, d); mn3(a, c, e); mx3(b, d, e); // 6 exchanges -#define mnmx6(a, b, c, d, e, f) s2(a, d); s2(b, e); s2(c, f); mn3(a, b, c); mx3(d, e, f); // 7 exchanges - - void main() - { - vec3 v[6]; - - v[0] = texture2D(inputImageTexture, bottomLeftTextureCoordinate).rgb; - v[1] = texture2D(inputImageTexture, topRightTextureCoordinate).rgb; - v[2] = texture2D(inputImageTexture, topLeftTextureCoordinate).rgb; - v[3] = texture2D(inputImageTexture, bottomRightTextureCoordinate).rgb; - v[4] = texture2D(inputImageTexture, leftTextureCoordinate).rgb; - v[5] = texture2D(inputImageTexture, rightTextureCoordinate).rgb; -// v[6] = texture2D(inputImageTexture, bottomTextureCoordinate).rgb; -// v[7] = texture2D(inputImageTexture, topTextureCoordinate).rgb; - vec3 temp; - - mnmx6(v[0], v[1], v[2], v[3], v[4], v[5]); - - v[5] = texture2D(inputImageTexture, bottomTextureCoordinate).rgb; - - mnmx5(v[1], v[2], v[3], v[4], v[5]); - - v[5] = texture2D(inputImageTexture, topTextureCoordinate).rgb; - - mnmx4(v[2], v[3], v[4], v[5]); - - v[5] = texture2D(inputImageTexture, textureCoordinate).rgb; - - mnmx3(v[3], v[4], v[5]); - - gl_FragColor = vec4(v[4], 1.0); - } -); -#else -NSString *const kGPUImageMedianFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - -#define s2(a, b) temp = a; a = min(a, b); b = max(temp, b); -#define mn3(a, b, c) s2(a, b); s2(a, c); -#define mx3(a, b, c) s2(b, c); s2(a, c); - -#define mnmx3(a, b, c) mx3(a, b, c); s2(a, b); // 3 exchanges -#define mnmx4(a, b, c, d) s2(a, b); s2(c, d); s2(a, c); s2(b, d); // 4 exchanges -#define mnmx5(a, b, c, d, e) s2(a, b); s2(c, d); mn3(a, c, e); mx3(b, d, e); // 6 exchanges -#define mnmx6(a, b, c, d, e, f) s2(a, d); s2(b, e); s2(c, f); mn3(a, b, c); mx3(d, e, f); // 7 exchanges - - void main() - { - vec3 v[6]; - - v[0] = texture2D(inputImageTexture, bottomLeftTextureCoordinate).rgb; - v[1] = texture2D(inputImageTexture, topRightTextureCoordinate).rgb; - v[2] = texture2D(inputImageTexture, topLeftTextureCoordinate).rgb; - v[3] = texture2D(inputImageTexture, bottomRightTextureCoordinate).rgb; - v[4] = texture2D(inputImageTexture, leftTextureCoordinate).rgb; - v[5] = texture2D(inputImageTexture, rightTextureCoordinate).rgb; - // v[6] = texture2D(inputImageTexture, bottomTextureCoordinate).rgb; - // v[7] = texture2D(inputImageTexture, topTextureCoordinate).rgb; - vec3 temp; - - mnmx6(v[0], v[1], v[2], v[3], v[4], v[5]); - - v[5] = texture2D(inputImageTexture, bottomTextureCoordinate).rgb; - - mnmx5(v[1], v[2], v[3], v[4], v[5]); - - v[5] = texture2D(inputImageTexture, topTextureCoordinate).rgb; - - mnmx4(v[2], v[3], v[4], v[5]); - - v[5] = texture2D(inputImageTexture, textureCoordinate).rgb; - - mnmx3(v[3], v[4], v[5]); - - gl_FragColor = vec4(v[4], 1.0); - } -); -#endif - -@implementation GPUImageMedianFilter - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageMedianFragmentShaderString])) - { - return nil; - } - - hasOverriddenImageSizeFactor = NO; - - return self; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMissEtikateFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMissEtikateFilter.h deleted file mode 100755 index de170647..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMissEtikateFilter.h +++ /dev/null @@ -1,17 +0,0 @@ -#import "GPUImageFilterGroup.h" - -@class GPUImagePicture; - -/** A photo filter based on Photoshop action by Miss Etikate: - http://miss-etikate.deviantart.com/art/Photoshop-Action-15-120151961 - */ - -// Note: If you want to use this effect you have to add lookup_miss_etikate.png -// from Resources folder to your application bundle. - -@interface GPUImageMissEtikateFilter : GPUImageFilterGroup -{ - GPUImagePicture *lookupImageSource; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMissEtikateFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMissEtikateFilter.m deleted file mode 100755 index 1810b707..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMissEtikateFilter.m +++ /dev/null @@ -1,38 +0,0 @@ -#import "GPUImageMissEtikateFilter.h" -#import "GPUImagePicture.h" -#import "GPUImageLookupFilter.h" - -@implementation GPUImageMissEtikateFilter - -- (id)init; -{ - if (!(self = [super init])) - { - return nil; - } - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - UIImage *image = [UIImage imageNamed:@"lookup_miss_etikate.png"]; -#else - NSImage *image = [NSImage imageNamed:@"lookup_miss_etikate.png"]; -#endif - - NSAssert(image, @"To use GPUImageMissEtikateFilter you need to add lookup_miss_etikate.png from GPUImage/framework/Resources to your application bundle."); - - lookupImageSource = [[GPUImagePicture alloc] initWithImage:image]; - GPUImageLookupFilter *lookupFilter = [[GPUImageLookupFilter alloc] init]; - [self addFilter:lookupFilter]; - - [lookupImageSource addTarget:lookupFilter atTextureLocation:1]; - [lookupImageSource processImage]; - - self.initialFilters = [NSArray arrayWithObjects:lookupFilter, nil]; - self.terminalFilter = lookupFilter; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMonochromeFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMonochromeFilter.h deleted file mode 100644 index 66a0e773..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMonochromeFilter.h +++ /dev/null @@ -1,13 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageMonochromeFilter : GPUImageFilter -{ - GLint intensityUniform, filterColorUniform; -} - -@property(readwrite, nonatomic) CGFloat intensity; -@property(readwrite, nonatomic) GPUVector4 color; - -- (void)setColorRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMonochromeFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMonochromeFilter.m deleted file mode 100644 index 70cef872..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMonochromeFilter.m +++ /dev/null @@ -1,115 +0,0 @@ -#import "GPUImageMonochromeFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUMonochromeFragmentShaderString = SHADER_STRING -( - precision lowp float; - - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float intensity; - uniform vec3 filterColor; - - const mediump vec3 luminanceWeighting = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - //desat, then apply overlay blend - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - float luminance = dot(textureColor.rgb, luminanceWeighting); - - lowp vec4 desat = vec4(vec3(luminance), 1.0); - - //overlay - lowp vec4 outputColor = vec4( - (desat.r < 0.5 ? (2.0 * desat.r * filterColor.r) : (1.0 - 2.0 * (1.0 - desat.r) * (1.0 - filterColor.r))), - (desat.g < 0.5 ? (2.0 * desat.g * filterColor.g) : (1.0 - 2.0 * (1.0 - desat.g) * (1.0 - filterColor.g))), - (desat.b < 0.5 ? (2.0 * desat.b * filterColor.b) : (1.0 - 2.0 * (1.0 - desat.b) * (1.0 - filterColor.b))), - 1.0 - ); - - //which is better, or are they equal? - gl_FragColor = vec4( mix(textureColor.rgb, outputColor.rgb, intensity), textureColor.a); - } -); -#else -NSString *const kGPUMonochromeFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float intensity; - uniform vec3 filterColor; - - const vec3 luminanceWeighting = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - //desat, then apply overlay blend - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - float luminance = dot(textureColor.rgb, luminanceWeighting); - - vec4 desat = vec4(vec3(luminance), 1.0); - - //overlay - vec4 outputColor = vec4( - (desat.r < 0.5 ? (2.0 * desat.r * filterColor.r) : (1.0 - 2.0 * (1.0 - desat.r) * (1.0 - filterColor.r))), - (desat.g < 0.5 ? (2.0 * desat.g * filterColor.g) : (1.0 - 2.0 * (1.0 - desat.g) * (1.0 - filterColor.g))), - (desat.b < 0.5 ? (2.0 * desat.b * filterColor.b) : (1.0 - 2.0 * (1.0 - desat.b) * (1.0 - filterColor.b))), - 1.0 - ); - - //which is better, or are they equal? - gl_FragColor = vec4( mix(textureColor.rgb, outputColor.rgb, intensity), textureColor.a); - } -); -#endif - -@implementation GPUImageMonochromeFilter - -@synthesize intensity = _intensity; -@synthesize color = _color; - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUMonochromeFragmentShaderString])) - { - return nil; - } - - intensityUniform = [filterProgram uniformIndex:@"intensity"]; - filterColorUniform = [filterProgram uniformIndex:@"filterColor"]; - - self.intensity = 1.0; - self.color = (GPUVector4){0.6f, 0.45f, 0.3f, 1.f}; - //self.color = [CIColor colorWithRed:0.6 green:0.45 blue:0.3 alpha:1.]; - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setColor:(GPUVector4)color; -{ - - _color = color; - - [self setColorRed:color.one green:color.two blue:color.three]; -} - -- (void)setColorRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent; -{ - GPUVector3 filterColor = {redComponent, greenComponent, blueComponent}; - - [self setVec3:filterColor forUniform:filterColorUniform program:filterProgram]; -} - -- (void)setIntensity:(CGFloat)newValue; -{ - _intensity = newValue; - - [self setFloat:_intensity forUniform:intensityUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMosaicFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMosaicFilter.h deleted file mode 100644 index 5f72d3c9..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMosaicFilter.h +++ /dev/null @@ -1,22 +0,0 @@ - -// This needs a little more work, it's rotating the input tileset and there are some artifacts (I think from GL_LINEAR interpolation), but it's working - -#import "GPUImageTwoInputFilter.h" -#import "GPUImagePicture.h" - -@interface GPUImageMosaicFilter : GPUImageTwoInputFilter { - GLint inputTileSizeUniform, numTilesUniform, displayTileSizeUniform, colorOnUniform; - GPUImagePicture *pic; -} - -// This filter takes an input tileset, the tiles must ascend in luminance -// It looks at the input image and replaces each display tile with an input tile -// according to the luminance of that tile. The idea was to replicate the ASCII -// video filters seen in other apps, but the tileset can be anything. -@property(readwrite, nonatomic) CGSize inputTileSize; -@property(readwrite, nonatomic) float numTiles; -@property(readwrite, nonatomic) CGSize displayTileSize; -@property(readwrite, nonatomic) BOOL colorOn; -@property(readwrite, nonatomic, copy) NSString *tileSet; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMosaicFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMosaicFilter.m deleted file mode 100644 index b017ca97..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMosaicFilter.m +++ /dev/null @@ -1,188 +0,0 @@ -// -// GPUImageMosaicFilter.m - - -#import "GPUImageMosaicFilter.h" -#import "GPUImagePicture.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageMosaicFragmentShaderString = SHADER_STRING -( - precision highp float; - - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - uniform vec2 inputTileSize; - uniform vec2 displayTileSize; - uniform float numTiles; - uniform int colorOn; - - void main() - { - vec2 xy = textureCoordinate; - xy = xy - mod(xy, displayTileSize); - - vec4 lumcoeff = vec4(0.299,0.587,0.114,0.0); - - vec4 inputColor = texture2D(inputImageTexture2, xy); - float lum = dot(inputColor,lumcoeff); - lum = 1.0 - lum; - - float stepsize = 1.0 / numTiles; - float lumStep = (lum - mod(lum, stepsize)) / stepsize; - - float rowStep = 1.0 / inputTileSize.x; - float x = mod(lumStep, rowStep); - float y = floor(lumStep / rowStep); - - vec2 startCoord = vec2(float(x) * inputTileSize.x, float(y) * inputTileSize.y); - vec2 finalCoord = startCoord + ((textureCoordinate - xy) * (inputTileSize / displayTileSize)); - - vec4 color = texture2D(inputImageTexture, finalCoord); - if (colorOn == 1) { - color = color * inputColor; - } - gl_FragColor = color; - - } -); -#else -NSString *const kGPUImageMosaicFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - uniform vec2 inputTileSize; - uniform vec2 displayTileSize; - uniform float numTiles; - uniform int colorOn; - - void main() - { - vec2 xy = textureCoordinate; - xy = xy - mod(xy, displayTileSize); - - vec4 lumcoeff = vec4(0.299,0.587,0.114,0.0); - - vec4 inputColor = texture2D(inputImageTexture2, xy); - float lum = dot(inputColor,lumcoeff); - lum = 1.0 - lum; - - float stepsize = 1.0 / numTiles; - float lumStep = (lum - mod(lum, stepsize)) / stepsize; - - float rowStep = 1.0 / inputTileSize.x; - float x = mod(lumStep, rowStep); - float y = floor(lumStep / rowStep); - - vec2 startCoord = vec2(float(x) * inputTileSize.x, float(y) * inputTileSize.y); - vec2 finalCoord = startCoord + ((textureCoordinate - xy) * (inputTileSize / displayTileSize)); - - vec4 color = texture2D(inputImageTexture, finalCoord); - if (colorOn == 1) { - color = color * inputColor; - } - gl_FragColor = color; - } -); -#endif - -@implementation GPUImageMosaicFilter - -@synthesize inputTileSize = _inputTileSize, numTiles = _numTiles, displayTileSize = _displayTileSize, colorOn = _colorOn; -@synthesize tileSet = _tileSet; - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageMosaicFragmentShaderString])) - { - return nil; - } - - inputTileSizeUniform = [filterProgram uniformIndex:@"inputTileSize"]; - displayTileSizeUniform = [filterProgram uniformIndex:@"displayTileSize"]; - numTilesUniform = [filterProgram uniformIndex:@"numTiles"]; - colorOnUniform = [filterProgram uniformIndex:@"colorOn"]; - - CGSize its = CGSizeMake(0.125, 0.125); - CGSize dts = CGSizeMake(0.025, 0.025); - [self setDisplayTileSize:dts]; - [self setInputTileSize:its]; - [self setNumTiles:64.0]; - [self setColorOn:YES]; - //[self setTileSet:@"squares.png"]; - return self; -} - -- (void)setColorOn:(BOOL)yes -{ - glUniform1i(colorOnUniform, yes); -} - -- (void)setNumTiles:(float)numTiles -{ - - _numTiles = numTiles; - [self setFloat:_numTiles forUniformName:@"numTiles"]; -} - -- (void)setInputTileSize:(CGSize)inputTileSize -{ - if (inputTileSize.width > 1.0) { - _inputTileSize.width = 1.0; - } - if (inputTileSize.height > 1.0) { - _inputTileSize.height = 1.0; - } - if (inputTileSize.width < 0.0) { - _inputTileSize.width = 0.0; - } - if (inputTileSize.height < 0.0) { - _inputTileSize.height = 0.0; - } - - - _inputTileSize = inputTileSize; - - [self setSize:_inputTileSize forUniform:inputTileSizeUniform program:filterProgram]; -} - --(void)setDisplayTileSize:(CGSize)displayTileSize -{ - if (displayTileSize.width > 1.0) { - _displayTileSize.width = 1.0; - } - if (displayTileSize.height > 1.0) { - _displayTileSize.height = 1.0; - } - if (displayTileSize.width < 0.0) { - _displayTileSize.width = 0.0; - } - if (displayTileSize.height < 0.0) { - _displayTileSize.height = 0.0; - } - - - _displayTileSize = displayTileSize; - - [self setSize:_displayTileSize forUniform:displayTileSizeUniform program:filterProgram]; -} - --(void)setTileSet:(NSString *)tileSet -{ -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - UIImage *img = [UIImage imageNamed:tileSet]; -#else - NSImage *img = [NSImage imageNamed:tileSet]; -#endif - pic = [[GPUImagePicture alloc] initWithImage:img smoothlyScaleOutput:YES]; - [pic addTarget:self]; - [pic processImage]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMotionBlurFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMotionBlurFilter.h deleted file mode 100644 index dcca712f..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMotionBlurFilter.h +++ /dev/null @@ -1,13 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageMotionBlurFilter : GPUImageFilter - -/** A multiplier for the blur size, ranging from 0.0 on up, with a default of 1.0 - */ -@property (readwrite, nonatomic) CGFloat blurSize; - -/** The angular direction of the blur, in degrees. 0 degrees by default - */ -@property (readwrite, nonatomic) CGFloat blurAngle; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMotionBlurFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMotionBlurFilter.m deleted file mode 100644 index 5a2c20b6..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMotionBlurFilter.m +++ /dev/null @@ -1,209 +0,0 @@ -#import "GPUImageMotionBlurFilter.h" - -// Override vertex shader to remove dependent texture reads -NSString *const kGPUImageTiltedTexelSamplingVertexShaderString = SHADER_STRING -( - attribute vec4 position; - attribute vec4 inputTextureCoordinate; - - uniform vec2 directionalTexelStep; - - varying vec2 textureCoordinate; - varying vec2 oneStepBackTextureCoordinate; - varying vec2 twoStepsBackTextureCoordinate; - varying vec2 threeStepsBackTextureCoordinate; - varying vec2 fourStepsBackTextureCoordinate; - varying vec2 oneStepForwardTextureCoordinate; - varying vec2 twoStepsForwardTextureCoordinate; - varying vec2 threeStepsForwardTextureCoordinate; - varying vec2 fourStepsForwardTextureCoordinate; - - void main() - { - gl_Position = position; - - textureCoordinate = inputTextureCoordinate.xy; - oneStepBackTextureCoordinate = inputTextureCoordinate.xy - directionalTexelStep; - twoStepsBackTextureCoordinate = inputTextureCoordinate.xy - 2.0 * directionalTexelStep; - threeStepsBackTextureCoordinate = inputTextureCoordinate.xy - 3.0 * directionalTexelStep; - fourStepsBackTextureCoordinate = inputTextureCoordinate.xy - 4.0 * directionalTexelStep; - oneStepForwardTextureCoordinate = inputTextureCoordinate.xy + directionalTexelStep; - twoStepsForwardTextureCoordinate = inputTextureCoordinate.xy + 2.0 * directionalTexelStep; - threeStepsForwardTextureCoordinate = inputTextureCoordinate.xy + 3.0 * directionalTexelStep; - fourStepsForwardTextureCoordinate = inputTextureCoordinate.xy + 4.0 * directionalTexelStep; - } -); - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageMotionBlurFragmentShaderString = SHADER_STRING -( - precision highp float; - - uniform sampler2D inputImageTexture; - - varying vec2 textureCoordinate; - varying vec2 oneStepBackTextureCoordinate; - varying vec2 twoStepsBackTextureCoordinate; - varying vec2 threeStepsBackTextureCoordinate; - varying vec2 fourStepsBackTextureCoordinate; - varying vec2 oneStepForwardTextureCoordinate; - varying vec2 twoStepsForwardTextureCoordinate; - varying vec2 threeStepsForwardTextureCoordinate; - varying vec2 fourStepsForwardTextureCoordinate; - - void main() - { - // Box weights -// lowp vec4 fragmentColor = texture2D(inputImageTexture, textureCoordinate) * 0.1111111; -// fragmentColor += texture2D(inputImageTexture, oneStepBackTextureCoordinate) * 0.1111111; -// fragmentColor += texture2D(inputImageTexture, twoStepsBackTextureCoordinate) * 0.1111111; -// fragmentColor += texture2D(inputImageTexture, threeStepsBackTextureCoordinate) * 0.1111111; -// fragmentColor += texture2D(inputImageTexture, fourStepsBackTextureCoordinate) * 0.1111111; -// fragmentColor += texture2D(inputImageTexture, oneStepForwardTextureCoordinate) * 0.1111111; -// fragmentColor += texture2D(inputImageTexture, twoStepsForwardTextureCoordinate) * 0.1111111; -// fragmentColor += texture2D(inputImageTexture, threeStepsForwardTextureCoordinate) * 0.1111111; -// fragmentColor += texture2D(inputImageTexture, fourStepsForwardTextureCoordinate) * 0.1111111; - - lowp vec4 fragmentColor = texture2D(inputImageTexture, textureCoordinate) * 0.18; - fragmentColor += texture2D(inputImageTexture, oneStepBackTextureCoordinate) * 0.15; - fragmentColor += texture2D(inputImageTexture, twoStepsBackTextureCoordinate) * 0.12; - fragmentColor += texture2D(inputImageTexture, threeStepsBackTextureCoordinate) * 0.09; - fragmentColor += texture2D(inputImageTexture, fourStepsBackTextureCoordinate) * 0.05; - fragmentColor += texture2D(inputImageTexture, oneStepForwardTextureCoordinate) * 0.15; - fragmentColor += texture2D(inputImageTexture, twoStepsForwardTextureCoordinate) * 0.12; - fragmentColor += texture2D(inputImageTexture, threeStepsForwardTextureCoordinate) * 0.09; - fragmentColor += texture2D(inputImageTexture, fourStepsForwardTextureCoordinate) * 0.05; - - gl_FragColor = fragmentColor; - } -); -#else -NSString *const kGPUImageMotionBlurFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - - varying vec2 textureCoordinate; - varying vec2 oneStepBackTextureCoordinate; - varying vec2 twoStepsBackTextureCoordinate; - varying vec2 threeStepsBackTextureCoordinate; - varying vec2 fourStepsBackTextureCoordinate; - varying vec2 oneStepForwardTextureCoordinate; - varying vec2 twoStepsForwardTextureCoordinate; - varying vec2 threeStepsForwardTextureCoordinate; - varying vec2 fourStepsForwardTextureCoordinate; - - void main() - { - // Box weights - // vec4 fragmentColor = texture2D(inputImageTexture, textureCoordinate) * 0.1111111; - // fragmentColor += texture2D(inputImageTexture, oneStepBackTextureCoordinate) * 0.1111111; - // fragmentColor += texture2D(inputImageTexture, twoStepsBackTextureCoordinate) * 0.1111111; - // fragmentColor += texture2D(inputImageTexture, threeStepsBackTextureCoordinate) * 0.1111111; - // fragmentColor += texture2D(inputImageTexture, fourStepsBackTextureCoordinate) * 0.1111111; - // fragmentColor += texture2D(inputImageTexture, oneStepForwardTextureCoordinate) * 0.1111111; - // fragmentColor += texture2D(inputImageTexture, twoStepsForwardTextureCoordinate) * 0.1111111; - // fragmentColor += texture2D(inputImageTexture, threeStepsForwardTextureCoordinate) * 0.1111111; - // fragmentColor += texture2D(inputImageTexture, fourStepsForwardTextureCoordinate) * 0.1111111; - - vec4 fragmentColor = texture2D(inputImageTexture, textureCoordinate) * 0.18; - fragmentColor += texture2D(inputImageTexture, oneStepBackTextureCoordinate) * 0.15; - fragmentColor += texture2D(inputImageTexture, twoStepsBackTextureCoordinate) * 0.12; - fragmentColor += texture2D(inputImageTexture, threeStepsBackTextureCoordinate) * 0.09; - fragmentColor += texture2D(inputImageTexture, fourStepsBackTextureCoordinate) * 0.05; - fragmentColor += texture2D(inputImageTexture, oneStepForwardTextureCoordinate) * 0.15; - fragmentColor += texture2D(inputImageTexture, twoStepsForwardTextureCoordinate) * 0.12; - fragmentColor += texture2D(inputImageTexture, threeStepsForwardTextureCoordinate) * 0.09; - fragmentColor += texture2D(inputImageTexture, fourStepsForwardTextureCoordinate) * 0.05; - - gl_FragColor = fragmentColor; - } -); -#endif - -@interface GPUImageMotionBlurFilter() -{ - GLint directionalTexelStepUniform; -} - -- (void)recalculateTexelOffsets; - -@end - -@implementation GPUImageMotionBlurFilter - -@synthesize blurSize = _blurSize; -@synthesize blurAngle = _blurAngle; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithVertexShaderFromString:kGPUImageTiltedTexelSamplingVertexShaderString fragmentShaderFromString:kGPUImageMotionBlurFragmentShaderString])) - { - return nil; - } - - directionalTexelStepUniform = [filterProgram uniformIndex:@"directionalTexelStep"]; - - self.blurSize = 2.5; - self.blurAngle = 0.0; - - return self; -} - -- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex; -{ - CGSize oldInputSize = inputTextureSize; - [super setInputSize:newSize atIndex:textureIndex]; - - if (!CGSizeEqualToSize(oldInputSize, inputTextureSize) && (!CGSizeEqualToSize(newSize, CGSizeZero)) ) - { - [self recalculateTexelOffsets]; - } -} - -- (void)recalculateTexelOffsets; -{ - CGFloat aspectRatio = 1.0; - CGPoint texelOffsets; - - if (GPUImageRotationSwapsWidthAndHeight(inputRotation)) - { - aspectRatio = (inputTextureSize.width / inputTextureSize.height); - texelOffsets.x = _blurSize * sin(_blurAngle * M_PI / 180.0) * aspectRatio / inputTextureSize.height; - texelOffsets.y = _blurSize * cos(_blurAngle * M_PI / 180.0) / inputTextureSize.height; - } - else - { - aspectRatio = (inputTextureSize.height / inputTextureSize.width); - texelOffsets.x = _blurSize * cos(_blurAngle * M_PI / 180.0) * aspectRatio / inputTextureSize.width; - texelOffsets.y = _blurSize * sin(_blurAngle * M_PI / 180.0) / inputTextureSize.width; - } - - [self setPoint:texelOffsets forUniform:directionalTexelStepUniform program:filterProgram]; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -{ - [super setInputRotation:newInputRotation atIndex:textureIndex]; - [self recalculateTexelOffsets]; -} - -- (void)setBlurAngle:(CGFloat)newValue; -{ - _blurAngle = newValue; - [self recalculateTexelOffsets]; -} - -- (void)setBlurSize:(CGFloat)newValue; -{ - _blurSize = newValue; - [self recalculateTexelOffsets]; -} - - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMotionDetector.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMotionDetector.h deleted file mode 100644 index 01329145..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMotionDetector.h +++ /dev/null @@ -1,18 +0,0 @@ -#import "GPUImageFilterGroup.h" -#import "GPUImageLowPassFilter.h" -#import "GPUImageAverageColor.h" - -@interface GPUImageMotionDetector : GPUImageFilterGroup -{ - GPUImageLowPassFilter *lowPassFilter; - GPUImageTwoInputFilter *frameComparisonFilter; - GPUImageAverageColor *averageColor; -} - -// This controls the low pass filter strength used to compare the current frame with previous ones to detect motion. This ranges from 0.0 to 1.0, with a default of 0.5. -@property(readwrite, nonatomic) CGFloat lowPassFilterStrength; - -// For every frame, this will feed back the calculated centroid of the motion, as well as a relative intensity. -@property(nonatomic, copy) void(^motionDetectionBlock)(CGPoint motionCentroid, CGFloat motionIntensity, CMTime frameTime); - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMotionDetector.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMotionDetector.m deleted file mode 100644 index 0e204ad7..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMotionDetector.m +++ /dev/null @@ -1,112 +0,0 @@ -#import "GPUImageMotionDetector.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageMotionComparisonFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - uniform highp float intensity; - - void main() - { - lowp vec3 currentImageColor = texture2D(inputImageTexture, textureCoordinate).rgb; - lowp vec3 lowPassImageColor = texture2D(inputImageTexture2, textureCoordinate2).rgb; - - mediump float colorDistance = distance(currentImageColor, lowPassImageColor); // * 0.57735 - lowp float movementThreshold = step(0.2, colorDistance); - - gl_FragColor = movementThreshold * vec4(textureCoordinate2.x, textureCoordinate2.y, 1.0, 1.0); - } -); -#else -NSString *const kGPUImageMotionComparisonFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - uniform float intensity; - - void main() - { - vec3 currentImageColor = texture2D(inputImageTexture, textureCoordinate).rgb; - vec3 lowPassImageColor = texture2D(inputImageTexture2, textureCoordinate2).rgb; - - float colorDistance = distance(currentImageColor, lowPassImageColor); // * 0.57735 - float movementThreshold = step(0.2, colorDistance); - - gl_FragColor = movementThreshold * vec4(textureCoordinate2.x, textureCoordinate2.y, 1.0, 1.0); - } -); -#endif - - -@implementation GPUImageMotionDetector - -@synthesize lowPassFilterStrength, motionDetectionBlock; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super init])) - { - return nil; - } - - // Start with a low pass filter to define the component to be removed - lowPassFilter = [[GPUImageLowPassFilter alloc] init]; - [self addFilter:lowPassFilter]; - - // Take the difference of the current frame from the low pass filtered result to get the high pass - frameComparisonFilter = [[GPUImageTwoInputFilter alloc] initWithFragmentShaderFromString:kGPUImageMotionComparisonFragmentShaderString]; - [self addFilter:frameComparisonFilter]; - - // Texture location 0 needs to be the original image for the difference blend - [lowPassFilter addTarget:frameComparisonFilter atTextureLocation:1]; - - // End with the average color for the scene to determine the centroid - averageColor = [[GPUImageAverageColor alloc] init]; - - __unsafe_unretained GPUImageMotionDetector *weakSelf = self; - - [averageColor setColorAverageProcessingFinishedBlock:^(CGFloat redComponent, CGFloat greenComponent, CGFloat blueComponent, CGFloat alphaComponent, CMTime frameTime) { - if (weakSelf.motionDetectionBlock != NULL) - { - weakSelf.motionDetectionBlock(CGPointMake(redComponent / alphaComponent, greenComponent / alphaComponent), alphaComponent, frameTime); - } -// NSLog(@"Average X: %f, Y: %f total: %f", redComponent / alphaComponent, greenComponent / alphaComponent, alphaComponent); - }]; - - [frameComparisonFilter addTarget:averageColor]; - - self.initialFilters = [NSArray arrayWithObjects:lowPassFilter, frameComparisonFilter, nil]; - self.terminalFilter = frameComparisonFilter; - - self.lowPassFilterStrength = 0.5; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setLowPassFilterStrength:(CGFloat)newValue; -{ - lowPassFilter.filterStrength = newValue; -} - -- (CGFloat)lowPassFilterStrength; -{ - return lowPassFilter.filterStrength; -} - - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMovie.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMovie.h deleted file mode 100755 index f61e56ef..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMovie.h +++ /dev/null @@ -1,61 +0,0 @@ -#import -#import -#import "GPUImageContext.h" -#import "GPUImageOutput.h" - -/** Protocol for getting Movie played callback. - */ -@protocol GPUImageMovieDelegate - -- (void)didCompletePlayingMovie; -@end - -/** Source object for filtering movies - */ -@interface GPUImageMovie : GPUImageOutput - -@property (readwrite, retain) AVAsset *asset; -@property (readwrite, retain) AVPlayerItem *playerItem; -@property(readwrite, retain) NSURL *url; - -/** This enables the benchmarking mode, which logs out instantaneous and average frame times to the console - */ -@property(readwrite, nonatomic) BOOL runBenchmark; - -/** This determines whether to play back a movie as fast as the frames can be processed, or if the original speed of the movie should be respected. Defaults to NO. - */ -@property(readwrite, nonatomic) BOOL playAtActualSpeed; - -/** This determines whether the video should repeat (loop) at the end and restart from the beginning. Defaults to NO. - */ -@property(readwrite, nonatomic) BOOL shouldRepeat; - -/** This specifies the progress of the process on a scale from 0 to 1.0. A value of 0 means the process has not yet begun, A value of 1.0 means the conversaion is complete. - This property is not key-value observable. - */ -@property(readonly, nonatomic) float progress; - -/** This is used to send the delete Movie did complete playing alert - */ -@property (readwrite, nonatomic, assign) id delegate; - -@property (readonly, nonatomic) AVAssetReader *assetReader; -@property (readonly, nonatomic) BOOL audioEncodingIsFinished; -@property (readonly, nonatomic) BOOL videoEncodingIsFinished; - -/// @name Initialization and teardown -- (id)initWithAsset:(AVAsset *)asset; -- (id)initWithPlayerItem:(AVPlayerItem *)playerItem; -- (id)initWithURL:(NSURL *)url; -- (void)yuvConversionSetup; - -/// @name Movie processing -- (void)enableSynchronizedEncodingUsingMovieWriter:(GPUImageMovieWriter *)movieWriter; -- (BOOL)readNextVideoFrameFromOutput:(AVAssetReaderOutput *)readerVideoTrackOutput; -- (BOOL)readNextAudioSampleFromOutput:(AVAssetReaderOutput *)readerAudioTrackOutput; -- (void)startProcessing; -- (void)endProcessing; -- (void)cancelProcessing; -- (void)processMovieFrame:(CMSampleBufferRef)movieSampleBuffer; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMovie.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMovie.m deleted file mode 100755 index d096b03e..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMovie.m +++ /dev/null @@ -1,761 +0,0 @@ -#import "GPUImageMovie.h" -#import "GPUImageMovieWriter.h" -#import "GPUImageFilter.h" -#import "GPUImageVideoCamera.h" - -@interface GPUImageMovie () -{ - BOOL audioEncodingIsFinished, videoEncodingIsFinished; - GPUImageMovieWriter *synchronizedMovieWriter; - AVAssetReader *reader; - AVPlayerItemVideoOutput *playerItemOutput; - CADisplayLink *displayLink; - CMTime previousFrameTime, processingFrameTime; - CFAbsoluteTime previousActualFrameTime; - BOOL keepLooping; - - GLuint luminanceTexture, chrominanceTexture; - - GLProgram *yuvConversionProgram; - GLint yuvConversionPositionAttribute, yuvConversionTextureCoordinateAttribute; - GLint yuvConversionLuminanceTextureUniform, yuvConversionChrominanceTextureUniform; - GLint yuvConversionMatrixUniform; - const GLfloat *_preferredConversion; - - BOOL isFullYUVRange; - - int imageBufferWidth, imageBufferHeight; -} - -- (void)processAsset; - -@end - -@implementation GPUImageMovie - -@synthesize url = _url; -@synthesize asset = _asset; -@synthesize runBenchmark = _runBenchmark; -@synthesize playAtActualSpeed = _playAtActualSpeed; -@synthesize delegate = _delegate; -@synthesize shouldRepeat = _shouldRepeat; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithURL:(NSURL *)url; -{ - if (!(self = [super init])) - { - return nil; - } - - [self yuvConversionSetup]; - - self.url = url; - self.asset = nil; - - return self; -} - -- (id)initWithAsset:(AVAsset *)asset; -{ - if (!(self = [super init])) - { - return nil; - } - - [self yuvConversionSetup]; - - self.url = nil; - self.asset = asset; - - return self; -} - -- (id)initWithPlayerItem:(AVPlayerItem *)playerItem; -{ - if (!(self = [super init])) - { - return nil; - } - - [self yuvConversionSetup]; - - self.url = nil; - self.asset = nil; - self.playerItem = playerItem; - - return self; -} - -- (void)yuvConversionSetup; -{ - if ([GPUImageContext supportsFastTextureUpload]) - { - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext useImageProcessingContext]; - - _preferredConversion = kColorConversion709; - isFullYUVRange = YES; - yuvConversionProgram = [[GPUImageContext sharedImageProcessingContext] programForVertexShaderString:kGPUImageVertexShaderString fragmentShaderString:kGPUImageYUVFullRangeConversionForLAFragmentShaderString]; - - if (!yuvConversionProgram.initialized) - { - [yuvConversionProgram addAttribute:@"position"]; - [yuvConversionProgram addAttribute:@"inputTextureCoordinate"]; - - if (![yuvConversionProgram link]) - { - NSString *progLog = [yuvConversionProgram programLog]; - NSLog(@"Program link log: %@", progLog); - NSString *fragLog = [yuvConversionProgram fragmentShaderLog]; - NSLog(@"Fragment shader compile log: %@", fragLog); - NSString *vertLog = [yuvConversionProgram vertexShaderLog]; - NSLog(@"Vertex shader compile log: %@", vertLog); - yuvConversionProgram = nil; - NSAssert(NO, @"Filter shader link failed"); - } - } - - yuvConversionPositionAttribute = [yuvConversionProgram attributeIndex:@"position"]; - yuvConversionTextureCoordinateAttribute = [yuvConversionProgram attributeIndex:@"inputTextureCoordinate"]; - yuvConversionLuminanceTextureUniform = [yuvConversionProgram uniformIndex:@"luminanceTexture"]; - yuvConversionChrominanceTextureUniform = [yuvConversionProgram uniformIndex:@"chrominanceTexture"]; - yuvConversionMatrixUniform = [yuvConversionProgram uniformIndex:@"colorConversionMatrix"]; - - [GPUImageContext setActiveShaderProgram:yuvConversionProgram]; - - glEnableVertexAttribArray(yuvConversionPositionAttribute); - glEnableVertexAttribArray(yuvConversionTextureCoordinateAttribute); - }); - } -} - -- (void)dealloc -{ - // Moved into endProcessing - //if (self.playerItem && (displayLink != nil)) - //{ - // [displayLink invalidate]; // remove from all run loops - // displayLink = nil; - //} -} - -#pragma mark - -#pragma mark Movie processing - -- (void)enableSynchronizedEncodingUsingMovieWriter:(GPUImageMovieWriter *)movieWriter; -{ - synchronizedMovieWriter = movieWriter; - movieWriter.encodingLiveVideo = NO; -} - -- (void)startProcessing -{ - if( self.playerItem ) { - [self processPlayerItem]; - return; - } - if(self.url == nil) - { - [self processAsset]; - return; - } - - if (_shouldRepeat) keepLooping = YES; - - previousFrameTime = kCMTimeZero; - previousActualFrameTime = CFAbsoluteTimeGetCurrent(); - - NSDictionary *inputOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:AVURLAssetPreferPreciseDurationAndTimingKey]; - AVURLAsset *inputAsset = [[AVURLAsset alloc] initWithURL:self.url options:inputOptions]; - - GPUImageMovie __block *blockSelf = self; - - [inputAsset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:@"tracks"] completionHandler: ^{ - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - NSError *error = nil; - AVKeyValueStatus tracksStatus = [inputAsset statusOfValueForKey:@"tracks" error:&error]; - if (tracksStatus != AVKeyValueStatusLoaded) - { - return; - } - blockSelf.asset = inputAsset; - [blockSelf processAsset]; - blockSelf = nil; - }); - }]; -} - -- (AVAssetReader*)createAssetReader -{ - NSError *error = nil; - AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:self.asset error:&error]; - - NSMutableDictionary *outputSettings = [NSMutableDictionary dictionary]; - if ([GPUImageContext supportsFastTextureUpload]) { - [outputSettings setObject:@(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) forKey:(id)kCVPixelBufferPixelFormatTypeKey]; - isFullYUVRange = YES; - } - else { - [outputSettings setObject:@(kCVPixelFormatType_32BGRA) forKey:(id)kCVPixelBufferPixelFormatTypeKey]; - isFullYUVRange = NO; - } - - // Maybe set alwaysCopiesSampleData to NO on iOS 5.0 for faster video decoding - AVAssetReaderTrackOutput *readerVideoTrackOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:[[self.asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] outputSettings:outputSettings]; - readerVideoTrackOutput.alwaysCopiesSampleData = NO; - [assetReader addOutput:readerVideoTrackOutput]; - - NSArray *audioTracks = [self.asset tracksWithMediaType:AVMediaTypeAudio]; - BOOL shouldRecordAudioTrack = (([audioTracks count] > 0) && (self.audioEncodingTarget != nil) ); - AVAssetReaderTrackOutput *readerAudioTrackOutput = nil; - - if (shouldRecordAudioTrack) - { - [self.audioEncodingTarget setShouldInvalidateAudioSampleWhenDone:YES]; - - // This might need to be extended to handle movies with more than one audio track - AVAssetTrack* audioTrack = [audioTracks objectAtIndex:0]; - readerAudioTrackOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:audioTrack outputSettings:nil]; - readerAudioTrackOutput.alwaysCopiesSampleData = NO; - [assetReader addOutput:readerAudioTrackOutput]; - } - - return assetReader; -} - -- (void)processAsset -{ - reader = [self createAssetReader]; - - AVAssetReaderOutput *readerVideoTrackOutput = nil; - AVAssetReaderOutput *readerAudioTrackOutput = nil; - - audioEncodingIsFinished = YES; - for( AVAssetReaderOutput *output in reader.outputs ) { - if( [output.mediaType isEqualToString:AVMediaTypeAudio] ) { - audioEncodingIsFinished = NO; - readerAudioTrackOutput = output; - } - else if( [output.mediaType isEqualToString:AVMediaTypeVideo] ) { - readerVideoTrackOutput = output; - } - } - - if ([reader startReading] == NO) - { - NSLog(@"Error reading from file at URL: %@", self.url); - return; - } - - __unsafe_unretained GPUImageMovie *weakSelf = self; - - if (synchronizedMovieWriter != nil) - { - [synchronizedMovieWriter setVideoInputReadyCallback:^{ - return [weakSelf readNextVideoFrameFromOutput:readerVideoTrackOutput]; - }]; - - [synchronizedMovieWriter setAudioInputReadyCallback:^{ - return [weakSelf readNextAudioSampleFromOutput:readerAudioTrackOutput]; - }]; - - [synchronizedMovieWriter enableSynchronizationCallbacks]; - } - else - { - while (reader.status == AVAssetReaderStatusReading && (!_shouldRepeat || keepLooping)) - { - [weakSelf readNextVideoFrameFromOutput:readerVideoTrackOutput]; - - if ( (readerAudioTrackOutput) && (!audioEncodingIsFinished) ) - { - [weakSelf readNextAudioSampleFromOutput:readerAudioTrackOutput]; - } - - } - - if (reader.status == AVAssetReaderStatusCompleted) { - - [reader cancelReading]; - - if (keepLooping) { - reader = nil; - dispatch_async(dispatch_get_main_queue(), ^{ - [self startProcessing]; - }); - } else { - [weakSelf endProcessing]; - } - - } - } -} - -- (void)processPlayerItem -{ - runSynchronouslyOnVideoProcessingQueue(^{ - displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkCallback:)]; - [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; - [displayLink setPaused:YES]; - - dispatch_queue_t videoProcessingQueue = [GPUImageContext sharedContextQueue]; - NSMutableDictionary *pixBuffAttributes = [NSMutableDictionary dictionary]; - if ([GPUImageContext supportsFastTextureUpload]) { - [pixBuffAttributes setObject:@(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) forKey:(id)kCVPixelBufferPixelFormatTypeKey]; - } - else { - [pixBuffAttributes setObject:@(kCVPixelFormatType_32BGRA) forKey:(id)kCVPixelBufferPixelFormatTypeKey]; - } - playerItemOutput = [[AVPlayerItemVideoOutput alloc] initWithPixelBufferAttributes:pixBuffAttributes]; - [playerItemOutput setDelegate:self queue:videoProcessingQueue]; - - [_playerItem addOutput:playerItemOutput]; - [playerItemOutput requestNotificationOfMediaDataChangeWithAdvanceInterval:0.1]; - }); -} - -- (void)outputMediaDataWillChange:(AVPlayerItemOutput *)sender -{ - // Restart display link. - [displayLink setPaused:NO]; -} - -- (void)displayLinkCallback:(CADisplayLink *)sender -{ - /* - The callback gets called once every Vsync. - Using the display link's timestamp and duration we can compute the next time the screen will be refreshed, and copy the pixel buffer for that time - This pixel buffer can then be processed and later rendered on screen. - */ - // Calculate the nextVsync time which is when the screen will be refreshed next. - CFTimeInterval nextVSync = ([sender timestamp] + [sender duration]); - - CMTime outputItemTime = [playerItemOutput itemTimeForHostTime:nextVSync]; - - if ([playerItemOutput hasNewPixelBufferForItemTime:outputItemTime]) { - __unsafe_unretained GPUImageMovie *weakSelf = self; - CVPixelBufferRef pixelBuffer = [playerItemOutput copyPixelBufferForItemTime:outputItemTime itemTimeForDisplay:NULL]; - if( pixelBuffer ) - runSynchronouslyOnVideoProcessingQueue(^{ - [weakSelf processMovieFrame:pixelBuffer withSampleTime:outputItemTime]; - CFRelease(pixelBuffer); - }); - } -} - -- (BOOL)readNextVideoFrameFromOutput:(AVAssetReaderOutput *)readerVideoTrackOutput; -{ - if (reader.status == AVAssetReaderStatusReading && ! videoEncodingIsFinished) - { - CMSampleBufferRef sampleBufferRef = [readerVideoTrackOutput copyNextSampleBuffer]; - if (sampleBufferRef) - { - //NSLog(@"read a video frame: %@", CFBridgingRelease(CMTimeCopyDescription(kCFAllocatorDefault, CMSampleBufferGetOutputPresentationTimeStamp(sampleBufferRef)))); - if (_playAtActualSpeed) - { - // Do this outside of the video processing queue to not slow that down while waiting - CMTime currentSampleTime = CMSampleBufferGetOutputPresentationTimeStamp(sampleBufferRef); - CMTime differenceFromLastFrame = CMTimeSubtract(currentSampleTime, previousFrameTime); - CFAbsoluteTime currentActualTime = CFAbsoluteTimeGetCurrent(); - - CGFloat frameTimeDifference = CMTimeGetSeconds(differenceFromLastFrame); - CGFloat actualTimeDifference = currentActualTime - previousActualFrameTime; - - if (frameTimeDifference > actualTimeDifference) - { - usleep(1000000.0 * (frameTimeDifference - actualTimeDifference)); - } - - previousFrameTime = currentSampleTime; - previousActualFrameTime = CFAbsoluteTimeGetCurrent(); - } - - __unsafe_unretained GPUImageMovie *weakSelf = self; - runSynchronouslyOnVideoProcessingQueue(^{ - [weakSelf processMovieFrame:sampleBufferRef]; - CMSampleBufferInvalidate(sampleBufferRef); - CFRelease(sampleBufferRef); - }); - - return YES; - } - else - { - if (!keepLooping) { - videoEncodingIsFinished = YES; - if( videoEncodingIsFinished && audioEncodingIsFinished ) - [self endProcessing]; - } - } - } - else if (synchronizedMovieWriter != nil) - { - if (reader.status == AVAssetReaderStatusCompleted) - { - [self endProcessing]; - } - } - return NO; -} - -- (BOOL)readNextAudioSampleFromOutput:(AVAssetReaderOutput *)readerAudioTrackOutput; -{ - if (reader.status == AVAssetReaderStatusReading && ! audioEncodingIsFinished) - { - CMSampleBufferRef audioSampleBufferRef = [readerAudioTrackOutput copyNextSampleBuffer]; - if (audioSampleBufferRef) - { - //NSLog(@"read an audio frame: %@", CFBridgingRelease(CMTimeCopyDescription(kCFAllocatorDefault, CMSampleBufferGetOutputPresentationTimeStamp(audioSampleBufferRef)))); - [self.audioEncodingTarget processAudioBuffer:audioSampleBufferRef]; - CFRelease(audioSampleBufferRef); - return YES; - } - else - { - if (!keepLooping) { - audioEncodingIsFinished = YES; - if( videoEncodingIsFinished && audioEncodingIsFinished ) - [self endProcessing]; - } - } - } - else if (synchronizedMovieWriter != nil) - { - if (reader.status == AVAssetReaderStatusCompleted || reader.status == AVAssetReaderStatusFailed || - reader.status == AVAssetReaderStatusCancelled) - { - [self endProcessing]; - } - } - return NO; -} - -- (void)processMovieFrame:(CMSampleBufferRef)movieSampleBuffer; -{ -// CMTimeGetSeconds -// CMTimeSubtract - - CMTime currentSampleTime = CMSampleBufferGetOutputPresentationTimeStamp(movieSampleBuffer); - CVImageBufferRef movieFrame = CMSampleBufferGetImageBuffer(movieSampleBuffer); - - processingFrameTime = currentSampleTime; - [self processMovieFrame:movieFrame withSampleTime:currentSampleTime]; -} - -- (float)progress -{ - if ( AVAssetReaderStatusReading == reader.status ) - { - float current = processingFrameTime.value * 1.0f / processingFrameTime.timescale; - float duration = self.asset.duration.value * 1.0f / self.asset.duration.timescale; - return current / duration; - } - else if ( AVAssetReaderStatusCompleted == reader.status ) - { - return 1.f; - } - else - { - return 0.f; - } -} - -- (void)processMovieFrame:(CVPixelBufferRef)movieFrame withSampleTime:(CMTime)currentSampleTime -{ - int bufferHeight = (int) CVPixelBufferGetHeight(movieFrame); - int bufferWidth = (int) CVPixelBufferGetWidth(movieFrame); - - CFTypeRef colorAttachments = CVBufferGetAttachment(movieFrame, kCVImageBufferYCbCrMatrixKey, NULL); - if (colorAttachments != NULL) - { - if(CFStringCompare(colorAttachments, kCVImageBufferYCbCrMatrix_ITU_R_601_4, 0) == kCFCompareEqualTo) - { - if (isFullYUVRange) - { - _preferredConversion = kColorConversion601FullRange; - } - else - { - _preferredConversion = kColorConversion601; - } - } - else - { - _preferredConversion = kColorConversion709; - } - } - else - { - if (isFullYUVRange) - { - _preferredConversion = kColorConversion601FullRange; - } - else - { - _preferredConversion = kColorConversion601; - } - - } - - CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); - - // Fix issue 1580 - [GPUImageContext useImageProcessingContext]; - - if ([GPUImageContext supportsFastTextureUpload]) - { - CVOpenGLESTextureRef luminanceTextureRef = NULL; - CVOpenGLESTextureRef chrominanceTextureRef = NULL; - - // if (captureAsYUV && [GPUImageContext deviceSupportsRedTextures]) - if (CVPixelBufferGetPlaneCount(movieFrame) > 0) // Check for YUV planar inputs to do RGB conversion - { - - if ( (imageBufferWidth != bufferWidth) && (imageBufferHeight != bufferHeight) ) - { - imageBufferWidth = bufferWidth; - imageBufferHeight = bufferHeight; - } - - CVReturn err; - // Y-plane - glActiveTexture(GL_TEXTURE4); - if ([GPUImageContext deviceSupportsRedTextures]) - { - err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, [[GPUImageContext sharedImageProcessingContext] coreVideoTextureCache], movieFrame, NULL, GL_TEXTURE_2D, GL_LUMINANCE, bufferWidth, bufferHeight, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, &luminanceTextureRef); - } - else - { - err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, [[GPUImageContext sharedImageProcessingContext] coreVideoTextureCache], movieFrame, NULL, GL_TEXTURE_2D, GL_LUMINANCE, bufferWidth, bufferHeight, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, &luminanceTextureRef); - } - if (err) - { - NSLog(@"Error at CVOpenGLESTextureCacheCreateTextureFromImage %d", err); - } - - luminanceTexture = CVOpenGLESTextureGetName(luminanceTextureRef); - glBindTexture(GL_TEXTURE_2D, luminanceTexture); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - // UV-plane - glActiveTexture(GL_TEXTURE5); - if ([GPUImageContext deviceSupportsRedTextures]) - { - err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, [[GPUImageContext sharedImageProcessingContext] coreVideoTextureCache], movieFrame, NULL, GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, bufferWidth/2, bufferHeight/2, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 1, &chrominanceTextureRef); - } - else - { - err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, [[GPUImageContext sharedImageProcessingContext] coreVideoTextureCache], movieFrame, NULL, GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, bufferWidth/2, bufferHeight/2, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 1, &chrominanceTextureRef); - } - if (err) - { - NSLog(@"Error at CVOpenGLESTextureCacheCreateTextureFromImage %d", err); - } - - chrominanceTexture = CVOpenGLESTextureGetName(chrominanceTextureRef); - glBindTexture(GL_TEXTURE_2D, chrominanceTexture); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - -// if (!allTargetsWantMonochromeData) -// { - [self convertYUVToRGBOutput]; -// } - - for (id currentTarget in targets) - { - NSInteger indexOfObject = [targets indexOfObject:currentTarget]; - NSInteger targetTextureIndex = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; - [currentTarget setInputSize:CGSizeMake(bufferWidth, bufferHeight) atIndex:targetTextureIndex]; - [currentTarget setInputFramebuffer:outputFramebuffer atIndex:targetTextureIndex]; - } - - [outputFramebuffer unlock]; - - for (id currentTarget in targets) - { - NSInteger indexOfObject = [targets indexOfObject:currentTarget]; - NSInteger targetTextureIndex = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; - [currentTarget newFrameReadyAtTime:currentSampleTime atIndex:targetTextureIndex]; - } - - CVPixelBufferUnlockBaseAddress(movieFrame, 0); - CFRelease(luminanceTextureRef); - CFRelease(chrominanceTextureRef); - } - else - { - // TODO: Mesh this with the new framebuffer cache -// CVPixelBufferLockBaseAddress(movieFrame, 0); -// -// CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, coreVideoTextureCache, movieFrame, NULL, GL_TEXTURE_2D, GL_RGBA, bufferWidth, bufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0, &texture); -// -// if (!texture || err) { -// NSLog(@"Movie CVOpenGLESTextureCacheCreateTextureFromImage failed (error: %d)", err); -// NSAssert(NO, @"Camera failure"); -// return; -// } -// -// outputTexture = CVOpenGLESTextureGetName(texture); -// // glBindTexture(CVOpenGLESTextureGetTarget(texture), outputTexture); -// glBindTexture(GL_TEXTURE_2D, outputTexture); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); -// -// for (id currentTarget in targets) -// { -// NSInteger indexOfObject = [targets indexOfObject:currentTarget]; -// NSInteger targetTextureIndex = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; -// -// [currentTarget setInputSize:CGSizeMake(bufferWidth, bufferHeight) atIndex:targetTextureIndex]; -// [currentTarget setInputTexture:outputTexture atIndex:targetTextureIndex]; -// -// [currentTarget newFrameReadyAtTime:currentSampleTime atIndex:targetTextureIndex]; -// } -// -// CVPixelBufferUnlockBaseAddress(movieFrame, 0); -// CVOpenGLESTextureCacheFlush(coreVideoTextureCache, 0); -// CFRelease(texture); -// -// outputTexture = 0; - } - } - else - { - // Upload to texture - CVPixelBufferLockBaseAddress(movieFrame, 0); - - outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:CGSizeMake(bufferWidth, bufferHeight) textureOptions:self.outputTextureOptions onlyTexture:YES]; - - glBindTexture(GL_TEXTURE_2D, [outputFramebuffer texture]); - // Using BGRA extension to pull in video frame data directly - glTexImage2D(GL_TEXTURE_2D, - 0, - self.outputTextureOptions.internalFormat, - bufferWidth, - bufferHeight, - 0, - self.outputTextureOptions.format, - self.outputTextureOptions.type, - CVPixelBufferGetBaseAddress(movieFrame)); - - for (id currentTarget in targets) - { - NSInteger indexOfObject = [targets indexOfObject:currentTarget]; - NSInteger targetTextureIndex = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; - [currentTarget setInputSize:CGSizeMake(bufferWidth, bufferHeight) atIndex:targetTextureIndex]; - [currentTarget setInputFramebuffer:outputFramebuffer atIndex:targetTextureIndex]; - } - - [outputFramebuffer unlock]; - - for (id currentTarget in targets) - { - NSInteger indexOfObject = [targets indexOfObject:currentTarget]; - NSInteger targetTextureIndex = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; - [currentTarget newFrameReadyAtTime:currentSampleTime atIndex:targetTextureIndex]; - } - CVPixelBufferUnlockBaseAddress(movieFrame, 0); - } - - if (_runBenchmark) - { - CFAbsoluteTime currentFrameTime = (CFAbsoluteTimeGetCurrent() - startTime); - NSLog(@"Current frame time : %f ms", 1000.0 * currentFrameTime); - } -} - -- (void)endProcessing; -{ - keepLooping = NO; - [displayLink setPaused:YES]; - - for (id currentTarget in targets) - { - [currentTarget endProcessing]; - } - - if (synchronizedMovieWriter != nil) - { - [synchronizedMovieWriter setVideoInputReadyCallback:^{return NO;}]; - [synchronizedMovieWriter setAudioInputReadyCallback:^{return NO;}]; - } - - if (self.playerItem && (displayLink != nil)) - { - [displayLink invalidate]; // remove from all run loops - displayLink = nil; - } - - if ([self.delegate respondsToSelector:@selector(didCompletePlayingMovie)]) { - [self.delegate didCompletePlayingMovie]; - } - self.delegate = nil; -} - -- (void)cancelProcessing -{ - if (reader) { - [reader cancelReading]; - } - [self endProcessing]; -} - -- (void)convertYUVToRGBOutput; -{ - [GPUImageContext setActiveShaderProgram:yuvConversionProgram]; - outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:CGSizeMake(imageBufferWidth, imageBufferHeight) onlyTexture:NO]; - [outputFramebuffer activateFramebuffer]; - - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - static const GLfloat squareVertices[] = { - -1.0f, -1.0f, - 1.0f, -1.0f, - -1.0f, 1.0f, - 1.0f, 1.0f, - }; - - static const GLfloat textureCoordinates[] = { - 0.0f, 0.0f, - 1.0f, 0.0f, - 0.0f, 1.0f, - 1.0f, 1.0f, - }; - - glActiveTexture(GL_TEXTURE4); - glBindTexture(GL_TEXTURE_2D, luminanceTexture); - glUniform1i(yuvConversionLuminanceTextureUniform, 4); - - glActiveTexture(GL_TEXTURE5); - glBindTexture(GL_TEXTURE_2D, chrominanceTexture); - glUniform1i(yuvConversionChrominanceTextureUniform, 5); - - glUniformMatrix3fv(yuvConversionMatrixUniform, 1, GL_FALSE, _preferredConversion); - - glVertexAttribPointer(yuvConversionPositionAttribute, 2, GL_FLOAT, 0, 0, squareVertices); - glVertexAttribPointer(yuvConversionTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); -} - -- (AVAssetReader*)assetReader { - return reader; -} - -- (BOOL)audioEncodingIsFinished { - return audioEncodingIsFinished; -} - -- (BOOL)videoEncodingIsFinished { - return videoEncodingIsFinished; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMovieComposition.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMovieComposition.h deleted file mode 100644 index 00e43814..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMovieComposition.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// GPUImageMovieComposition.h -// Givit -// -// Created by Sean Meiners on 2013/01/25. -// -// - -#import "GPUImageMovie.h" - -@interface GPUImageMovieComposition : GPUImageMovie - -@property (readwrite, retain) AVComposition *compositon; -@property (readwrite, retain) AVVideoComposition *videoComposition; -@property (readwrite, retain) AVAudioMix *audioMix; - -- (id)initWithComposition:(AVComposition*)compositon - andVideoComposition:(AVVideoComposition*)videoComposition - andAudioMix:(AVAudioMix*)audioMix; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMovieComposition.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMovieComposition.m deleted file mode 100644 index 6138fffe..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMovieComposition.m +++ /dev/null @@ -1,70 +0,0 @@ -// -// GPUImageMovieComposition.m -// Givit -// -// Created by Sean Meiners on 2013/01/25. -// -// - -#import "GPUImageMovieComposition.h" -#import "GPUImageMovieWriter.h" - -@implementation GPUImageMovieComposition - -@synthesize compositon = _compositon; -@synthesize videoComposition = _videoComposition; -@synthesize audioMix = _audioMix; - -- (id)initWithComposition:(AVComposition*)compositon - andVideoComposition:(AVVideoComposition*)videoComposition - andAudioMix:(AVAudioMix*)audioMix { - if (!(self = [super init])) - { - return nil; - } - - [self yuvConversionSetup]; - - self.compositon = compositon; - self.videoComposition = videoComposition; - self.audioMix = audioMix; - - return self; -} - -- (AVAssetReader*)createAssetReader - { - //NSLog(@"creating reader from composition: %@, video: %@, audio: %@ with duration: %@", _compositon, _videoComposition, _audioMix, CFBridgingRelease(CMTimeCopyDescription(kCFAllocatorDefault, _compositon.duration))); - - NSError *error = nil; - AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:self.compositon error:&error]; - - NSDictionary *outputSettings = @{(id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange)}; - AVAssetReaderVideoCompositionOutput *readerVideoOutput = [AVAssetReaderVideoCompositionOutput assetReaderVideoCompositionOutputWithVideoTracks:[_compositon tracksWithMediaType:AVMediaTypeVideo] - videoSettings:outputSettings]; -#if ! TARGET_IPHONE_SIMULATOR - if( [_videoComposition isKindOfClass:[AVMutableVideoComposition class]] ) - [(AVMutableVideoComposition*)_videoComposition setRenderScale:1.0]; -#endif - readerVideoOutput.videoComposition = self.videoComposition; - readerVideoOutput.alwaysCopiesSampleData = NO; - [assetReader addOutput:readerVideoOutput]; - - NSArray *audioTracks = [_compositon tracksWithMediaType:AVMediaTypeAudio]; - BOOL shouldRecordAudioTrack = (([audioTracks count] > 0) && (self.audioEncodingTarget != nil) ); - AVAssetReaderAudioMixOutput *readerAudioOutput = nil; - - if (shouldRecordAudioTrack) - { - [self.audioEncodingTarget setShouldInvalidateAudioSampleWhenDone:YES]; - - readerAudioOutput = [AVAssetReaderAudioMixOutput assetReaderAudioMixOutputWithAudioTracks:audioTracks audioSettings:nil]; - readerAudioOutput.audioMix = self.audioMix; - readerAudioOutput.alwaysCopiesSampleData = NO; - [assetReader addOutput:readerAudioOutput]; - } - - return assetReader; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMultiplyBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMultiplyBlendFilter.h deleted file mode 100755 index 5ebc28bb..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMultiplyBlendFilter.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageMultiplyBlendFilter : GPUImageTwoInputFilter -{ -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMultiplyBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMultiplyBlendFilter.m deleted file mode 100755 index ed647072..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageMultiplyBlendFilter.m +++ /dev/null @@ -1,52 +0,0 @@ -#import "GPUImageMultiplyBlendFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageMultiplyBlendFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - lowp vec4 base = texture2D(inputImageTexture, textureCoordinate); - lowp vec4 overlayer = texture2D(inputImageTexture2, textureCoordinate2); - - gl_FragColor = overlayer * base + overlayer * (1.0 - base.a) + base * (1.0 - overlayer.a); - } -); -#else -NSString *const kGPUImageMultiplyBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 base = texture2D(inputImageTexture, textureCoordinate); - vec4 overlayer = texture2D(inputImageTexture2, textureCoordinate2); - - gl_FragColor = overlayer * base + overlayer * (1.0 - base.a) + base * (1.0 - overlayer.a); - } -); -#endif - -@implementation GPUImageMultiplyBlendFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageMultiplyBlendFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNobleCornerDetectionFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNobleCornerDetectionFilter.h deleted file mode 100644 index 963fd66a..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNobleCornerDetectionFilter.h +++ /dev/null @@ -1,12 +0,0 @@ -#import "GPUImageHarrisCornerDetectionFilter.h" - -/** Noble corner detector - - This is the Noble variant on the Harris detector, from - Alison Noble, "Descriptions of Image Surfaces", PhD thesis, Department of Engineering Science, Oxford University 1989, p45. -*/ - - -@interface GPUImageNobleCornerDetectionFilter : GPUImageHarrisCornerDetectionFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNobleCornerDetectionFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNobleCornerDetectionFilter.m deleted file mode 100644 index aa6b3041..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNobleCornerDetectionFilter.m +++ /dev/null @@ -1,74 +0,0 @@ -#import "GPUImageNobleCornerDetectionFilter.h" - -@implementation GPUImageNobleCornerDetectionFilter - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageNobleCornerDetectionFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform lowp float sensitivity; - - void main() - { - mediump vec3 derivativeElements = texture2D(inputImageTexture, textureCoordinate).rgb; - - mediump float derivativeSum = derivativeElements.x + derivativeElements.y; - - // R = (Ix^2 * Iy^2 - Ixy * Ixy) / (Ix^2 + Iy^2) - mediump float zElement = (derivativeElements.z * 2.0) - 1.0; - // mediump float harrisIntensity = (derivativeElements.x * derivativeElements.y - (derivativeElements.z * derivativeElements.z)) / (derivativeSum); - mediump float cornerness = (derivativeElements.x * derivativeElements.y - (zElement * zElement)) / (derivativeSum); - - // Original Harris detector - // R = Ix^2 * Iy^2 - Ixy * Ixy - k * (Ix^2 + Iy^2)^2 - // highp float harrisIntensity = derivativeElements.x * derivativeElements.y - (derivativeElements.z * derivativeElements.z) - harrisConstant * derivativeSum * derivativeSum; - - // gl_FragColor = vec4(vec3(harrisIntensity * 7.0), 1.0); - gl_FragColor = vec4(vec3(cornerness * sensitivity), 1.0); - } -); -#else -NSString *const kGPUImageNobleCornerDetectionFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float sensitivity; - - void main() - { - vec3 derivativeElements = texture2D(inputImageTexture, textureCoordinate).rgb; - - float derivativeSum = derivativeElements.x + derivativeElements.y; - - // R = (Ix^2 * Iy^2 - Ixy * Ixy) / (Ix^2 + Iy^2) - float zElement = (derivativeElements.z * 2.0) - 1.0; - // mediump float harrisIntensity = (derivativeElements.x * derivativeElements.y - (derivativeElements.z * derivativeElements.z)) / (derivativeSum); - float cornerness = (derivativeElements.x * derivativeElements.y - (zElement * zElement)) / (derivativeSum); - - // Original Harris detector - // R = Ix^2 * Iy^2 - Ixy * Ixy - k * (Ix^2 + Iy^2)^2 - // highp float harrisIntensity = derivativeElements.x * derivativeElements.y - (derivativeElements.z * derivativeElements.z) - harrisConstant * derivativeSum * derivativeSum; - - // gl_FragColor = vec4(vec3(harrisIntensity * 7.0), 1.0); - gl_FragColor = vec4(vec3(cornerness * sensitivity), 1.0); - } -); -#endif - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [self initWithCornerDetectionFragmentShader:kGPUImageNobleCornerDetectionFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNonMaximumSuppressionFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNonMaximumSuppressionFilter.h deleted file mode 100644 index fd8fe6d6..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNonMaximumSuppressionFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImage3x3TextureSamplingFilter.h" - -@interface GPUImageNonMaximumSuppressionFilter : GPUImage3x3TextureSamplingFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNonMaximumSuppressionFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNonMaximumSuppressionFilter.m deleted file mode 100644 index eaf7ce56..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNonMaximumSuppressionFilter.m +++ /dev/null @@ -1,107 +0,0 @@ -#import "GPUImageNonMaximumSuppressionFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageNonMaximumSuppressionFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - - varying highp vec2 textureCoordinate; - varying highp vec2 leftTextureCoordinate; - varying highp vec2 rightTextureCoordinate; - - varying highp vec2 topTextureCoordinate; - varying highp vec2 topLeftTextureCoordinate; - varying highp vec2 topRightTextureCoordinate; - - varying highp vec2 bottomTextureCoordinate; - varying highp vec2 bottomLeftTextureCoordinate; - varying highp vec2 bottomRightTextureCoordinate; - - void main() - { - lowp float bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate).r; - lowp float bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - lowp float bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - lowp vec4 centerColor = texture2D(inputImageTexture, textureCoordinate); - lowp float leftColor = texture2D(inputImageTexture, leftTextureCoordinate).r; - lowp float rightColor = texture2D(inputImageTexture, rightTextureCoordinate).r; - lowp float topColor = texture2D(inputImageTexture, topTextureCoordinate).r; - lowp float topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate).r; - lowp float topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - - // Use a tiebreaker for pixels to the left and immediately above this one - lowp float multiplier = 1.0 - step(centerColor.r, topColor); - multiplier = multiplier * (1.0 - step(centerColor.r, topLeftColor)); - multiplier = multiplier * (1.0 - step(centerColor.r, leftColor)); - multiplier = multiplier * (1.0 - step(centerColor.r, bottomLeftColor)); - - lowp float maxValue = max(centerColor.r, bottomColor); - maxValue = max(maxValue, bottomRightColor); - maxValue = max(maxValue, rightColor); - maxValue = max(maxValue, topRightColor); - - gl_FragColor = vec4((centerColor.rgb * step(maxValue, centerColor.r) * multiplier), 1.0); - } -); -#else -NSString *const kGPUImageNonMaximumSuppressionFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - void main() - { - float bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate).r; - float bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - float bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - vec4 centerColor = texture2D(inputImageTexture, textureCoordinate); - float leftColor = texture2D(inputImageTexture, leftTextureCoordinate).r; - float rightColor = texture2D(inputImageTexture, rightTextureCoordinate).r; - float topColor = texture2D(inputImageTexture, topTextureCoordinate).r; - float topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate).r; - float topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - - // Use a tiebreaker for pixels to the left and immediately above this one - float multiplier = 1.0 - step(centerColor.r, topColor); - multiplier = multiplier * (1.0 - step(centerColor.r, topLeftColor)); - multiplier = multiplier * (1.0 - step(centerColor.r, leftColor)); - multiplier = multiplier * (1.0 - step(centerColor.r, bottomLeftColor)); - - float maxValue = max(centerColor.r, bottomColor); - maxValue = max(maxValue, bottomRightColor); - maxValue = max(maxValue, rightColor); - maxValue = max(maxValue, topRightColor); - - gl_FragColor = vec4((centerColor.rgb * step(maxValue, centerColor.r) * multiplier), 1.0); - } -); -#endif - -@implementation GPUImageNonMaximumSuppressionFilter - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageNonMaximumSuppressionFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNormalBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNormalBlendFilter.h deleted file mode 100644 index ce5e22b4..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNormalBlendFilter.h +++ /dev/null @@ -1,8 +0,0 @@ -// Created by Jorge Garcia on 9/5/12. -// - -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageNormalBlendFilter : GPUImageTwoInputFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNormalBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNormalBlendFilter.m deleted file mode 100644 index f5b5069d..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageNormalBlendFilter.m +++ /dev/null @@ -1,96 +0,0 @@ -// Created by Jorge Garcia on 9/5/12. - -#import "GPUImageNormalBlendFilter.h" -/* - This equation is a simplification of the general blending equation. It assumes the destination color is opaque, and therefore drops the destination color's alpha term. - - D = C1 * C1a + C2 * C2a * (1 - C1a) - where D is the resultant color, C1 is the color of the first element, C1a is the alpha of the first element, C2 is the second element color, C2a is the alpha of the second element. The destination alpha is calculated with: - - Da = C1a + C2a * (1 - C1a) - The resultant color is premultiplied with the alpha. To restore the color to the unmultiplied values, just divide by Da, the resultant alpha. - - http://stackoverflow.com/questions/1724946/blend-mode-on-a-transparent-and-semi-transparent-background - - For some reason Photoshop behaves - D = C1 + C2 * C2a * (1 - C1a) - */ -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageNormalBlendFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - lowp vec4 c2 = texture2D(inputImageTexture, textureCoordinate); - lowp vec4 c1 = texture2D(inputImageTexture2, textureCoordinate2); - - lowp vec4 outputColor; - -// outputColor.r = c1.r + c2.r * c2.a * (1.0 - c1.a); -// outputColor.g = c1.g + c2.g * c2.a * (1.0 - c1.a); -// outputColor.b = c1.b + c2.b * c2.a * (1.0 - c1.a); -// outputColor.a = c1.a + c2.a * (1.0 - c1.a); - - lowp float a = c1.a + c2.a * (1.0 - c1.a); - lowp float alphaDivisor = a + step(a, 0.0); // Protect against a divide-by-zero blacking out things in the output - - outputColor.r = (c1.r * c1.a + c2.r * c2.a * (1.0 - c1.a))/alphaDivisor; - outputColor.g = (c1.g * c1.a + c2.g * c2.a * (1.0 - c1.a))/alphaDivisor; - outputColor.b = (c1.b * c1.a + c2.b * c2.a * (1.0 - c1.a))/alphaDivisor; - outputColor.a = a; - - gl_FragColor = outputColor; - } -); -#else -NSString *const kGPUImageNormalBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 c2 = texture2D(inputImageTexture, textureCoordinate); - vec4 c1 = texture2D(inputImageTexture2, textureCoordinate2); - - vec4 outputColor; - - // outputColor.r = c1.r + c2.r * c2.a * (1.0 - c1.a); - // outputColor.g = c1.g + c2.g * c2.a * (1.0 - c1.a); - // outputColor.b = c1.b + c2.b * c2.a * (1.0 - c1.a); - // outputColor.a = c1.a + c2.a * (1.0 - c1.a); - - float a = c1.a + c2.a * (1.0 - c1.a); - float alphaDivisor = a + step(a, 0.0); // Protect against a divide-by-zero blacking out things in the output - - outputColor.r = (c1.r * c1.a + c2.r * c2.a * (1.0 - c1.a))/alphaDivisor; - outputColor.g = (c1.g * c1.a + c2.g * c2.a * (1.0 - c1.a))/alphaDivisor; - outputColor.b = (c1.b * c1.a + c2.b * c2.a * (1.0 - c1.a))/alphaDivisor; - outputColor.a = a; - - gl_FragColor = outputColor; - } -); -#endif - -@implementation GPUImageNormalBlendFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageNormalBlendFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end \ No newline at end of file diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOpacityFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOpacityFilter.h deleted file mode 100644 index 826749fb..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOpacityFilter.h +++ /dev/null @@ -1,11 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageOpacityFilter : GPUImageFilter -{ - GLint opacityUniform; -} - -// Opacity ranges from 0.0 to 1.0, with 1.0 as the normal setting -@property(readwrite, nonatomic) CGFloat opacity; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOpacityFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOpacityFilter.m deleted file mode 100644 index b74acb60..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOpacityFilter.m +++ /dev/null @@ -1,65 +0,0 @@ -#import "GPUImageOpacityFilter.h" - -@implementation GPUImageOpacityFilter - -@synthesize opacity = _opacity; - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageOpacityFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform lowp float opacity; - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - gl_FragColor = vec4(textureColor.rgb, textureColor.a * opacity); - } -); -#else -NSString *const kGPUImageOpacityFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float opacity; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - gl_FragColor = vec4(textureColor.rgb, textureColor.a * opacity); - } -); -#endif - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageOpacityFragmentShaderString])) - { - return nil; - } - - opacityUniform = [filterProgram uniformIndex:@"opacity"]; - self.opacity = 1.0; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setOpacity:(CGFloat)newValue; -{ - _opacity = newValue; - - [self setFloat:_opacity forUniform:opacityUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOpeningFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOpeningFilter.h deleted file mode 100644 index 3e4f7545..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOpeningFilter.h +++ /dev/null @@ -1,19 +0,0 @@ -#import "GPUImageFilterGroup.h" - -@class GPUImageErosionFilter; -@class GPUImageDilationFilter; - -// A filter that first performs an erosion on the red channel of an image, followed by a dilation of the same radius. -// This helps to filter out smaller bright elements. - -@interface GPUImageOpeningFilter : GPUImageFilterGroup -{ - GPUImageErosionFilter *erosionFilter; - GPUImageDilationFilter *dilationFilter; -} - -@property(readwrite, nonatomic) CGFloat verticalTexelSpacing, horizontalTexelSpacing; - -- (id)initWithRadius:(NSUInteger)radius; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOpeningFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOpeningFilter.m deleted file mode 100644 index 4e7a5653..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOpeningFilter.m +++ /dev/null @@ -1,57 +0,0 @@ -#import "GPUImageOpeningFilter.h" -#import "GPUImageErosionFilter.h" -#import "GPUImageDilationFilter.h" - -@implementation GPUImageOpeningFilter - -@synthesize verticalTexelSpacing = _verticalTexelSpacing; -@synthesize horizontalTexelSpacing = _horizontalTexelSpacing; - -- (id)init; -{ - if (!(self = [self initWithRadius:1])) - { - return nil; - } - - return self; -} - -- (id)initWithRadius:(NSUInteger)radius; -{ - if (!(self = [super init])) - { - return nil; - } - - // First pass: erosion - erosionFilter = [[GPUImageErosionFilter alloc] initWithRadius:radius]; - [self addFilter:erosionFilter]; - - // Second pass: dilation - dilationFilter = [[GPUImageDilationFilter alloc] initWithRadius:radius]; - [self addFilter:dilationFilter]; - - [erosionFilter addTarget:dilationFilter]; - - self.initialFilters = [NSArray arrayWithObjects:erosionFilter, nil]; - self.terminalFilter = dilationFilter; - - return self; -} - -- (void)setVerticalTexelSpacing:(CGFloat)newValue; -{ - _verticalTexelSpacing = newValue; - erosionFilter.verticalTexelSpacing = newValue; - dilationFilter.verticalTexelSpacing = newValue; -} - -- (void)setHorizontalTexelSpacing:(CGFloat)newValue; -{ - _horizontalTexelSpacing = newValue; - erosionFilter.horizontalTexelSpacing = newValue; - dilationFilter.horizontalTexelSpacing = newValue; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOutput.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOutput.h deleted file mode 100755 index a1af54d7..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOutput.h +++ /dev/null @@ -1,127 +0,0 @@ -#import "GPUImageContext.h" -#import "GPUImageFramebuffer.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -#import -#else -// For now, just redefine this on the Mac -typedef NS_ENUM(NSInteger, UIImageOrientation) { - UIImageOrientationUp, // default orientation - UIImageOrientationDown, // 180 deg rotation - UIImageOrientationLeft, // 90 deg CCW - UIImageOrientationRight, // 90 deg CW - UIImageOrientationUpMirrored, // as above but image mirrored along other axis. horizontal flip - UIImageOrientationDownMirrored, // horizontal flip - UIImageOrientationLeftMirrored, // vertical flip - UIImageOrientationRightMirrored, // vertical flip -}; -#endif - -void runOnMainQueueWithoutDeadlocking(void (^block)(void)); -void runSynchronouslyOnVideoProcessingQueue(void (^block)(void)); -void runAsynchronouslyOnVideoProcessingQueue(void (^block)(void)); -void runSynchronouslyOnContextQueue(GPUImageContext *context, void (^block)(void)); -void runAsynchronouslyOnContextQueue(GPUImageContext *context, void (^block)(void)); -void reportAvailableMemoryForGPUImage(NSString *tag); - -@class GPUImageMovieWriter; - -/** GPUImage's base source object - - Images or frames of video are uploaded from source objects, which are subclasses of GPUImageOutput. These include: - - - GPUImageVideoCamera (for live video from an iOS camera) - - GPUImageStillCamera (for taking photos with the camera) - - GPUImagePicture (for still images) - - GPUImageMovie (for movies) - - Source objects upload still image frames to OpenGL ES as textures, then hand those textures off to the next objects in the processing chain. - */ -@interface GPUImageOutput : NSObject -{ - GPUImageFramebuffer *outputFramebuffer; - - NSMutableArray *targets, *targetTextureIndices; - - CGSize inputTextureSize, cachedMaximumOutputSize, forcedMaximumSize; - - BOOL overrideInputSize; - - BOOL allTargetsWantMonochromeData; - BOOL usingNextFrameForImageCapture; -} - -@property(readwrite, nonatomic) BOOL shouldSmoothlyScaleOutput; -@property(readwrite, nonatomic) BOOL shouldIgnoreUpdatesToThisTarget; -@property(readwrite, nonatomic, retain) GPUImageMovieWriter *audioEncodingTarget; -@property(readwrite, nonatomic, unsafe_unretained) id targetToIgnoreForUpdates; -@property(nonatomic, copy) void(^frameProcessingCompletionBlock)(GPUImageOutput*, CMTime); -@property(nonatomic) BOOL enabled; -@property(readwrite, nonatomic) GPUTextureOptions outputTextureOptions; - -/// @name Managing targets -- (void)setInputFramebufferForTarget:(id)target atIndex:(NSInteger)inputTextureIndex; -- (GPUImageFramebuffer *)framebufferForOutput; -- (void)removeOutputFramebuffer; -- (void)notifyTargetsAboutNewOutputTexture; - -/** Returns an array of the current targets. - */ -- (NSArray*)targets; - -/** Adds a target to receive notifications when new frames are available. - - The target will be asked for its next available texture. - - See [GPUImageInput newFrameReadyAtTime:] - - @param newTarget Target to be added - */ -- (void)addTarget:(id)newTarget; - -/** Adds a target to receive notifications when new frames are available. - - See [GPUImageInput newFrameReadyAtTime:] - - @param newTarget Target to be added - */ -- (void)addTarget:(id)newTarget atTextureLocation:(NSInteger)textureLocation; - -/** Removes a target. The target will no longer receive notifications when new frames are available. - - @param targetToRemove Target to be removed - */ -- (void)removeTarget:(id)targetToRemove; - -/** Removes all targets. - */ -- (void)removeAllTargets; - -/// @name Manage the output texture - -- (void)forceProcessingAtSize:(CGSize)frameSize; -- (void)forceProcessingAtSizeRespectingAspectRatio:(CGSize)frameSize; - -/// @name Still image processing - -- (void)useNextFrameForImageCapture; -- (CGImageRef)newCGImageFromCurrentlyProcessedOutput; -- (CGImageRef)newCGImageByFilteringCGImage:(CGImageRef)imageToFilter; - -// Platform-specific image output methods -// If you're trying to use these methods, remember that you need to set -useNextFrameForImageCapture before running -processImage or running video and calling any of these methods, or you will get a nil image -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -- (UIImage *)imageFromCurrentFramebuffer; -- (UIImage *)imageFromCurrentFramebufferWithOrientation:(UIImageOrientation)imageOrientation; -- (UIImage *)imageByFilteringImage:(UIImage *)imageToFilter; -- (CGImageRef)newCGImageByFilteringImage:(UIImage *)imageToFilter; -#else -- (NSImage *)imageFromCurrentFramebuffer; -- (NSImage *)imageFromCurrentFramebufferWithOrientation:(UIImageOrientation)imageOrientation; -- (NSImage *)imageByFilteringImage:(NSImage *)imageToFilter; -- (CGImageRef)newCGImageByFilteringImage:(NSImage *)imageToFilter; -#endif - -- (BOOL)providesMonochromeOutput; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOutput.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOutput.m deleted file mode 100755 index 2817a445..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOutput.m +++ /dev/null @@ -1,428 +0,0 @@ -#import "GPUImageOutput.h" -#import "GPUImageMovieWriter.h" -#import "GPUImagePicture.h" -#import - -void runOnMainQueueWithoutDeadlocking(void (^block)(void)) -{ - if ([NSThread isMainThread]) - { - block(); - } - else - { - dispatch_sync(dispatch_get_main_queue(), block); - } -} - -void runSynchronouslyOnVideoProcessingQueue(void (^block)(void)) -{ - dispatch_queue_t videoProcessingQueue = [GPUImageContext sharedContextQueue]; -#if !OS_OBJECT_USE_OBJC -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - if (dispatch_get_current_queue() == videoProcessingQueue) -#pragma clang diagnostic pop -#else - if (dispatch_get_specific([GPUImageContext contextKey])) -#endif - { - block(); - }else - { - dispatch_sync(videoProcessingQueue, block); - } -} - -void runAsynchronouslyOnVideoProcessingQueue(void (^block)(void)) -{ - dispatch_queue_t videoProcessingQueue = [GPUImageContext sharedContextQueue]; - -#if !OS_OBJECT_USE_OBJC -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - if (dispatch_get_current_queue() == videoProcessingQueue) -#pragma clang diagnostic pop -#else - if (dispatch_get_specific([GPUImageContext contextKey])) -#endif - { - block(); - }else - { - dispatch_async(videoProcessingQueue, block); - } -} - -void runSynchronouslyOnContextQueue(GPUImageContext *context, void (^block)(void)) -{ - dispatch_queue_t videoProcessingQueue = [context contextQueue]; -#if !OS_OBJECT_USE_OBJC -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - if (dispatch_get_current_queue() == videoProcessingQueue) -#pragma clang diagnostic pop -#else - if (dispatch_get_specific([GPUImageContext contextKey])) -#endif - { - block(); - }else - { - dispatch_sync(videoProcessingQueue, block); - } -} - -void runAsynchronouslyOnContextQueue(GPUImageContext *context, void (^block)(void)) -{ - dispatch_queue_t videoProcessingQueue = [context contextQueue]; - -#if !OS_OBJECT_USE_OBJC -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - if (dispatch_get_current_queue() == videoProcessingQueue) -#pragma clang diagnostic pop -#else - if (dispatch_get_specific([GPUImageContext contextKey])) -#endif - { - block(); - }else - { - dispatch_async(videoProcessingQueue, block); - } -} - -void reportAvailableMemoryForGPUImage(NSString *tag) -{ - if (!tag) - tag = @"Default"; - - struct task_basic_info info; - - mach_msg_type_number_t size = sizeof(info); - - kern_return_t kerr = task_info(mach_task_self(), - - TASK_BASIC_INFO, - - (task_info_t)&info, - - &size); - if( kerr == KERN_SUCCESS ) { - NSLog(@"%@ - Memory used: %u", tag, (unsigned int)info.resident_size); //in bytes - } else { - NSLog(@"%@ - Error: %s", tag, mach_error_string(kerr)); - } -} - -@implementation GPUImageOutput - -@synthesize shouldSmoothlyScaleOutput = _shouldSmoothlyScaleOutput; -@synthesize shouldIgnoreUpdatesToThisTarget = _shouldIgnoreUpdatesToThisTarget; -@synthesize audioEncodingTarget = _audioEncodingTarget; -@synthesize targetToIgnoreForUpdates = _targetToIgnoreForUpdates; -@synthesize frameProcessingCompletionBlock = _frameProcessingCompletionBlock; -@synthesize enabled = _enabled; -@synthesize outputTextureOptions = _outputTextureOptions; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super init])) - { - return nil; - } - - targets = [[NSMutableArray alloc] init]; - targetTextureIndices = [[NSMutableArray alloc] init]; - _enabled = YES; - allTargetsWantMonochromeData = YES; - usingNextFrameForImageCapture = NO; - - // set default texture options - _outputTextureOptions.minFilter = GL_LINEAR; - _outputTextureOptions.magFilter = GL_LINEAR; - _outputTextureOptions.wrapS = GL_CLAMP_TO_EDGE; - _outputTextureOptions.wrapT = GL_CLAMP_TO_EDGE; - _outputTextureOptions.internalFormat = GL_RGBA; - _outputTextureOptions.format = GL_BGRA; - _outputTextureOptions.type = GL_UNSIGNED_BYTE; - - return self; -} - -- (void)dealloc -{ - [self removeAllTargets]; -} - -#pragma mark - -#pragma mark Managing targets - -- (void)setInputFramebufferForTarget:(id)target atIndex:(NSInteger)inputTextureIndex; -{ - [target setInputFramebuffer:[self framebufferForOutput] atIndex:inputTextureIndex]; -} - -- (GPUImageFramebuffer *)framebufferForOutput; -{ - return outputFramebuffer; -} - -- (void)removeOutputFramebuffer; -{ - outputFramebuffer = nil; -} - -- (void)notifyTargetsAboutNewOutputTexture; -{ - for (id currentTarget in targets) - { - NSInteger indexOfObject = [targets indexOfObject:currentTarget]; - NSInteger textureIndex = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; - - [self setInputFramebufferForTarget:currentTarget atIndex:textureIndex]; - } -} - -- (NSArray*)targets; -{ - return [NSArray arrayWithArray:targets]; -} - -- (void)addTarget:(id)newTarget; -{ - NSInteger nextAvailableTextureIndex = [newTarget nextAvailableTextureIndex]; - [self addTarget:newTarget atTextureLocation:nextAvailableTextureIndex]; - - if ([newTarget shouldIgnoreUpdatesToThisTarget]) - { - _targetToIgnoreForUpdates = newTarget; - } -} - -- (void)addTarget:(id)newTarget atTextureLocation:(NSInteger)textureLocation; -{ - if([targets containsObject:newTarget]) - { - return; - } - - cachedMaximumOutputSize = CGSizeZero; - runSynchronouslyOnVideoProcessingQueue(^{ - [self setInputFramebufferForTarget:newTarget atIndex:textureLocation]; - [targets addObject:newTarget]; - [targetTextureIndices addObject:[NSNumber numberWithInteger:textureLocation]]; - - allTargetsWantMonochromeData = allTargetsWantMonochromeData && [newTarget wantsMonochromeInput]; - }); -} - -- (void)removeTarget:(id)targetToRemove; -{ - if(![targets containsObject:targetToRemove]) - { - return; - } - - if (_targetToIgnoreForUpdates == targetToRemove) - { - _targetToIgnoreForUpdates = nil; - } - - cachedMaximumOutputSize = CGSizeZero; - - NSInteger indexOfObject = [targets indexOfObject:targetToRemove]; - NSInteger textureIndexOfTarget = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; - - runSynchronouslyOnVideoProcessingQueue(^{ - [targetToRemove setInputSize:CGSizeZero atIndex:textureIndexOfTarget]; - [targetToRemove setInputRotation:kGPUImageNoRotation atIndex:textureIndexOfTarget]; - - [targetTextureIndices removeObjectAtIndex:indexOfObject]; - [targets removeObject:targetToRemove]; - [targetToRemove endProcessing]; - }); -} - -- (void)removeAllTargets; -{ - cachedMaximumOutputSize = CGSizeZero; - runSynchronouslyOnVideoProcessingQueue(^{ - for (id targetToRemove in targets) - { - NSInteger indexOfObject = [targets indexOfObject:targetToRemove]; - NSInteger textureIndexOfTarget = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; - - [targetToRemove setInputSize:CGSizeZero atIndex:textureIndexOfTarget]; - [targetToRemove setInputRotation:kGPUImageNoRotation atIndex:textureIndexOfTarget]; - } - [targets removeAllObjects]; - [targetTextureIndices removeAllObjects]; - - allTargetsWantMonochromeData = YES; - }); -} - -#pragma mark - -#pragma mark Manage the output texture - -- (void)forceProcessingAtSize:(CGSize)frameSize; -{ - -} - -- (void)forceProcessingAtSizeRespectingAspectRatio:(CGSize)frameSize; -{ -} - -#pragma mark - -#pragma mark Still image processing - -- (void)useNextFrameForImageCapture; -{ - -} - -- (CGImageRef)newCGImageFromCurrentlyProcessedOutput; -{ - return nil; -} - -- (CGImageRef)newCGImageByFilteringCGImage:(CGImageRef)imageToFilter; -{ - GPUImagePicture *stillImageSource = [[GPUImagePicture alloc] initWithCGImage:imageToFilter]; - - [self useNextFrameForImageCapture]; - [stillImageSource addTarget:(id)self]; - [stillImageSource processImage]; - - CGImageRef processedImage = [self newCGImageFromCurrentlyProcessedOutput]; - - [stillImageSource removeTarget:(id)self]; - return processedImage; -} - -- (BOOL)providesMonochromeOutput; -{ - return NO; -} - -#pragma mark - -#pragma mark Platform-specific image output methods - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - -- (UIImage *)imageFromCurrentFramebuffer; -{ - UIDeviceOrientation deviceOrientation = [[UIDevice currentDevice] orientation]; - UIImageOrientation imageOrientation = UIImageOrientationLeft; - switch (deviceOrientation) - { - case UIDeviceOrientationPortrait: - imageOrientation = UIImageOrientationUp; - break; - case UIDeviceOrientationPortraitUpsideDown: - imageOrientation = UIImageOrientationDown; - break; - case UIDeviceOrientationLandscapeLeft: - imageOrientation = UIImageOrientationLeft; - break; - case UIDeviceOrientationLandscapeRight: - imageOrientation = UIImageOrientationRight; - break; - default: - imageOrientation = UIImageOrientationUp; - break; - } - - return [self imageFromCurrentFramebufferWithOrientation:imageOrientation]; -} - -- (UIImage *)imageFromCurrentFramebufferWithOrientation:(UIImageOrientation)imageOrientation; -{ - CGImageRef cgImageFromBytes = [self newCGImageFromCurrentlyProcessedOutput]; - UIImage *finalImage = [UIImage imageWithCGImage:cgImageFromBytes scale:1.0 orientation:imageOrientation]; - CGImageRelease(cgImageFromBytes); - - return finalImage; -} - -- (UIImage *)imageByFilteringImage:(UIImage *)imageToFilter; -{ - CGImageRef image = [self newCGImageByFilteringCGImage:[imageToFilter CGImage]]; - UIImage *processedImage = [UIImage imageWithCGImage:image scale:[imageToFilter scale] orientation:[imageToFilter imageOrientation]]; - CGImageRelease(image); - return processedImage; -} - -- (CGImageRef)newCGImageByFilteringImage:(UIImage *)imageToFilter -{ - return [self newCGImageByFilteringCGImage:[imageToFilter CGImage]]; -} - -#else - -- (NSImage *)imageFromCurrentFramebuffer; -{ - return [self imageFromCurrentFramebufferWithOrientation:UIImageOrientationLeft]; -} - -- (NSImage *)imageFromCurrentFramebufferWithOrientation:(UIImageOrientation)imageOrientation; -{ - CGImageRef cgImageFromBytes = [self newCGImageFromCurrentlyProcessedOutput]; - NSImage *finalImage = [[NSImage alloc] initWithCGImage:cgImageFromBytes size:NSZeroSize]; - CGImageRelease(cgImageFromBytes); - - return finalImage; -} - -- (NSImage *)imageByFilteringImage:(NSImage *)imageToFilter; -{ - CGImageRef image = [self newCGImageByFilteringCGImage:[imageToFilter CGImageForProposedRect:NULL context:[NSGraphicsContext currentContext] hints:nil]]; - NSImage *processedImage = [[NSImage alloc] initWithCGImage:image size:NSZeroSize]; - CGImageRelease(image); - return processedImage; -} - -- (CGImageRef)newCGImageByFilteringImage:(NSImage *)imageToFilter -{ - return [self newCGImageByFilteringCGImage:[imageToFilter CGImageForProposedRect:NULL context:[NSGraphicsContext currentContext] hints:nil]]; -} - -#endif - -#pragma mark - -#pragma mark Accessors - -- (void)setAudioEncodingTarget:(GPUImageMovieWriter *)newValue; -{ - _audioEncodingTarget = newValue; - if( ! _audioEncodingTarget.hasAudioTrack ) - { - _audioEncodingTarget.hasAudioTrack = YES; - } -} - --(void)setOutputTextureOptions:(GPUTextureOptions)outputTextureOptions -{ - _outputTextureOptions = outputTextureOptions; - - if( outputFramebuffer.texture ) - { - glBindTexture(GL_TEXTURE_2D, outputFramebuffer.texture); - //_outputTextureOptions.format - //_outputTextureOptions.internalFormat - //_outputTextureOptions.magFilter - //_outputTextureOptions.minFilter - //_outputTextureOptions.type - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _outputTextureOptions.wrapS); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _outputTextureOptions.wrapT); - glBindTexture(GL_TEXTURE_2D, 0); - } -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOverlayBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOverlayBlendFilter.h deleted file mode 100755 index 57eb8402..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOverlayBlendFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageOverlayBlendFilter : GPUImageTwoInputFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOverlayBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOverlayBlendFilter.m deleted file mode 100755 index c8c5185d..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageOverlayBlendFilter.m +++ /dev/null @@ -1,94 +0,0 @@ -#import "GPUImageOverlayBlendFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageOverlayBlendFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - mediump vec4 base = texture2D(inputImageTexture, textureCoordinate); - mediump vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2); - - mediump float ra; - if (2.0 * base.r < base.a) { - ra = 2.0 * overlay.r * base.r + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a); - } else { - ra = overlay.a * base.a - 2.0 * (base.a - base.r) * (overlay.a - overlay.r) + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a); - } - - mediump float ga; - if (2.0 * base.g < base.a) { - ga = 2.0 * overlay.g * base.g + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a); - } else { - ga = overlay.a * base.a - 2.0 * (base.a - base.g) * (overlay.a - overlay.g) + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a); - } - - mediump float ba; - if (2.0 * base.b < base.a) { - ba = 2.0 * overlay.b * base.b + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a); - } else { - ba = overlay.a * base.a - 2.0 * (base.a - base.b) * (overlay.a - overlay.b) + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a); - } - - gl_FragColor = vec4(ra, ga, ba, 1.0); - } -); -#else -NSString *const kGPUImageOverlayBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 base = texture2D(inputImageTexture, textureCoordinate); - vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2); - - float ra; - if (2.0 * base.r < base.a) { - ra = 2.0 * overlay.r * base.r + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a); - } else { - ra = overlay.a * base.a - 2.0 * (base.a - base.r) * (overlay.a - overlay.r) + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a); - } - - float ga; - if (2.0 * base.g < base.a) { - ga = 2.0 * overlay.g * base.g + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a); - } else { - ga = overlay.a * base.a - 2.0 * (base.a - base.g) * (overlay.a - overlay.g) + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a); - } - - float ba; - if (2.0 * base.b < base.a) { - ba = 2.0 * overlay.b * base.b + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a); - } else { - ba = overlay.a * base.a - 2.0 * (base.a - base.b) * (overlay.a - overlay.b) + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a); - } - - gl_FragColor = vec4(ra, ga, ba, 1.0); - } -); -#endif - -@implementation GPUImageOverlayBlendFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageOverlayBlendFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageParallelCoordinateLineTransformFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageParallelCoordinateLineTransformFilter.h deleted file mode 100644 index aa8f3f47..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageParallelCoordinateLineTransformFilter.h +++ /dev/null @@ -1,16 +0,0 @@ -#import "GPUImageFilter.h" - -// This is an accumulator that uses a Hough transform in parallel coordinate space to identify probable lines in a scene. -// -// It is entirely based on the work of the Graph@FIT research group at the Brno University of Technology and their publications: -// M. Dubská, J. Havel, and A. Herout. Real-Time Detection of Lines using Parallel Coordinates and OpenGL. Proceedings of SCCG 2011, Bratislava, SK, p. 7. -// M. Dubská, J. Havel, and A. Herout. PClines — Line detection using parallel coordinates. 2011 IEEE Conference on Computer Vision and Pattern Recognition (CVPR), p. 1489- 1494. - -@interface GPUImageParallelCoordinateLineTransformFilter : GPUImageFilter -{ - GLubyte *rawImagePixels; - GLfloat *lineCoordinates; - unsigned int maxLinePairsToRender, linePairsToRender; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageParallelCoordinateLineTransformFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageParallelCoordinateLineTransformFilter.m deleted file mode 100644 index 0a2f6e49..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageParallelCoordinateLineTransformFilter.m +++ /dev/null @@ -1,266 +0,0 @@ -#import "GPUImageParallelCoordinateLineTransformFilter.h" - -NSString *const kGPUImageHoughAccumulationVertexShaderString = SHADER_STRING -( - attribute vec4 position; - - void main() - { - gl_Position = position; - } -); - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageHoughAccumulationFragmentShaderString = SHADER_STRING -( - const lowp float scalingFactor = 1.0 / 256.0; - - void main() - { - gl_FragColor = vec4(0.004, 0.004, 0.004, 1.0); - } -); - -// highp - 16-bit, floating point range: -2^62 to 2^62, integer range: -2^16 to 2^16 -// NOTE: See below for where I'm tacking on the required extension as a prefix -NSString *const kGPUImageHoughAccumulationFBOReadFragmentShaderString = SHADER_STRING -( - const lowp float scalingFactor = 0.004; -// const lowp float scalingFactor = 0.1; - - void main() - { - mediump vec4 fragmentData = gl_LastFragData[0]; - - fragmentData.r = fragmentData.r + scalingFactor; - fragmentData.g = scalingFactor * floor(fragmentData.r) + fragmentData.g; - fragmentData.b = scalingFactor * floor(fragmentData.g) + fragmentData.b; - fragmentData.a = scalingFactor * floor(fragmentData.b) + fragmentData.a; - - fragmentData = fract(fragmentData); - - gl_FragColor = vec4(fragmentData.rgb, 1.0); - } -); - -#else -NSString *const kGPUImageHoughAccumulationFragmentShaderString = SHADER_STRING -( - const float scalingFactor = 1.0 / 256.0; - - void main() - { - gl_FragColor = vec4(0.004, 0.004, 0.004, 1.0); - } -); - -NSString *const kGPUImageHoughAccumulationFBOReadFragmentShaderString = SHADER_STRING -( - const float scalingFactor = 1.0 / 256.0; - - void main() - { - // gl_FragColor = vec4(scalingFactor, scalingFactor, scalingFactor, 1.0); - gl_FragColor = vec4(0.004, 0.004, 0.004, 1.0); - } -); -#endif - -@interface GPUImageParallelCoordinateLineTransformFilter() -// Rendering -- (void)generateLineCoordinates; - -@end - -@implementation GPUImageParallelCoordinateLineTransformFilter - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - NSString *fragmentShaderToUse = nil; - - if ([GPUImageContext deviceSupportsFramebufferReads]) - { - fragmentShaderToUse = [NSString stringWithFormat:@"#extension GL_EXT_shader_framebuffer_fetch : require\n %@",kGPUImageHoughAccumulationFBOReadFragmentShaderString]; - } - else - { - fragmentShaderToUse = kGPUImageHoughAccumulationFragmentShaderString; - } - - if (!(self = [super initWithVertexShaderFromString:kGPUImageHoughAccumulationVertexShaderString fragmentShaderFromString:fragmentShaderToUse])) - { - return nil; - } - - - return self; -} - -// TODO: have this be regenerated on change of image size -- (void)dealloc; -{ - free(rawImagePixels); - free(lineCoordinates); -} - -- (void)initializeAttributes; -{ - [filterProgram addAttribute:@"position"]; -} - -#pragma mark - -#pragma mark Rendering - -#define MAXLINESCALINGFACTOR 4 - -- (void)generateLineCoordinates; -{ - unsigned int imageByteSize = inputTextureSize.width * inputTextureSize.height * 4; - rawImagePixels = (GLubyte *)malloc(imageByteSize); - - maxLinePairsToRender = (inputTextureSize.width * inputTextureSize.height) / MAXLINESCALINGFACTOR; - lineCoordinates = calloc(maxLinePairsToRender * 8, sizeof(GLfloat)); -} - -- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex; -{ - if (lineCoordinates == NULL) - { - [self generateLineCoordinates]; - } - - [self renderToTextureWithVertices:NULL textureCoordinates:NULL]; - - [self informTargetsAboutNewFrameAtTime:frameTime]; -} - -- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates; -{ - // we need a normal color texture for this filter - NSAssert(self.outputTextureOptions.internalFormat == GL_RGBA, @"The output texture format for this filter must be GL_RGBA."); - NSAssert(self.outputTextureOptions.type == GL_UNSIGNED_BYTE, @"The type of the output texture of this filter must be GL_UNSIGNED_BYTE."); - - if (self.preventRendering) - { - [firstInputFramebuffer unlock]; - return; - } - - // Grab the edge points from the previous frame and create the parallel coordinate lines for them - // This would be a great place to have a working histogram pyramid implementation - - [GPUImageContext useImageProcessingContext]; - [firstInputFramebuffer activateFramebuffer]; - - glFinish(); - glReadPixels(0, 0, inputTextureSize.width, inputTextureSize.height, GL_RGBA, GL_UNSIGNED_BYTE, rawImagePixels); - - CGFloat xAspectMultiplier = 1.0, yAspectMultiplier = 1.0; - -// if (inputTextureSize.width > inputTextureSize.height) -// { -// yAspectMultiplier = inputTextureSize.height / inputTextureSize.width; -// } -// else -// { -// xAspectMultiplier = inputTextureSize.width / inputTextureSize.height; -// } - -// CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); - - unsigned int imageByteSize = inputTextureSize.width * inputTextureSize.height * 4; - unsigned int imageWidth = inputTextureSize.width * 4; - - linePairsToRender = 0; - unsigned int currentByte = 0; - unsigned int lineStorageIndex = 0; - unsigned int maxLineStorageIndex = maxLinePairsToRender * 8 - 8; - - GLfloat minY = 100, maxY = -100, minX = 100, maxX = -100; - while (currentByte < imageByteSize) - { - GLubyte colorByte = rawImagePixels[currentByte]; - - if (colorByte > 0) - { - unsigned int xCoordinate = currentByte % imageWidth; - unsigned int yCoordinate = currentByte / imageWidth; - - CGFloat normalizedXCoordinate = (-1.0 + 2.0 * (CGFloat)(xCoordinate / 4) / inputTextureSize.width) * xAspectMultiplier; - CGFloat normalizedYCoordinate = (-1.0 + 2.0 * (CGFloat)(yCoordinate) / inputTextureSize.height) * yAspectMultiplier; - - minY = MIN(minY, normalizedYCoordinate); - maxY = MAX(maxY, normalizedYCoordinate); - minX = MIN(minX, normalizedXCoordinate); - maxX = MAX(maxX, normalizedXCoordinate); - -// NSLog(@"Parallel line coordinates: (%f, %f) - (%f, %f) - (%f, %f)", -1.0, -normalizedYCoordinate, 0.0, normalizedXCoordinate, 1.0, normalizedYCoordinate); - // T space coordinates, (-d, -y) to (0, x) - lineCoordinates[lineStorageIndex++] = -1.0; - lineCoordinates[lineStorageIndex++] = -normalizedYCoordinate; - lineCoordinates[lineStorageIndex++] = 0.0; - lineCoordinates[lineStorageIndex++] = normalizedXCoordinate; - - // S space coordinates, (0, x) to (d, y) - lineCoordinates[lineStorageIndex++] = 0.0; - lineCoordinates[lineStorageIndex++] = normalizedXCoordinate; - lineCoordinates[lineStorageIndex++] = 1.0; - lineCoordinates[lineStorageIndex++] = normalizedYCoordinate; - - linePairsToRender++; - - linePairsToRender = MIN(linePairsToRender, maxLinePairsToRender); - lineStorageIndex = MIN(lineStorageIndex, maxLineStorageIndex); - } - currentByte +=8; - } - -// NSLog(@"Line pairs to render: %d out of max: %d", linePairsToRender, maxLinePairsToRender); - -// CFAbsoluteTime currentFrameTime = (CFAbsoluteTimeGetCurrent() - startTime); -// NSLog(@"Line generation processing time : %f ms", 1000.0 * currentFrameTime); - - outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:[self sizeOfFBO] textureOptions:self.outputTextureOptions onlyTexture:NO]; - [outputFramebuffer activateFramebuffer]; - - if (usingNextFrameForImageCapture) - { - [outputFramebuffer lock]; - } - - [GPUImageContext setActiveShaderProgram:filterProgram]; - [self setUniformsForProgramAtIndex:0]; - - glClearColor(0.0, 0.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - - if (![GPUImageContext deviceSupportsFramebufferReads]) - { - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_ONE, GL_ONE); - glEnable(GL_BLEND); - } - else - { - } - - glLineWidth(1); - - glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, lineCoordinates); - glDrawArrays(GL_LINES, 0, (linePairsToRender * 4)); - - if (![GPUImageContext deviceSupportsFramebufferReads]) - { - glDisable(GL_BLEND); - } - [firstInputFramebuffer unlock]; - if (usingNextFrameForImageCapture) - { - dispatch_semaphore_signal(imageCaptureSemaphore); - } -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePerlinNoiseFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePerlinNoiseFilter.h deleted file mode 100644 index 922f4d30..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePerlinNoiseFilter.h +++ /dev/null @@ -1,13 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImagePerlinNoiseFilter : GPUImageFilter -{ - GLint scaleUniform, colorStartUniform, colorFinishUniform; -} - -@property (readwrite, nonatomic) GPUVector4 colorStart; -@property (readwrite, nonatomic) GPUVector4 colorFinish; - -@property (readwrite, nonatomic) float scale; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePerlinNoiseFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePerlinNoiseFilter.m deleted file mode 100644 index 9ca7cbad..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePerlinNoiseFilter.m +++ /dev/null @@ -1,239 +0,0 @@ -#import "GPUImagePerlinNoiseFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImagePerlinNoiseFragmentShaderString = SHADER_STRING -( - precision highp float; - varying highp vec2 textureCoordinate; - uniform float scale; - - uniform vec4 colorStart; - uniform vec4 colorFinish; - - // - // Description : Array and textureless GLSL 2D/3D/4D simplex - // noise functions. - // Author : Ian McEwan, Ashima Arts. - // Maintainer : ijm - // Lastmod : 20110822 (ijm) - // License : Copyright (C) 2011 Ashima Arts. All rights reserved. - // Distributed under the MIT License. See LICENSE file. - // https://github.com/ashima/webgl-noise - // - - vec4 mod289(vec4 x) -{ - return x - floor(x * (1.0 / 289.0)) * 289.0; -} - - vec4 permute(vec4 x) -{ - return mod289(((x*34.0)+1.0)*x); -} - - vec4 taylorInvSqrt(vec4 r) -{ - return 1.79284291400159 - 0.85373472095314 * r; -} - - vec2 fade(vec2 t) { - return t*t*t*(t*(t*6.0-15.0)+10.0); - } - - // Classic Perlin noise - float cnoise(vec2 P) -{ - vec4 Pi = floor(P.xyxy) + vec4(0.0, 0.0, 1.0, 1.0); - vec4 Pf = fract(P.xyxy) - vec4(0.0, 0.0, 1.0, 1.0); - Pi = mod289(Pi); // To avoid truncation effects in permutation - vec4 ix = Pi.xzxz; - vec4 iy = Pi.yyww; - vec4 fx = Pf.xzxz; - vec4 fy = Pf.yyww; - - vec4 i = permute(permute(ix) + iy); - - vec4 gx = fract(i * (1.0 / 41.0)) * 2.0 - 1.0 ; - vec4 gy = abs(gx) - 0.5 ; - vec4 tx = floor(gx + 0.5); - gx = gx - tx; - - vec2 g00 = vec2(gx.x,gy.x); - vec2 g10 = vec2(gx.y,gy.y); - vec2 g01 = vec2(gx.z,gy.z); - vec2 g11 = vec2(gx.w,gy.w); - - vec4 norm = taylorInvSqrt(vec4(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11))); - g00 *= norm.x; - g01 *= norm.y; - g10 *= norm.z; - g11 *= norm.w; - - float n00 = dot(g00, vec2(fx.x, fy.x)); - float n10 = dot(g10, vec2(fx.y, fy.y)); - float n01 = dot(g01, vec2(fx.z, fy.z)); - float n11 = dot(g11, vec2(fx.w, fy.w)); - - vec2 fade_xy = fade(Pf.xy); - vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade_xy.x); - float n_xy = mix(n_x.x, n_x.y, fade_xy.y); - return 2.3 * n_xy; -} - - - void main() - { - - float n1 = (cnoise(textureCoordinate * scale) + 1.0) / 2.0; - - vec4 colorDiff = colorFinish - colorStart; - vec4 color = colorStart + colorDiff * n1; - - gl_FragColor = color; - } -); -#else -NSString *const kGPUImagePerlinNoiseFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - uniform float scale; - - uniform vec4 colorStart; - uniform vec4 colorFinish; - - // - // Description : Array and textureless GLSL 2D/3D/4D simplex - // noise functions. - // Author : Ian McEwan, Ashima Arts. - // Maintainer : ijm - // Lastmod : 20110822 (ijm) - // License : Copyright (C) 2011 Ashima Arts. All rights reserved. - // Distributed under the MIT License. See LICENSE file. - // https://github.com/ashima/webgl-noise - // - - vec4 mod289(vec4 x) -{ - return x - floor(x * (1.0 / 289.0)) * 289.0; -} - - vec4 permute(vec4 x) -{ - return mod289(((x*34.0)+1.0)*x); -} - - vec4 taylorInvSqrt(vec4 r) -{ - return 1.79284291400159 - 0.85373472095314 * r; -} - - vec2 fade(vec2 t) { - return t*t*t*(t*(t*6.0-15.0)+10.0); - } - - // Classic Perlin noise - float cnoise(vec2 P) -{ - vec4 Pi = floor(P.xyxy) + vec4(0.0, 0.0, 1.0, 1.0); - vec4 Pf = fract(P.xyxy) - vec4(0.0, 0.0, 1.0, 1.0); - Pi = mod289(Pi); // To avoid truncation effects in permutation - vec4 ix = Pi.xzxz; - vec4 iy = Pi.yyww; - vec4 fx = Pf.xzxz; - vec4 fy = Pf.yyww; - - vec4 i = permute(permute(ix) + iy); - - vec4 gx = fract(i * (1.0 / 41.0)) * 2.0 - 1.0 ; - vec4 gy = abs(gx) - 0.5 ; - vec4 tx = floor(gx + 0.5); - gx = gx - tx; - - vec2 g00 = vec2(gx.x,gy.x); - vec2 g10 = vec2(gx.y,gy.y); - vec2 g01 = vec2(gx.z,gy.z); - vec2 g11 = vec2(gx.w,gy.w); - - vec4 norm = taylorInvSqrt(vec4(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11))); - g00 *= norm.x; - g01 *= norm.y; - g10 *= norm.z; - g11 *= norm.w; - - float n00 = dot(g00, vec2(fx.x, fy.x)); - float n10 = dot(g10, vec2(fx.y, fy.y)); - float n01 = dot(g01, vec2(fx.z, fy.z)); - float n11 = dot(g11, vec2(fx.w, fy.w)); - - vec2 fade_xy = fade(Pf.xy); - vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade_xy.x); - float n_xy = mix(n_x.x, n_x.y, fade_xy.y); - return 2.3 * n_xy; - } - - void main() - { - - float n1 = (cnoise(textureCoordinate * scale) + 1.0) / 2.0; - - vec4 colorDiff = colorFinish - colorStart; - vec4 color = colorStart + colorDiff * n1; - - gl_FragColor = color; - } -); -#endif - - -@implementation GPUImagePerlinNoiseFilter - -@synthesize scale = _scale, colorStart = _colorStart, colorFinish = _colorFinish; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImagePerlinNoiseFragmentShaderString])) - { - return nil; - } - - scaleUniform = [filterProgram uniformIndex:@"scale"]; - - colorStartUniform = [filterProgram uniformIndex:@"colorStart"]; - colorFinishUniform = [filterProgram uniformIndex:@"colorFinish"]; - - [self setScale:8.0]; - - [self setColorStart:(GPUVector4){0.0, 0.0, 0.0, 1.0}]; - [self setColorFinish:(GPUVector4){1.0, 1.0, 1.0, 1.0}]; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setScale:(float)scale -{ - _scale = scale; - - [self setFloat:_scale forUniform:scaleUniform program:filterProgram]; -} - -- (void)setColorStart:(GPUVector4)colorStart -{ - _colorStart = colorStart; - - [self setVec4:_colorStart forUniform:colorStartUniform program:filterProgram]; -} - -- (void)setColorFinish:(GPUVector4)colorFinish -{ - _colorFinish = colorFinish; - - [self setVec4:_colorFinish forUniform:colorFinishUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePinchDistortionFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePinchDistortionFilter.h deleted file mode 100755 index 994774fd..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePinchDistortionFilter.h +++ /dev/null @@ -1,20 +0,0 @@ -#import "GPUImageFilter.h" - -/** Creates a pinch distortion of the image - */ -@interface GPUImagePinchDistortionFilter : GPUImageFilter -{ - GLint aspectRatioUniform, radiusUniform, centerUniform, scaleUniform; -} - -/** The center about which to apply the distortion, with a default of (0.5, 0.5) - */ -@property(readwrite, nonatomic) CGPoint center; -/** The radius of the distortion, ranging from 0.0 to 2.0, with a default of 1.0 - */ -@property(readwrite, nonatomic) CGFloat radius; -/** The amount of distortion to apply, from -2.0 to 2.0, with a default of 0.5 - */ -@property(readwrite, nonatomic) CGFloat scale; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePinchDistortionFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePinchDistortionFilter.m deleted file mode 100755 index 76d79096..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePinchDistortionFilter.m +++ /dev/null @@ -1,176 +0,0 @@ -#import "GPUImagePinchDistortionFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImagePinchDistortionFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform highp float aspectRatio; - uniform highp vec2 center; - uniform highp float radius; - uniform highp float scale; - - void main() - { - highp vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); - highp float dist = distance(center, textureCoordinateToUse); - textureCoordinateToUse = textureCoordinate; - - if (dist < radius) - { - textureCoordinateToUse -= center; - highp float percent = 1.0 + ((0.5 - dist) / 0.5) * scale; - textureCoordinateToUse = textureCoordinateToUse * percent; - textureCoordinateToUse += center; - - gl_FragColor = texture2D(inputImageTexture, textureCoordinateToUse ); - } - else - { - gl_FragColor = texture2D(inputImageTexture, textureCoordinate ); - } - } -); -#else -NSString *const kGPUImagePinchDistortionFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform float aspectRatio; - uniform vec2 center; - uniform float radius; - uniform float scale; - - void main() - { - vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); - float dist = distance(center, textureCoordinateToUse); - textureCoordinateToUse = textureCoordinate; - - if (dist < radius) - { - textureCoordinateToUse -= center; - float percent = 1.0 + ((0.5 - dist) / 0.5) * scale; - textureCoordinateToUse = textureCoordinateToUse * percent; - textureCoordinateToUse += center; - - gl_FragColor = texture2D(inputImageTexture, textureCoordinateToUse ); - } - else - { - gl_FragColor = texture2D(inputImageTexture, textureCoordinate ); - } - } -); -#endif - -@interface GPUImagePinchDistortionFilter () - -- (void)adjustAspectRatio; - -@property (readwrite, nonatomic) CGFloat aspectRatio; - -@end - -@implementation GPUImagePinchDistortionFilter - -@synthesize aspectRatio = _aspectRatio; -@synthesize center = _center; -@synthesize radius = _radius; -@synthesize scale = _scale; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImagePinchDistortionFragmentShaderString])) - { - return nil; - } - - aspectRatioUniform = [filterProgram uniformIndex:@"aspectRatio"]; - radiusUniform = [filterProgram uniformIndex:@"radius"]; - scaleUniform = [filterProgram uniformIndex:@"scale"]; - centerUniform = [filterProgram uniformIndex:@"center"]; - - self.radius = 1.0; - self.scale = 0.5; - self.center = CGPointMake(0.5, 0.5); - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)adjustAspectRatio; -{ - if (GPUImageRotationSwapsWidthAndHeight(inputRotation)) - { - [self setAspectRatio:(inputTextureSize.width / inputTextureSize.height)]; - } - else - { - [self setAspectRatio:(inputTextureSize.height / inputTextureSize.width)]; - } -} - -- (void)forceProcessingAtSize:(CGSize)frameSize; -{ - [super forceProcessingAtSize:frameSize]; - [self adjustAspectRatio]; -} - -- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex; -{ - CGSize oldInputSize = inputTextureSize; - [super setInputSize:newSize atIndex:textureIndex]; - - if ( (!CGSizeEqualToSize(oldInputSize, inputTextureSize)) && (!CGSizeEqualToSize(newSize, CGSizeZero)) ) - { - [self adjustAspectRatio]; - } -} - -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -{ - [super setInputRotation:newInputRotation atIndex:textureIndex]; - [self setCenter:self.center]; - [self adjustAspectRatio]; -} - -- (void)setAspectRatio:(CGFloat)newValue; -{ - _aspectRatio = newValue; - - [self setFloat:_aspectRatio forUniform:aspectRatioUniform program:filterProgram]; -} - -- (void)setRadius:(CGFloat)newValue; -{ - _radius = newValue; - - [self setFloat:_radius forUniform:radiusUniform program:filterProgram]; -} - -- (void)setScale:(CGFloat)newValue; -{ - _scale = newValue; - - [self setFloat:_scale forUniform:scaleUniform program:filterProgram]; -} - -- (void)setCenter:(CGPoint)newValue; -{ - _center = newValue; - - CGPoint rotatedPoint = [self rotatedPoint:_center forRotation:inputRotation]; - [self setPoint:rotatedPoint forUniform:centerUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePixellateFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePixellateFilter.h deleted file mode 100755 index d0f6ae04..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePixellateFilter.h +++ /dev/null @@ -1,12 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImagePixellateFilter : GPUImageFilter -{ - GLint fractionalWidthOfAPixelUniform, aspectRatioUniform; -} - -// The fractional width of the image to use as a size for the pixels in the resulting image. Values below one pixel width in the source image are ignored. -@property(readwrite, nonatomic) CGFloat fractionalWidthOfAPixel; - - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePixellateFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePixellateFilter.m deleted file mode 100755 index 88430d09..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePixellateFilter.m +++ /dev/null @@ -1,151 +0,0 @@ -#import "GPUImagePixellateFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImagePixellationFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform highp float fractionalWidthOfPixel; - uniform highp float aspectRatio; - - void main() - { - highp vec2 sampleDivisor = vec2(fractionalWidthOfPixel, fractionalWidthOfPixel / aspectRatio); - - highp vec2 samplePos = textureCoordinate - mod(textureCoordinate, sampleDivisor) + 0.5 * sampleDivisor; - gl_FragColor = texture2D(inputImageTexture, samplePos ); - } -); -#else -NSString *const kGPUImagePixellationFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform float fractionalWidthOfPixel; - uniform float aspectRatio; - - void main() - { - vec2 sampleDivisor = vec2(fractionalWidthOfPixel, fractionalWidthOfPixel / aspectRatio); - - vec2 samplePos = textureCoordinate - mod(textureCoordinate, sampleDivisor) + 0.5 * sampleDivisor; - gl_FragColor = texture2D(inputImageTexture, samplePos ); - } -); -#endif - -@interface GPUImagePixellateFilter () - -@property (readwrite, nonatomic) CGFloat aspectRatio; - -- (void)adjustAspectRatio; - -@end - -@implementation GPUImagePixellateFilter - -@synthesize fractionalWidthOfAPixel = _fractionalWidthOfAPixel; -@synthesize aspectRatio = _aspectRatio; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [self initWithFragmentShaderFromString:kGPUImagePixellationFragmentShaderString])) - { - return nil; - } - - return self; -} - -- (id)initWithFragmentShaderFromString:(NSString *)fragmentShaderString; -{ - if (!(self = [super initWithFragmentShaderFromString:fragmentShaderString])) - { - return nil; - } - - fractionalWidthOfAPixelUniform = [filterProgram uniformIndex:@"fractionalWidthOfPixel"]; - aspectRatioUniform = [filterProgram uniformIndex:@"aspectRatio"]; - - self.fractionalWidthOfAPixel = 0.05; - - return self; -} - -- (void)adjustAspectRatio; -{ - if (GPUImageRotationSwapsWidthAndHeight(inputRotation)) - { - [self setAspectRatio:(inputTextureSize.width / inputTextureSize.height)]; - } - else - { - [self setAspectRatio:(inputTextureSize.height / inputTextureSize.width)]; - } -} - -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -{ - [super setInputRotation:newInputRotation atIndex:textureIndex]; - [self adjustAspectRatio]; -} - -- (void)forceProcessingAtSize:(CGSize)frameSize; -{ - [super forceProcessingAtSize:frameSize]; - [self adjustAspectRatio]; -} - -- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex; -{ - CGSize oldInputSize = inputTextureSize; - [super setInputSize:newSize atIndex:textureIndex]; - - if ( (!CGSizeEqualToSize(oldInputSize, inputTextureSize)) && (!CGSizeEqualToSize(newSize, CGSizeZero)) ) - { - [self adjustAspectRatio]; - } -} - -#pragma mark - -#pragma mark Accessors - -- (void)setFractionalWidthOfAPixel:(CGFloat)newValue; -{ - CGFloat singlePixelSpacing; - if (inputTextureSize.width != 0.0) - { - singlePixelSpacing = 1.0 / inputTextureSize.width; - } - else - { - singlePixelSpacing = 1.0 / 2048.0; - } - - if (newValue < singlePixelSpacing) - { - _fractionalWidthOfAPixel = singlePixelSpacing; - } - else - { - _fractionalWidthOfAPixel = newValue; - } - - [self setFloat:_fractionalWidthOfAPixel forUniform:fractionalWidthOfAPixelUniform program:filterProgram]; -} - -- (void)setAspectRatio:(CGFloat)newValue; -{ - _aspectRatio = newValue; - - [self setFloat:_aspectRatio forUniform:aspectRatioUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePixellatePositionFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePixellatePositionFilter.h deleted file mode 100755 index 9d304c93..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePixellatePositionFilter.h +++ /dev/null @@ -1,17 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImagePixellatePositionFilter : GPUImageFilter -{ - GLint fractionalWidthOfAPixelUniform, aspectRatioUniform, centerUniform, radiusUniform; -} - -// The fractional width of the image to use as a size for the pixels in the resulting image. Values below one pixel width in the source image are ignored. -@property(readwrite, nonatomic) CGFloat fractionalWidthOfAPixel; - -// the center point to start pixelation in texture coordinates, default 0.5, 0.5 -@property(readwrite, nonatomic) CGPoint center; - -// the radius (0.0 - 1.0) in which to pixelate, default 1.0 -@property(readwrite, nonatomic) CGFloat radius; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePixellatePositionFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePixellatePositionFilter.m deleted file mode 100755 index f1bd09cc..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePixellatePositionFilter.m +++ /dev/null @@ -1,194 +0,0 @@ -#import "GPUImagePixellatePositionFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImagePixellationPositionFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform highp float fractionalWidthOfPixel; - uniform highp float aspectRatio; - uniform lowp vec2 pixelateCenter; - uniform highp float pixelateRadius; - - void main() - { - highp vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); - highp float dist = distance(pixelateCenter, textureCoordinateToUse); - - if (dist < pixelateRadius) - { - highp vec2 sampleDivisor = vec2(fractionalWidthOfPixel, fractionalWidthOfPixel / aspectRatio); - highp vec2 samplePos = textureCoordinate - mod(textureCoordinate, sampleDivisor) + 0.5 * sampleDivisor; - gl_FragColor = texture2D(inputImageTexture, samplePos ); - } - else - { - gl_FragColor = texture2D(inputImageTexture, textureCoordinate ); - } - } -); -#else -NSString *const kGPUImagePixellationPositionFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform float fractionalWidthOfPixel; - uniform float aspectRatio; - uniform vec2 pixelateCenter; - uniform float pixelateRadius; - - void main() - { - vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); - float dist = distance(pixelateCenter, textureCoordinateToUse); - - if (dist < pixelateRadius) - { - vec2 sampleDivisor = vec2(fractionalWidthOfPixel, fractionalWidthOfPixel / aspectRatio); - vec2 samplePos = textureCoordinate - mod(textureCoordinate, sampleDivisor) + 0.5 * sampleDivisor; - gl_FragColor = texture2D(inputImageTexture, samplePos ); - } - else - { - gl_FragColor = texture2D(inputImageTexture, textureCoordinate ); - } - } -); -#endif - -@interface GPUImagePixellatePositionFilter () - -- (void)adjustAspectRatio; - -@property (readwrite, nonatomic) CGFloat aspectRatio; - -@end - -@implementation GPUImagePixellatePositionFilter - -@synthesize fractionalWidthOfAPixel = _fractionalWidthOfAPixel; -@synthesize aspectRatio = _aspectRatio; -@synthesize center = _center; -@synthesize radius = _radius; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [self initWithFragmentShaderFromString:kGPUImagePixellationPositionFragmentShaderString])) - { - return nil; - } - - return self; -} - -- (id)initWithFragmentShaderFromString:(NSString *)fragmentShaderString; -{ - if (!(self = [super initWithFragmentShaderFromString:fragmentShaderString])) - { - return nil; - } - - fractionalWidthOfAPixelUniform = [filterProgram uniformIndex:@"fractionalWidthOfPixel"]; - aspectRatioUniform = [filterProgram uniformIndex:@"aspectRatio"]; - centerUniform = [filterProgram uniformIndex:@"pixelateCenter"]; - radiusUniform = [filterProgram uniformIndex:@"pixelateRadius"]; - - self.fractionalWidthOfAPixel = 0.05; - self.center = CGPointMake(0.5f, 0.5f); - self.radius = 0.25f; - - return self; -} - -- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex; -{ - CGSize oldInputSize = inputTextureSize; - [super setInputSize:newSize atIndex:textureIndex]; - - if ( (!CGSizeEqualToSize(oldInputSize, inputTextureSize)) && (!CGSizeEqualToSize(newSize, CGSizeZero)) ) - { - [self adjustAspectRatio]; - } -} - -#pragma mark - -#pragma mark Accessors - -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -{ - [super setInputRotation:newInputRotation atIndex:textureIndex]; - [self setCenter:self.center]; - [self adjustAspectRatio]; -} - -- (void)adjustAspectRatio; -{ - if (GPUImageRotationSwapsWidthAndHeight(inputRotation)) - { - [self setAspectRatio:(inputTextureSize.width / inputTextureSize.height)]; - } - else - { - [self setAspectRatio:(inputTextureSize.height / inputTextureSize.width)]; - } -} - -- (void)forceProcessingAtSize:(CGSize)frameSize; -{ - [super forceProcessingAtSize:frameSize]; - [self adjustAspectRatio]; -} - -- (void)setFractionalWidthOfAPixel:(CGFloat)newValue; -{ - CGFloat singlePixelSpacing; - if (inputTextureSize.width != 0.0) - { - singlePixelSpacing = 1.0 / inputTextureSize.width; - } - else - { - singlePixelSpacing = 1.0 / 2048.0; - } - - if (newValue < singlePixelSpacing) - { - _fractionalWidthOfAPixel = singlePixelSpacing; - } - else - { - _fractionalWidthOfAPixel = newValue; - } - - [self setFloat:_fractionalWidthOfAPixel forUniform:fractionalWidthOfAPixelUniform program:filterProgram]; -} - -- (void)setAspectRatio:(CGFloat)newValue; -{ - _aspectRatio = newValue; - - [self setFloat:_aspectRatio forUniform:aspectRatioUniform program:filterProgram]; -} - -- (void)setCenter:(CGPoint)center -{ - _center = center; - CGPoint rotatedPoint = [self rotatedPoint:center forRotation:inputRotation]; - [self setPoint:rotatedPoint forUniform:centerUniform program:filterProgram]; -} - -- (void)setRadius:(CGFloat)radius -{ - _radius = radius; - - [self setFloat:_radius forUniform:radiusUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePoissonBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePoissonBlendFilter.h deleted file mode 100644 index 58eff225..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePoissonBlendFilter.h +++ /dev/null @@ -1,18 +0,0 @@ -#import "GPUImageTwoInputCrossTextureSamplingFilter.h" -#import "GPUImageFilterGroup.h" - -@interface GPUImagePoissonBlendFilter : GPUImageTwoInputCrossTextureSamplingFilter -{ - GLint mixUniform; - - GPUImageFramebuffer *secondOutputFramebuffer; -} - -// Mix ranges from 0.0 (only image 1) to 1.0 (only image 2 gradients), with 1.0 as the normal level -@property(readwrite, nonatomic) CGFloat mix; - -// The number of times to propagate the gradients. -// Crank this up to 100 or even 1000 if you want to get anywhere near convergence. Yes, this will be slow. -@property(readwrite, nonatomic) NSUInteger numIterations; - -@end \ No newline at end of file diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePoissonBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePoissonBlendFilter.m deleted file mode 100644 index 0167e024..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePoissonBlendFilter.m +++ /dev/null @@ -1,175 +0,0 @@ -#import "GPUImagePoissonBlendFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImagePoissonBlendFragmentShaderString = SHADER_STRING -( - precision mediump float; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - varying vec2 topTextureCoordinate; - varying vec2 bottomTextureCoordinate; - - varying vec2 textureCoordinate2; - varying vec2 leftTextureCoordinate2; - varying vec2 rightTextureCoordinate2; - varying vec2 topTextureCoordinate2; - varying vec2 bottomTextureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - uniform lowp float mixturePercent; - - void main() - { - vec4 centerColor = texture2D(inputImageTexture, textureCoordinate); - vec3 bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate).rgb; - vec3 leftColor = texture2D(inputImageTexture, leftTextureCoordinate).rgb; - vec3 rightColor = texture2D(inputImageTexture, rightTextureCoordinate).rgb; - vec3 topColor = texture2D(inputImageTexture, topTextureCoordinate).rgb; - - vec4 centerColor2 = texture2D(inputImageTexture2, textureCoordinate2); - vec3 bottomColor2 = texture2D(inputImageTexture2, bottomTextureCoordinate2).rgb; - vec3 leftColor2 = texture2D(inputImageTexture2, leftTextureCoordinate2).rgb; - vec3 rightColor2 = texture2D(inputImageTexture2, rightTextureCoordinate2).rgb; - vec3 topColor2 = texture2D(inputImageTexture2, topTextureCoordinate2).rgb; - - vec3 meanColor = (bottomColor + leftColor + rightColor + topColor) / 4.0; - vec3 diffColor = centerColor.rgb - meanColor; - - vec3 meanColor2 = (bottomColor2 + leftColor2 + rightColor2 + topColor2) / 4.0; - vec3 diffColor2 = centerColor2.rgb - meanColor2; - - vec3 gradColor = (meanColor + diffColor2); - - gl_FragColor = vec4(mix(centerColor.rgb, gradColor, centerColor2.a * mixturePercent), centerColor.a); - } -); -#else -NSString *const kGPUImagePoissonBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - varying vec2 topTextureCoordinate; - varying vec2 bottomTextureCoordinate; - - varying vec2 textureCoordinate2; - varying vec2 leftTextureCoordinate2; - varying vec2 rightTextureCoordinate2; - varying vec2 topTextureCoordinate2; - varying vec2 bottomTextureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - uniform float mixturePercent; - - void main() - { - vec4 centerColor = texture2D(inputImageTexture, textureCoordinate); - vec3 bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate).rgb; - vec3 leftColor = texture2D(inputImageTexture, leftTextureCoordinate).rgb; - vec3 rightColor = texture2D(inputImageTexture, rightTextureCoordinate).rgb; - vec3 topColor = texture2D(inputImageTexture, topTextureCoordinate).rgb; - - vec4 centerColor2 = texture2D(inputImageTexture2, textureCoordinate2); - vec3 bottomColor2 = texture2D(inputImageTexture2, bottomTextureCoordinate2).rgb; - vec3 leftColor2 = texture2D(inputImageTexture2, leftTextureCoordinate2).rgb; - vec3 rightColor2 = texture2D(inputImageTexture2, rightTextureCoordinate2).rgb; - vec3 topColor2 = texture2D(inputImageTexture2, topTextureCoordinate2).rgb; - - vec3 meanColor = (bottomColor + leftColor + rightColor + topColor) / 4.0; - vec3 diffColor = centerColor.rgb - meanColor; - - vec3 meanColor2 = (bottomColor2 + leftColor2 + rightColor2 + topColor2) / 4.0; - vec3 diffColor2 = centerColor2.rgb - meanColor2; - - vec3 gradColor = (meanColor + diffColor2); - - gl_FragColor = vec4(mix(centerColor.rgb, gradColor, centerColor2.a * mixturePercent), centerColor.a); - } -); -#endif - -@implementation GPUImagePoissonBlendFilter - -@synthesize mix = _mix; -@synthesize numIterations = _numIterations; - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImagePoissonBlendFragmentShaderString])) - { - return nil; - } - - mixUniform = [filterProgram uniformIndex:@"mixturePercent"]; - self.mix = 0.5; - - self.numIterations = 10; - - return self; -} - -- (void)setMix:(CGFloat)newValue; -{ - _mix = newValue; - - [self setFloat:_mix forUniform:mixUniform program:filterProgram]; -} - -//- (void)setOutputFBO; -//{ -// if (self.numIterations % 2 == 1) { -// [self setSecondFilterFBO]; -// } else { -// [self setFilterFBO]; -// } -//} - -- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates; -{ - // Run the first stage of the two-pass filter - [GPUImageContext setActiveShaderProgram:filterProgram]; - - [super renderToTextureWithVertices:vertices textureCoordinates:textureCoordinates]; - - for (int pass = 1; pass < self.numIterations; pass++) { - - if (pass % 2 == 0) { - - [GPUImageContext setActiveShaderProgram:filterProgram]; - - // TODO: This will over-unlock the incoming framebuffer - [super renderToTextureWithVertices:vertices textureCoordinates:[[self class] textureCoordinatesForRotation:kGPUImageNoRotation]]; - } else { - // Run the second stage of the two-pass filter - secondOutputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:[self sizeOfFBO] textureOptions:self.outputTextureOptions onlyTexture:NO]; - [secondOutputFramebuffer activateFramebuffer]; - - [GPUImageContext setActiveShaderProgram:filterProgram]; - - glClearColor(backgroundColorRed, backgroundColorGreen, backgroundColorBlue, backgroundColorAlpha); - glClear(GL_COLOR_BUFFER_BIT); - - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, [outputFramebuffer texture]); - glUniform1i(filterInputTextureUniform, 2); - - glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D, [secondInputFramebuffer texture]); - glUniform1i(filterInputTextureUniform2, 3); - - glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, vertices); - glVertexAttribPointer(filterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, [[self class] textureCoordinatesForRotation:kGPUImageNoRotation]); - glVertexAttribPointer(filterSecondTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, [[self class] textureCoordinatesForRotation:inputRotation2]); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - } - } -} - -@end \ No newline at end of file diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePolarPixellateFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePolarPixellateFilter.h deleted file mode 100755 index 3de6a4d3..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePolarPixellateFilter.h +++ /dev/null @@ -1,13 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImagePolarPixellateFilter : GPUImageFilter { - GLint centerUniform, pixelSizeUniform; -} - -// The center about which to apply the distortion, with a default of (0.5, 0.5) -@property(readwrite, nonatomic) CGPoint center; -// The amount of distortion to apply, from (-2.0, -2.0) to (2.0, 2.0), with a default of (0.05, 0.05) -@property(readwrite, nonatomic) CGSize pixelSize; - - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePolarPixellateFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePolarPixellateFilter.m deleted file mode 100755 index 5677db48..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePolarPixellateFilter.m +++ /dev/null @@ -1,128 +0,0 @@ -#import "GPUImagePolarPixellateFilter.h" - -// @fattjake based on vid by toneburst - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImagePolarPixellateFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform highp vec2 center; - uniform highp vec2 pixelSize; - - - void main() - { - highp vec2 normCoord = 2.0 * textureCoordinate - 1.0; - highp vec2 normCenter = 2.0 * center - 1.0; - - normCoord -= normCenter; - - highp float r = length(normCoord); // to polar coords - highp float phi = atan(normCoord.y, normCoord.x); // to polar coords - - r = r - mod(r, pixelSize.x) + 0.03; - phi = phi - mod(phi, pixelSize.y); - - normCoord.x = r * cos(phi); - normCoord.y = r * sin(phi); - - normCoord += normCenter; - - mediump vec2 textureCoordinateToUse = normCoord / 2.0 + 0.5; - - gl_FragColor = texture2D(inputImageTexture, textureCoordinateToUse ); - - } -); -#else -NSString *const kGPUImagePolarPixellateFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform vec2 center; - uniform vec2 pixelSize; - - - void main() - { - vec2 normCoord = 2.0 * textureCoordinate - 1.0; - vec2 normCenter = 2.0 * center - 1.0; - - normCoord -= normCenter; - - float r = length(normCoord); // to polar coords - float phi = atan(normCoord.y, normCoord.x); // to polar coords - - r = r - mod(r, pixelSize.x) + 0.03; - phi = phi - mod(phi, pixelSize.y); - - normCoord.x = r * cos(phi); - normCoord.y = r * sin(phi); - - normCoord += normCenter; - - vec2 textureCoordinateToUse = normCoord / 2.0 + 0.5; - - gl_FragColor = texture2D(inputImageTexture, textureCoordinateToUse ); - - } -); -#endif - - -@implementation GPUImagePolarPixellateFilter - -@synthesize center = _center; - -@synthesize pixelSize = _pixelSize; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImagePolarPixellateFragmentShaderString])) - { - return nil; - } - - pixelSizeUniform = [filterProgram uniformIndex:@"pixelSize"]; - centerUniform = [filterProgram uniformIndex:@"center"]; - - - self.pixelSize = CGSizeMake(0.05, 0.05); - self.center = CGPointMake(0.5, 0.5); - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -{ - [super setInputRotation:newInputRotation atIndex:textureIndex]; - [self setCenter:self.center]; -} - -- (void)setPixelSize:(CGSize)pixelSize -{ - _pixelSize = pixelSize; - - [self setSize:_pixelSize forUniform:pixelSizeUniform program:filterProgram]; -} - -- (void)setCenter:(CGPoint)newValue; -{ - _center = newValue; - - CGPoint rotatedPoint = [self rotatedPoint:_center forRotation:inputRotation]; - [self setPoint:rotatedPoint forUniform:centerUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePolkaDotFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePolkaDotFilter.h deleted file mode 100644 index 369b7737..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePolkaDotFilter.h +++ /dev/null @@ -1,10 +0,0 @@ -#import "GPUImagePixellateFilter.h" - -@interface GPUImagePolkaDotFilter : GPUImagePixellateFilter -{ - GLint dotScalingUniform; -} - -@property(readwrite, nonatomic) CGFloat dotScaling; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePolkaDotFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePolkaDotFilter.m deleted file mode 100644 index a439a043..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePolkaDotFilter.m +++ /dev/null @@ -1,85 +0,0 @@ -#import "GPUImagePolkaDotFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImagePolkaDotFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform highp float fractionalWidthOfPixel; - uniform highp float aspectRatio; - uniform highp float dotScaling; - - void main() - { - highp vec2 sampleDivisor = vec2(fractionalWidthOfPixel, fractionalWidthOfPixel / aspectRatio); - - highp vec2 samplePos = textureCoordinate - mod(textureCoordinate, sampleDivisor) + 0.5 * sampleDivisor; - highp vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); - highp vec2 adjustedSamplePos = vec2(samplePos.x, (samplePos.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); - highp float distanceFromSamplePoint = distance(adjustedSamplePos, textureCoordinateToUse); - lowp float checkForPresenceWithinDot = step(distanceFromSamplePoint, (fractionalWidthOfPixel * 0.5) * dotScaling); - - lowp vec4 inputColor = texture2D(inputImageTexture, samplePos); - - gl_FragColor = vec4(inputColor.rgb * checkForPresenceWithinDot, inputColor.a); - } -); -#else -NSString *const kGPUImagePolkaDotFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform float fractionalWidthOfPixel; - uniform float aspectRatio; - uniform float dotScaling; - - void main() - { - vec2 sampleDivisor = vec2(fractionalWidthOfPixel, fractionalWidthOfPixel / aspectRatio); - - vec2 samplePos = textureCoordinate - mod(textureCoordinate, sampleDivisor) + 0.5 * sampleDivisor; - vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); - vec2 adjustedSamplePos = vec2(samplePos.x, (samplePos.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); - float distanceFromSamplePoint = distance(adjustedSamplePos, textureCoordinateToUse); - float checkForPresenceWithinDot = step(distanceFromSamplePoint, (fractionalWidthOfPixel * 0.5) * dotScaling); - - vec4 inputColor = texture2D(inputImageTexture, samplePos); - - gl_FragColor = vec4(inputColor.rgb * checkForPresenceWithinDot, inputColor.a); - } -); -#endif - -@implementation GPUImagePolkaDotFilter - -@synthesize dotScaling = _dotScaling; - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImagePolkaDotFragmentShaderString])) - { - return nil; - } - - dotScalingUniform = [filterProgram uniformIndex:@"dotScaling"]; - - self.dotScaling = 0.90; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setDotScaling:(CGFloat)newValue; -{ - _dotScaling = newValue; - - [self setFloat:_dotScaling forUniform:dotScalingUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePosterizeFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePosterizeFilter.h deleted file mode 100755 index 6f655b3e..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePosterizeFilter.h +++ /dev/null @@ -1,14 +0,0 @@ -#import "GPUImageFilter.h" - -/** This reduces the color dynamic range into the number of steps specified, leading to a cartoon-like simple shading of the image. - */ -@interface GPUImagePosterizeFilter : GPUImageFilter -{ - GLint colorLevelsUniform; -} - -/** The number of color levels to reduce the image space to. This ranges from 1 to 256, with a default of 10. - */ -@property(readwrite, nonatomic) NSUInteger colorLevels; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePosterizeFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePosterizeFilter.m deleted file mode 100755 index a438cea5..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePosterizeFilter.m +++ /dev/null @@ -1,66 +0,0 @@ -#import "GPUImagePosterizeFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImagePosterizeFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform highp float colorLevels; - - void main() - { - highp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - gl_FragColor = floor((textureColor * colorLevels) + vec4(0.5)) / colorLevels; - } -); -#else -NSString *const kGPUImagePosterizeFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float colorLevels; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - gl_FragColor = floor((textureColor * colorLevels) + vec4(0.5)) / colorLevels; - } -); -#endif - -@implementation GPUImagePosterizeFilter - -@synthesize colorLevels = _colorLevels; - -#pragma mark - -#pragma mark Initialization - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImagePosterizeFragmentShaderString])) - { - return nil; - } - - colorLevelsUniform = [filterProgram uniformIndex:@"colorLevels"]; - self.colorLevels = 10; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setColorLevels:(NSUInteger)newValue; -{ - _colorLevels = newValue; - - [self setFloat:_colorLevels forUniform:colorLevelsUniform program:filterProgram]; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePrewittEdgeDetectionFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePrewittEdgeDetectionFilter.h deleted file mode 100755 index 141f8c5f..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePrewittEdgeDetectionFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImageSobelEdgeDetectionFilter.h" - -@interface GPUImagePrewittEdgeDetectionFilter : GPUImageSobelEdgeDetectionFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePrewittEdgeDetectionFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePrewittEdgeDetectionFilter.m deleted file mode 100755 index a9906930..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImagePrewittEdgeDetectionFilter.m +++ /dev/null @@ -1,97 +0,0 @@ -#import "GPUImagePrewittEdgeDetectionFilter.h" - -@implementation GPUImagePrewittEdgeDetectionFilter - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImagePrewittFragmentShaderString = SHADER_STRING -( - precision highp float; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float edgeStrength; - - void main() - { - float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r; - float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r; - float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r; - float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r; - float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r; - float h = -topLeftIntensity - topIntensity - topRightIntensity + bottomLeftIntensity + bottomIntensity + bottomRightIntensity; - float v = -bottomLeftIntensity - leftIntensity - topLeftIntensity + bottomRightIntensity + rightIntensity + topRightIntensity; - - float mag = length(vec2(h, v)) * edgeStrength; - - gl_FragColor = vec4(vec3(mag), 1.0); - } -); -#else -NSString *const kGPUImagePrewittFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float edgeStrength; - - void main() - { - float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r; - float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r; - float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r; - float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r; - float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r; - float h = -topLeftIntensity - topIntensity - topRightIntensity + bottomLeftIntensity + bottomIntensity + bottomRightIntensity; - float v = -bottomLeftIntensity - leftIntensity - topLeftIntensity + bottomRightIntensity + rightIntensity + topRightIntensity; - - float mag = length(vec2(h, v)) * edgeStrength; - - gl_FragColor = vec4(vec3(mag), 1.0); - } -); -#endif - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [self initWithFragmentShaderFromString:kGPUImagePrewittFragmentShaderString])) - { - return nil; - } - - self.edgeStrength = 1.0; - - return self; -} - - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBClosingFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBClosingFilter.h deleted file mode 100644 index 08d13f88..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBClosingFilter.h +++ /dev/null @@ -1,18 +0,0 @@ -#import "GPUImageFilterGroup.h" - -@class GPUImageRGBErosionFilter; -@class GPUImageRGBDilationFilter; - -// A filter that first performs a dilation on each color channel of an image, followed by an erosion of the same radius. -// This helps to filter out smaller dark elements. - -@interface GPUImageRGBClosingFilter : GPUImageFilterGroup -{ - GPUImageRGBErosionFilter *erosionFilter; - GPUImageRGBDilationFilter *dilationFilter; -} - -- (id)initWithRadius:(NSUInteger)radius; - - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBClosingFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBClosingFilter.m deleted file mode 100644 index c5bb1c8d..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBClosingFilter.m +++ /dev/null @@ -1,41 +0,0 @@ -#import "GPUImageRGBClosingFilter.h" -#import "GPUImageRGBErosionFilter.h" -#import "GPUImageRGBDilationFilter.h" - -@implementation GPUImageRGBClosingFilter - -- (id)init; -{ - if (!(self = [self initWithRadius:1])) - { - return nil; - } - - return self; -} - -- (id)initWithRadius:(NSUInteger)radius; -{ - if (!(self = [super init])) - { - return nil; - } - - // First pass: dilation - dilationFilter = [[GPUImageRGBDilationFilter alloc] initWithRadius:radius]; - [self addFilter:dilationFilter]; - - // Second pass: erosion - erosionFilter = [[GPUImageRGBErosionFilter alloc] initWithRadius:radius]; - [self addFilter:erosionFilter]; - - [dilationFilter addTarget:erosionFilter]; - - self.initialFilters = [NSArray arrayWithObjects:dilationFilter, nil]; - self.terminalFilter = erosionFilter; - - return self; -} - - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBDilationFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBDilationFilter.h deleted file mode 100644 index 68276f84..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBDilationFilter.h +++ /dev/null @@ -1,11 +0,0 @@ -#import "GPUImageTwoPassTextureSamplingFilter.h" - -// For each pixel, this sets it to the maximum value of each color channel in a rectangular neighborhood extending out dilationRadius pixels from the center. -// This extends out brighter colors, and can be used for abstraction of color images. - -@interface GPUImageRGBDilationFilter : GPUImageTwoPassTextureSamplingFilter - -// Acceptable values for dilationRadius, which sets the distance in pixels to sample out from the center, are 1, 2, 3, and 4. -- (id)initWithRadius:(NSUInteger)dilationRadius; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBDilationFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBDilationFilter.m deleted file mode 100644 index 9702c783..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBDilationFilter.m +++ /dev/null @@ -1,306 +0,0 @@ -#import "GPUImageRGBDilationFilter.h" -#import "GPUImageDilationFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageRGBDilationRadiusOneFragmentShaderString = SHADER_STRING -( - precision highp float; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - lowp vec4 centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate); - lowp vec4 oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate); - lowp vec4 oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate); - - lowp vec4 maxValue = max(centerIntensity, oneStepPositiveIntensity); - - gl_FragColor = max(maxValue, oneStepNegativeIntensity); - } -); - -NSString *const kGPUImageRGBDilationRadiusTwoFragmentShaderString = SHADER_STRING -( - precision highp float; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - lowp vec4 centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate); - lowp vec4 oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate); - lowp vec4 oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate); - lowp vec4 twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate); - lowp vec4 twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate); - - lowp vec4 maxValue = max(centerIntensity, oneStepPositiveIntensity); - maxValue = max(maxValue, oneStepNegativeIntensity); - maxValue = max(maxValue, twoStepsPositiveIntensity); - maxValue = max(maxValue, twoStepsNegativeIntensity); - - gl_FragColor = max(maxValue, twoStepsNegativeIntensity); - } -); - -NSString *const kGPUImageRGBDilationRadiusThreeFragmentShaderString = SHADER_STRING -( - precision highp float; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - varying vec2 threeStepsPositiveTextureCoordinate; - varying vec2 threeStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - lowp vec4 centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate); - lowp vec4 oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate); - lowp vec4 oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate); - lowp vec4 twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate); - lowp vec4 twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate); - lowp vec4 threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate); - lowp vec4 threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate); - - lowp vec4 maxValue = max(centerIntensity, oneStepPositiveIntensity); - maxValue = max(maxValue, oneStepNegativeIntensity); - maxValue = max(maxValue, twoStepsPositiveIntensity); - maxValue = max(maxValue, twoStepsNegativeIntensity); - maxValue = max(maxValue, threeStepsPositiveIntensity); - - gl_FragColor = max(maxValue, threeStepsNegativeIntensity); - } -); - -NSString *const kGPUImageRGBDilationRadiusFourFragmentShaderString = SHADER_STRING -( - precision highp float; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - varying vec2 threeStepsPositiveTextureCoordinate; - varying vec2 threeStepsNegativeTextureCoordinate; - varying vec2 fourStepsPositiveTextureCoordinate; - varying vec2 fourStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - lowp vec4 centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate); - lowp vec4 oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate); - lowp vec4 oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate); - lowp vec4 twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate); - lowp vec4 twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate); - lowp vec4 threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate); - lowp vec4 threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate); - lowp vec4 fourStepsPositiveIntensity = texture2D(inputImageTexture, fourStepsPositiveTextureCoordinate); - lowp vec4 fourStepsNegativeIntensity = texture2D(inputImageTexture, fourStepsNegativeTextureCoordinate); - - lowp vec4 maxValue = max(centerIntensity, oneStepPositiveIntensity); - maxValue = max(maxValue, oneStepNegativeIntensity); - maxValue = max(maxValue, twoStepsPositiveIntensity); - maxValue = max(maxValue, twoStepsNegativeIntensity); - maxValue = max(maxValue, threeStepsPositiveIntensity); - maxValue = max(maxValue, threeStepsNegativeIntensity); - maxValue = max(maxValue, fourStepsPositiveIntensity); - - gl_FragColor = max(maxValue, fourStepsNegativeIntensity); - } -); -#else -NSString *const kGPUImageRGBDilationRadiusOneFragmentShaderString = SHADER_STRING -( - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - vec4 centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate); - vec4 oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate); - vec4 oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate); - - vec4 maxValue = max(centerIntensity, oneStepPositiveIntensity); - - gl_FragColor = max(maxValue, oneStepNegativeIntensity); - } - ); - -NSString *const kGPUImageRGBDilationRadiusTwoFragmentShaderString = SHADER_STRING -( - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - vec4 centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate); - vec4 oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate); - vec4 oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate); - vec4 twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate); - vec4 twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate); - - vec4 maxValue = max(centerIntensity, oneStepPositiveIntensity); - maxValue = max(maxValue, oneStepNegativeIntensity); - maxValue = max(maxValue, twoStepsPositiveIntensity); - maxValue = max(maxValue, twoStepsNegativeIntensity); - - gl_FragColor = max(maxValue, twoStepsNegativeIntensity); - } - ); - -NSString *const kGPUImageRGBDilationRadiusThreeFragmentShaderString = SHADER_STRING -( - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - varying vec2 threeStepsPositiveTextureCoordinate; - varying vec2 threeStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - vec4 centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate); - vec4 oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate); - vec4 oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate); - vec4 twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate); - vec4 twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate); - vec4 threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate); - vec4 threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate); - - vec4 maxValue = max(centerIntensity, oneStepPositiveIntensity); - maxValue = max(maxValue, oneStepNegativeIntensity); - maxValue = max(maxValue, twoStepsPositiveIntensity); - maxValue = max(maxValue, twoStepsNegativeIntensity); - maxValue = max(maxValue, threeStepsPositiveIntensity); - - gl_FragColor = max(maxValue, threeStepsNegativeIntensity); - } -); - -NSString *const kGPUImageRGBDilationRadiusFourFragmentShaderString = SHADER_STRING -( - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - varying vec2 threeStepsPositiveTextureCoordinate; - varying vec2 threeStepsNegativeTextureCoordinate; - varying vec2 fourStepsPositiveTextureCoordinate; - varying vec2 fourStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - vec4 centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate); - vec4 oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate); - vec4 oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate); - vec4 twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate); - vec4 twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate); - vec4 threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate); - vec4 threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate); - vec4 fourStepsPositiveIntensity = texture2D(inputImageTexture, fourStepsPositiveTextureCoordinate); - vec4 fourStepsNegativeIntensity = texture2D(inputImageTexture, fourStepsNegativeTextureCoordinate); - - vec4 maxValue = max(centerIntensity, oneStepPositiveIntensity); - maxValue = max(maxValue, oneStepNegativeIntensity); - maxValue = max(maxValue, twoStepsPositiveIntensity); - maxValue = max(maxValue, twoStepsNegativeIntensity); - maxValue = max(maxValue, threeStepsPositiveIntensity); - maxValue = max(maxValue, threeStepsNegativeIntensity); - maxValue = max(maxValue, fourStepsPositiveIntensity); - - gl_FragColor = max(maxValue, fourStepsNegativeIntensity); - } -); -#endif - -@implementation GPUImageRGBDilationFilter - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithRadius:(NSUInteger)dilationRadius; -{ - NSString *fragmentShaderForThisRadius = nil; - NSString *vertexShaderForThisRadius = nil; - - switch (dilationRadius) - { - case 0: - case 1: - { - vertexShaderForThisRadius = kGPUImageDilationRadiusOneVertexShaderString; - fragmentShaderForThisRadius = kGPUImageRGBDilationRadiusOneFragmentShaderString; - }; break; - case 2: - { - vertexShaderForThisRadius = kGPUImageDilationRadiusTwoVertexShaderString; - fragmentShaderForThisRadius = kGPUImageRGBDilationRadiusTwoFragmentShaderString; - }; break; - case 3: - { - vertexShaderForThisRadius = kGPUImageDilationRadiusThreeVertexShaderString; - fragmentShaderForThisRadius = kGPUImageRGBDilationRadiusThreeFragmentShaderString; - }; break; - case 4: - { - vertexShaderForThisRadius = kGPUImageDilationRadiusFourVertexShaderString; - fragmentShaderForThisRadius = kGPUImageRGBDilationRadiusFourFragmentShaderString; - }; break; - default: - { - vertexShaderForThisRadius = kGPUImageDilationRadiusFourVertexShaderString; - fragmentShaderForThisRadius = kGPUImageRGBDilationRadiusFourFragmentShaderString; - }; break; - } - - if (!(self = [super initWithFirstStageVertexShaderFromString:vertexShaderForThisRadius firstStageFragmentShaderFromString:fragmentShaderForThisRadius secondStageVertexShaderFromString:vertexShaderForThisRadius secondStageFragmentShaderFromString:fragmentShaderForThisRadius])) - { - return nil; - } - - return self; -} - -- (id)init; -{ - if (!(self = [self initWithRadius:1])) - { - return nil; - } - - return self; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBErosionFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBErosionFilter.h deleted file mode 100644 index 5979cb7e..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBErosionFilter.h +++ /dev/null @@ -1,11 +0,0 @@ -#import "GPUImageTwoPassTextureSamplingFilter.h" - -// For each pixel, this sets it to the minimum value of each color channel in a rectangular neighborhood extending out dilationRadius pixels from the center. -// This extends out dark features, and can be used for abstraction of color images. - -@interface GPUImageRGBErosionFilter : GPUImageTwoPassTextureSamplingFilter - -// Acceptable values for erosionRadius, which sets the distance in pixels to sample out from the center, are 1, 2, 3, and 4. -- (id)initWithRadius:(NSUInteger)erosionRadius; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBErosionFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBErosionFilter.m deleted file mode 100644 index 91e5f33d..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBErosionFilter.m +++ /dev/null @@ -1,304 +0,0 @@ -#import "GPUImageRGBErosionFilter.h" -#import "GPUImageDilationFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageRGBErosionRadiusOneFragmentShaderString = SHADER_STRING -( - precision highp float; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - lowp vec4 centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate); - lowp vec4 oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate); - lowp vec4 oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate); - - lowp vec4 minValue = min(centerIntensity, oneStepPositiveIntensity); - - gl_FragColor = min(minValue, oneStepNegativeIntensity); - } -); - -NSString *const kGPUImageRGBErosionRadiusTwoFragmentShaderString = SHADER_STRING -( - precision highp float; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - lowp vec4 centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate); - lowp vec4 oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate); - lowp vec4 oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate); - lowp vec4 twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate); - lowp vec4 twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate); - - lowp vec4 minValue = min(centerIntensity, oneStepPositiveIntensity); - minValue = min(minValue, oneStepNegativeIntensity); - minValue = min(minValue, twoStepsPositiveIntensity); - - gl_FragColor = min(minValue, twoStepsNegativeIntensity); - } - ); - -NSString *const kGPUImageRGBErosionRadiusThreeFragmentShaderString = SHADER_STRING -( - precision highp float; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - varying vec2 threeStepsPositiveTextureCoordinate; - varying vec2 threeStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - lowp vec4 centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate); - lowp vec4 oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate); - lowp vec4 oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate); - lowp vec4 twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate); - lowp vec4 twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate); - lowp vec4 threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate); - lowp vec4 threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate); - - lowp vec4 minValue = min(centerIntensity, oneStepPositiveIntensity); - minValue = min(minValue, oneStepNegativeIntensity); - minValue = min(minValue, twoStepsPositiveIntensity); - minValue = min(minValue, twoStepsNegativeIntensity); - minValue = min(minValue, threeStepsPositiveIntensity); - - gl_FragColor = min(minValue, threeStepsNegativeIntensity); - } - ); - -NSString *const kGPUImageRGBErosionRadiusFourFragmentShaderString = SHADER_STRING -( - precision highp float; - - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - varying vec2 threeStepsPositiveTextureCoordinate; - varying vec2 threeStepsNegativeTextureCoordinate; - varying vec2 fourStepsPositiveTextureCoordinate; - varying vec2 fourStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - lowp vec4 centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate); - lowp vec4 oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate); - lowp vec4 oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate); - lowp vec4 twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate); - lowp vec4 twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate); - lowp vec4 threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate); - lowp vec4 threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate); - lowp vec4 fourStepsPositiveIntensity = texture2D(inputImageTexture, fourStepsPositiveTextureCoordinate); - lowp vec4 fourStepsNegativeIntensity = texture2D(inputImageTexture, fourStepsNegativeTextureCoordinate); - - lowp vec4 minValue = min(centerIntensity, oneStepPositiveIntensity); - minValue = min(minValue, oneStepNegativeIntensity); - minValue = min(minValue, twoStepsPositiveIntensity); - minValue = min(minValue, twoStepsNegativeIntensity); - minValue = min(minValue, threeStepsPositiveIntensity); - minValue = min(minValue, threeStepsNegativeIntensity); - minValue = min(minValue, fourStepsPositiveIntensity); - - gl_FragColor = min(minValue, fourStepsNegativeIntensity); - } -); -#else -NSString *const kGPUImageRGBErosionRadiusOneFragmentShaderString = SHADER_STRING -( - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - vec4 centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate); - vec4 oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate); - vec4 oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate); - - vec4 minValue = min(centerIntensity, oneStepPositiveIntensity); - - gl_FragColor = min(minValue, oneStepNegativeIntensity); - } -); - -NSString *const kGPUImageRGBErosionRadiusTwoFragmentShaderString = SHADER_STRING -( - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - vec4 centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate); - vec4 oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate); - vec4 oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate); - vec4 twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate); - vec4 twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate); - - vec4 minValue = min(centerIntensity, oneStepPositiveIntensity); - minValue = min(minValue, oneStepNegativeIntensity); - minValue = min(minValue, twoStepsPositiveIntensity); - - gl_FragColor = min(minValue, twoStepsNegativeIntensity); - } -); - -NSString *const kGPUImageRGBErosionRadiusThreeFragmentShaderString = SHADER_STRING -( - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - varying vec2 threeStepsPositiveTextureCoordinate; - varying vec2 threeStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - vec4 centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate); - vec4 oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate); - vec4 oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate); - vec4 twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate); - vec4 twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate); - vec4 threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate); - vec4 threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate); - - vec4 minValue = min(centerIntensity, oneStepPositiveIntensity); - minValue = min(minValue, oneStepNegativeIntensity); - minValue = min(minValue, twoStepsPositiveIntensity); - minValue = min(minValue, twoStepsNegativeIntensity); - minValue = min(minValue, threeStepsPositiveIntensity); - - gl_FragColor = min(minValue, threeStepsNegativeIntensity); - } -); - -NSString *const kGPUImageRGBErosionRadiusFourFragmentShaderString = SHADER_STRING -( - varying vec2 centerTextureCoordinate; - varying vec2 oneStepPositiveTextureCoordinate; - varying vec2 oneStepNegativeTextureCoordinate; - varying vec2 twoStepsPositiveTextureCoordinate; - varying vec2 twoStepsNegativeTextureCoordinate; - varying vec2 threeStepsPositiveTextureCoordinate; - varying vec2 threeStepsNegativeTextureCoordinate; - varying vec2 fourStepsPositiveTextureCoordinate; - varying vec2 fourStepsNegativeTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - vec4 centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate); - vec4 oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate); - vec4 oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate); - vec4 twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate); - vec4 twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate); - vec4 threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate); - vec4 threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate); - vec4 fourStepsPositiveIntensity = texture2D(inputImageTexture, fourStepsPositiveTextureCoordinate); - vec4 fourStepsNegativeIntensity = texture2D(inputImageTexture, fourStepsNegativeTextureCoordinate); - - vec4 minValue = min(centerIntensity, oneStepPositiveIntensity); - minValue = min(minValue, oneStepNegativeIntensity); - minValue = min(minValue, twoStepsPositiveIntensity); - minValue = min(minValue, twoStepsNegativeIntensity); - minValue = min(minValue, threeStepsPositiveIntensity); - minValue = min(minValue, threeStepsNegativeIntensity); - minValue = min(minValue, fourStepsPositiveIntensity); - - gl_FragColor = min(minValue, fourStepsNegativeIntensity); - } -); -#endif - -@implementation GPUImageRGBErosionFilter - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithRadius:(NSUInteger)erosionRadius; -{ - NSString *fragmentShaderForThisRadius = nil; - NSString *vertexShaderForThisRadius = nil; - - switch (erosionRadius) - { - case 0: - case 1: - { - vertexShaderForThisRadius = kGPUImageDilationRadiusOneVertexShaderString; - fragmentShaderForThisRadius = kGPUImageRGBErosionRadiusOneFragmentShaderString; - }; break; - case 2: - { - vertexShaderForThisRadius = kGPUImageDilationRadiusTwoVertexShaderString; - fragmentShaderForThisRadius = kGPUImageRGBErosionRadiusTwoFragmentShaderString; - }; break; - case 3: - { - vertexShaderForThisRadius = kGPUImageDilationRadiusThreeVertexShaderString; - fragmentShaderForThisRadius = kGPUImageRGBErosionRadiusThreeFragmentShaderString; - }; break; - case 4: - { - vertexShaderForThisRadius = kGPUImageDilationRadiusFourVertexShaderString; - fragmentShaderForThisRadius = kGPUImageRGBErosionRadiusFourFragmentShaderString; - }; break; - default: - { - vertexShaderForThisRadius = kGPUImageDilationRadiusFourVertexShaderString; - fragmentShaderForThisRadius = kGPUImageRGBErosionRadiusFourFragmentShaderString; - }; break; - } - - if (!(self = [super initWithFirstStageVertexShaderFromString:vertexShaderForThisRadius firstStageFragmentShaderFromString:fragmentShaderForThisRadius secondStageVertexShaderFromString:vertexShaderForThisRadius secondStageFragmentShaderFromString:fragmentShaderForThisRadius])) - { - return nil; - } - - return self; -} - -- (id)init; -{ - if (!(self = [self initWithRadius:1])) - { - return nil; - } - - return self; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBFilter.h deleted file mode 100755 index 18966b1b..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBFilter.h +++ /dev/null @@ -1,15 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageRGBFilter : GPUImageFilter -{ - GLint redUniform; - GLint greenUniform; - GLint blueUniform; -} - -// Normalized values by which each color channel is multiplied. The range is from 0.0 up, with 1.0 as the default. -@property (readwrite, nonatomic) CGFloat red; -@property (readwrite, nonatomic) CGFloat green; -@property (readwrite, nonatomic) CGFloat blue; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBFilter.m deleted file mode 100755 index 7a2e5681..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBFilter.m +++ /dev/null @@ -1,89 +0,0 @@ -#import "GPUImageRGBFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageRGBFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform highp float redAdjustment; - uniform highp float greenAdjustment; - uniform highp float blueAdjustment; - - void main() - { - highp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - gl_FragColor = vec4(textureColor.r * redAdjustment, textureColor.g * greenAdjustment, textureColor.b * blueAdjustment, textureColor.a); - } -); -#else -NSString *const kGPUImageRGBFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float redAdjustment; - uniform float greenAdjustment; - uniform float blueAdjustment; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - gl_FragColor = vec4(textureColor.r * redAdjustment, textureColor.g * greenAdjustment, textureColor.b * blueAdjustment, textureColor.a); - } - ); -#endif - -@implementation GPUImageRGBFilter - -@synthesize red = _red, blue = _blue, green = _green; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageRGBFragmentShaderString])) - { - return nil; - } - - redUniform = [filterProgram uniformIndex:@"redAdjustment"]; - self.red = 1.0; - - greenUniform = [filterProgram uniformIndex:@"greenAdjustment"]; - self.green = 1.0; - - blueUniform = [filterProgram uniformIndex:@"blueAdjustment"]; - self.blue = 1.0; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setRed:(CGFloat)newValue; -{ - _red = newValue; - - [self setFloat:_red forUniform:redUniform program:filterProgram]; -} - -- (void)setGreen:(CGFloat)newValue; -{ - _green = newValue; - - [self setFloat:_green forUniform:greenUniform program:filterProgram]; -} - -- (void)setBlue:(CGFloat)newValue; -{ - _blue = newValue; - - [self setFloat:_blue forUniform:blueUniform program:filterProgram]; -} - -@end \ No newline at end of file diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBOpeningFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBOpeningFilter.h deleted file mode 100644 index dbec75fb..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBOpeningFilter.h +++ /dev/null @@ -1,17 +0,0 @@ -#import "GPUImageFilterGroup.h" - -@class GPUImageRGBErosionFilter; -@class GPUImageRGBDilationFilter; - -// A filter that first performs an erosion on each color channel of an image, followed by a dilation of the same radius. -// This helps to filter out smaller bright elements. - -@interface GPUImageRGBOpeningFilter : GPUImageFilterGroup -{ - GPUImageRGBErosionFilter *erosionFilter; - GPUImageRGBDilationFilter *dilationFilter; -} - -- (id)initWithRadius:(NSUInteger)radius; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBOpeningFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBOpeningFilter.m deleted file mode 100644 index 9d53021e..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRGBOpeningFilter.m +++ /dev/null @@ -1,41 +0,0 @@ -#import "GPUImageRGBOpeningFilter.h" -#import "GPUImageRGBErosionFilter.h" -#import "GPUImageRGBDilationFilter.h" - -@implementation GPUImageRGBOpeningFilter - -- (id)init; -{ - if (!(self = [self initWithRadius:1])) - { - return nil; - } - - return self; -} - -- (id)initWithRadius:(NSUInteger)radius; -{ - if (!(self = [super init])) - { - return nil; - } - - // First pass: erosion - erosionFilter = [[GPUImageRGBErosionFilter alloc] initWithRadius:radius]; - [self addFilter:erosionFilter]; - - // Second pass: dilation - dilationFilter = [[GPUImageRGBDilationFilter alloc] initWithRadius:radius]; - [self addFilter:dilationFilter]; - - [erosionFilter addTarget:dilationFilter]; - - self.initialFilters = [NSArray arrayWithObjects:erosionFilter, nil]; - self.terminalFilter = dilationFilter; - - return self; -} - - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRawDataInput.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRawDataInput.h deleted file mode 100644 index 6ec4720f..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRawDataInput.h +++ /dev/null @@ -1,43 +0,0 @@ -#import "GPUImageOutput.h" - -// The bytes passed into this input are not copied or retained, but you are free to deallocate them after they are used by this filter. -// The bytes are uploaded and stored within a texture, so nothing is kept locally. -// The default format for input bytes is GPUPixelFormatBGRA, unless specified with pixelFormat: -// The default type for input bytes is GPUPixelTypeUByte, unless specified with pixelType: - -typedef enum { - GPUPixelFormatBGRA = GL_BGRA, - GPUPixelFormatRGBA = GL_RGBA, - GPUPixelFormatRGB = GL_RGB, - GPUPixelFormatLuminance = GL_LUMINANCE -} GPUPixelFormat; - -typedef enum { - GPUPixelTypeUByte = GL_UNSIGNED_BYTE, - GPUPixelTypeFloat = GL_FLOAT -} GPUPixelType; - -@interface GPUImageRawDataInput : GPUImageOutput -{ - CGSize uploadedImageSize; - - dispatch_semaphore_t dataUpdateSemaphore; -} - -// Initialization and teardown -- (id)initWithBytes:(GLubyte *)bytesToUpload size:(CGSize)imageSize; -- (id)initWithBytes:(GLubyte *)bytesToUpload size:(CGSize)imageSize pixelFormat:(GPUPixelFormat)pixelFormat; -- (id)initWithBytes:(GLubyte *)bytesToUpload size:(CGSize)imageSize pixelFormat:(GPUPixelFormat)pixelFormat type:(GPUPixelType)pixelType; - -/** Input data pixel format - */ -@property (readwrite, nonatomic) GPUPixelFormat pixelFormat; -@property (readwrite, nonatomic) GPUPixelType pixelType; - -// Image rendering -- (void)updateDataFromBytes:(GLubyte *)bytesToUpload size:(CGSize)imageSize; -- (void)processData; -- (void)processDataForTimestamp:(CMTime)frameTime; -- (CGSize)outputImageSize; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRawDataInput.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRawDataInput.m deleted file mode 100644 index 4b6bfa74..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRawDataInput.m +++ /dev/null @@ -1,139 +0,0 @@ -#import "GPUImageRawDataInput.h" - -@interface GPUImageRawDataInput() -- (void)uploadBytes:(GLubyte *)bytesToUpload; -@end - -@implementation GPUImageRawDataInput - -@synthesize pixelFormat = _pixelFormat; -@synthesize pixelType = _pixelType; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithBytes:(GLubyte *)bytesToUpload size:(CGSize)imageSize; -{ - if (!(self = [self initWithBytes:bytesToUpload size:imageSize pixelFormat:GPUPixelFormatBGRA type:GPUPixelTypeUByte])) - { - return nil; - } - - return self; -} - -- (id)initWithBytes:(GLubyte *)bytesToUpload size:(CGSize)imageSize pixelFormat:(GPUPixelFormat)pixelFormat; -{ - if (!(self = [self initWithBytes:bytesToUpload size:imageSize pixelFormat:pixelFormat type:GPUPixelTypeUByte])) - { - return nil; - } - - return self; -} - -- (id)initWithBytes:(GLubyte *)bytesToUpload size:(CGSize)imageSize pixelFormat:(GPUPixelFormat)pixelFormat type:(GPUPixelType)pixelType; -{ - if (!(self = [super init])) - { - return nil; - } - - dataUpdateSemaphore = dispatch_semaphore_create(1); - - uploadedImageSize = imageSize; - self.pixelFormat = pixelFormat; - self.pixelType = pixelType; - - [self uploadBytes:bytesToUpload]; - - return self; -} - -// ARC forbids explicit message send of 'release'; since iOS 6 even for dispatch_release() calls: stripping it out in that case is required. -- (void)dealloc; -{ -#if !OS_OBJECT_USE_OBJC - if (dataUpdateSemaphore != NULL) - { - dispatch_release(dataUpdateSemaphore); - } -#endif -} - -#pragma mark - -#pragma mark Image rendering - -- (void)uploadBytes:(GLubyte *)bytesToUpload; -{ - [GPUImageContext useImageProcessingContext]; - - // TODO: This probably isn't right, and will need to be corrected - outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:uploadedImageSize textureOptions:self.outputTextureOptions onlyTexture:YES]; - - glBindTexture(GL_TEXTURE_2D, [outputFramebuffer texture]); - glTexImage2D(GL_TEXTURE_2D, 0, _pixelFormat==GPUPixelFormatRGB ? GL_RGB : GL_RGBA, (int)uploadedImageSize.width, (int)uploadedImageSize.height, 0, (GLint)_pixelFormat, (GLenum)_pixelType, bytesToUpload); -} - -- (void)updateDataFromBytes:(GLubyte *)bytesToUpload size:(CGSize)imageSize; -{ - uploadedImageSize = imageSize; - - [self uploadBytes:bytesToUpload]; -} - -- (void)processData; -{ - if (dispatch_semaphore_wait(dataUpdateSemaphore, DISPATCH_TIME_NOW) != 0) - { - return; - } - - runAsynchronouslyOnVideoProcessingQueue(^{ - - CGSize pixelSizeOfImage = [self outputImageSize]; - - for (id currentTarget in targets) - { - NSInteger indexOfObject = [targets indexOfObject:currentTarget]; - NSInteger textureIndexOfTarget = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; - - [currentTarget setInputSize:pixelSizeOfImage atIndex:textureIndexOfTarget]; - [currentTarget setInputFramebuffer:outputFramebuffer atIndex:textureIndexOfTarget]; - [currentTarget newFrameReadyAtTime:kCMTimeInvalid atIndex:textureIndexOfTarget]; - } - - dispatch_semaphore_signal(dataUpdateSemaphore); - }); -} - -- (void)processDataForTimestamp:(CMTime)frameTime; -{ - if (dispatch_semaphore_wait(dataUpdateSemaphore, DISPATCH_TIME_NOW) != 0) - { - return; - } - - runAsynchronouslyOnVideoProcessingQueue(^{ - - CGSize pixelSizeOfImage = [self outputImageSize]; - - for (id currentTarget in targets) - { - NSInteger indexOfObject = [targets indexOfObject:currentTarget]; - NSInteger textureIndexOfTarget = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; - - [currentTarget setInputSize:pixelSizeOfImage atIndex:textureIndexOfTarget]; - [currentTarget newFrameReadyAtTime:frameTime atIndex:textureIndexOfTarget]; - } - - dispatch_semaphore_signal(dataUpdateSemaphore); - }); -} - -- (CGSize)outputImageSize; -{ - return uploadedImageSize; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRawDataOutput.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRawDataOutput.h deleted file mode 100755 index 5a4538c1..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRawDataOutput.h +++ /dev/null @@ -1,44 +0,0 @@ -#import -#import "GPUImageContext.h" - -struct GPUByteColorVector { - GLubyte red; - GLubyte green; - GLubyte blue; - GLubyte alpha; -}; -typedef struct GPUByteColorVector GPUByteColorVector; - -@protocol GPUImageRawDataProcessor; - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -@interface GPUImageRawDataOutput : NSObject { - CGSize imageSize; - GPUImageRotationMode inputRotation; - BOOL outputBGRA; -} -#else -@interface GPUImageRawDataOutput : NSObject { - CGSize imageSize; - GPUImageRotationMode inputRotation; - BOOL outputBGRA; -} -#endif - -@property(readonly) GLubyte *rawBytesForImage; -@property(nonatomic, copy) void(^newFrameAvailableBlock)(void); -@property(nonatomic) BOOL enabled; - -// Initialization and teardown -- (id)initWithImageSize:(CGSize)newImageSize resultsInBGRAFormat:(BOOL)resultsInBGRAFormat; - -// Data access -- (GPUByteColorVector)colorAtLocation:(CGPoint)locationInImage; -- (NSUInteger)bytesPerRowInOutput; - -- (void)setImageSize:(CGSize)newImageSize; - -- (void)lockFramebufferForReading; -- (void)unlockFramebufferAfterReading; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRawDataOutput.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRawDataOutput.m deleted file mode 100755 index 18101e2c..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageRawDataOutput.m +++ /dev/null @@ -1,307 +0,0 @@ -#import "GPUImageRawDataOutput.h" - -#import "GPUImageContext.h" -#import "GLProgram.h" -#import "GPUImageFilter.h" -#import "GPUImageMovieWriter.h" - -@interface GPUImageRawDataOutput () -{ - GPUImageFramebuffer *firstInputFramebuffer, *outputFramebuffer, *retainedFramebuffer; - - BOOL hasReadFromTheCurrentFrame; - - GLProgram *dataProgram; - GLint dataPositionAttribute, dataTextureCoordinateAttribute; - GLint dataInputTextureUniform; - - GLubyte *_rawBytesForImage; - - BOOL lockNextFramebuffer; -} - -// Frame rendering -- (void)renderAtInternalSize; - -@end - -@implementation GPUImageRawDataOutput - -@synthesize rawBytesForImage = _rawBytesForImage; -@synthesize newFrameAvailableBlock = _newFrameAvailableBlock; -@synthesize enabled; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithImageSize:(CGSize)newImageSize resultsInBGRAFormat:(BOOL)resultsInBGRAFormat; -{ - if (!(self = [super init])) - { - return nil; - } - - self.enabled = YES; - lockNextFramebuffer = NO; - outputBGRA = resultsInBGRAFormat; - imageSize = newImageSize; - hasReadFromTheCurrentFrame = NO; - _rawBytesForImage = NULL; - inputRotation = kGPUImageNoRotation; - - [GPUImageContext useImageProcessingContext]; - if ( (outputBGRA && ![GPUImageContext supportsFastTextureUpload]) || (!outputBGRA && [GPUImageContext supportsFastTextureUpload]) ) - { - dataProgram = [[GPUImageContext sharedImageProcessingContext] programForVertexShaderString:kGPUImageVertexShaderString fragmentShaderString:kGPUImageColorSwizzlingFragmentShaderString]; - } - else - { - dataProgram = [[GPUImageContext sharedImageProcessingContext] programForVertexShaderString:kGPUImageVertexShaderString fragmentShaderString:kGPUImagePassthroughFragmentShaderString]; - } - - if (!dataProgram.initialized) - { - [dataProgram addAttribute:@"position"]; - [dataProgram addAttribute:@"inputTextureCoordinate"]; - - if (![dataProgram link]) - { - NSString *progLog = [dataProgram programLog]; - NSLog(@"Program link log: %@", progLog); - NSString *fragLog = [dataProgram fragmentShaderLog]; - NSLog(@"Fragment shader compile log: %@", fragLog); - NSString *vertLog = [dataProgram vertexShaderLog]; - NSLog(@"Vertex shader compile log: %@", vertLog); - dataProgram = nil; - NSAssert(NO, @"Filter shader link failed"); - } - } - - dataPositionAttribute = [dataProgram attributeIndex:@"position"]; - dataTextureCoordinateAttribute = [dataProgram attributeIndex:@"inputTextureCoordinate"]; - dataInputTextureUniform = [dataProgram uniformIndex:@"inputImageTexture"]; - - return self; -} - -- (void)dealloc -{ - if (_rawBytesForImage != NULL && (![GPUImageContext supportsFastTextureUpload])) - { - free(_rawBytesForImage); - _rawBytesForImage = NULL; - } -} - -#pragma mark - -#pragma mark Data access - -- (void)renderAtInternalSize; -{ - [GPUImageContext setActiveShaderProgram:dataProgram]; - - outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:imageSize onlyTexture:NO]; - [outputFramebuffer activateFramebuffer]; - - if(lockNextFramebuffer) - { - retainedFramebuffer = outputFramebuffer; - [retainedFramebuffer lock]; - [retainedFramebuffer lockForReading]; - lockNextFramebuffer = NO; - } - - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - static const GLfloat squareVertices[] = { - -1.0f, -1.0f, - 1.0f, -1.0f, - -1.0f, 1.0f, - 1.0f, 1.0f, - }; - - static const GLfloat textureCoordinates[] = { - 0.0f, 0.0f, - 1.0f, 0.0f, - 0.0f, 1.0f, - 1.0f, 1.0f, - }; - - glActiveTexture(GL_TEXTURE4); - glBindTexture(GL_TEXTURE_2D, [firstInputFramebuffer texture]); - glUniform1i(dataInputTextureUniform, 4); - - glVertexAttribPointer(dataPositionAttribute, 2, GL_FLOAT, 0, 0, squareVertices); - glVertexAttribPointer(dataTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates); - - glEnableVertexAttribArray(dataPositionAttribute); - glEnableVertexAttribArray(dataTextureCoordinateAttribute); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - [firstInputFramebuffer unlock]; -} - -- (GPUByteColorVector)colorAtLocation:(CGPoint)locationInImage; -{ - GPUByteColorVector *imageColorBytes = (GPUByteColorVector *)self.rawBytesForImage; -// NSLog(@"Row start"); -// for (unsigned int currentXPosition = 0; currentXPosition < (imageSize.width * 2.0); currentXPosition++) -// { -// GPUByteColorVector byteAtPosition = imageColorBytes[currentXPosition]; -// NSLog(@"%d - %d, %d, %d", currentXPosition, byteAtPosition.red, byteAtPosition.green, byteAtPosition.blue); -// } -// NSLog(@"Row end"); - -// GPUByteColorVector byteAtOne = imageColorBytes[1]; -// GPUByteColorVector byteAtWidth = imageColorBytes[(int)imageSize.width - 3]; -// GPUByteColorVector byteAtHeight = imageColorBytes[(int)(imageSize.height - 1) * (int)imageSize.width]; -// NSLog(@"Byte 1: %d, %d, %d, byte 2: %d, %d, %d, byte 3: %d, %d, %d", byteAtOne.red, byteAtOne.green, byteAtOne.blue, byteAtWidth.red, byteAtWidth.green, byteAtWidth.blue, byteAtHeight.red, byteAtHeight.green, byteAtHeight.blue); - - CGPoint locationToPickFrom = CGPointZero; - locationToPickFrom.x = MIN(MAX(locationInImage.x, 0.0), (imageSize.width - 1.0)); - locationToPickFrom.y = MIN(MAX((imageSize.height - locationInImage.y), 0.0), (imageSize.height - 1.0)); - - if (outputBGRA) - { - GPUByteColorVector flippedColor = imageColorBytes[(int)(round((locationToPickFrom.y * imageSize.width) + locationToPickFrom.x))]; - GLubyte temporaryRed = flippedColor.red; - - flippedColor.red = flippedColor.blue; - flippedColor.blue = temporaryRed; - - return flippedColor; - } - else - { - return imageColorBytes[(int)(round((locationToPickFrom.y * imageSize.width) + locationToPickFrom.x))]; - } -} - -#pragma mark - -#pragma mark GPUImageInput protocol - -- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex; -{ - hasReadFromTheCurrentFrame = NO; - - if (_newFrameAvailableBlock != NULL) - { - _newFrameAvailableBlock(); - } -} - -- (NSInteger)nextAvailableTextureIndex; -{ - return 0; -} - -- (void)setInputFramebuffer:(GPUImageFramebuffer *)newInputFramebuffer atIndex:(NSInteger)textureIndex; -{ - firstInputFramebuffer = newInputFramebuffer; - [firstInputFramebuffer lock]; -} - -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -{ - inputRotation = newInputRotation; -} - -- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex; -{ -} - -- (CGSize)maximumOutputSize; -{ - return imageSize; -} - -- (void)endProcessing; -{ -} - -- (BOOL)shouldIgnoreUpdatesToThisTarget; -{ - return NO; -} - -- (BOOL)wantsMonochromeInput; -{ - return NO; -} - -- (void)setCurrentlyReceivingMonochromeInput:(BOOL)newValue; -{ - -} - -#pragma mark - -#pragma mark Accessors - -- (GLubyte *)rawBytesForImage; -{ - if ( (_rawBytesForImage == NULL) && (![GPUImageContext supportsFastTextureUpload]) ) - { - _rawBytesForImage = (GLubyte *) calloc(imageSize.width * imageSize.height * 4, sizeof(GLubyte)); - hasReadFromTheCurrentFrame = NO; - } - - if (hasReadFromTheCurrentFrame) - { - return _rawBytesForImage; - } - else - { - runSynchronouslyOnVideoProcessingQueue(^{ - // Note: the fast texture caches speed up 640x480 frame reads from 9.6 ms to 3.1 ms on iPhone 4S - - [GPUImageContext useImageProcessingContext]; - [self renderAtInternalSize]; - - if ([GPUImageContext supportsFastTextureUpload]) - { - glFinish(); - _rawBytesForImage = [outputFramebuffer byteBuffer]; - } - else - { - glReadPixels(0, 0, imageSize.width, imageSize.height, GL_RGBA, GL_UNSIGNED_BYTE, _rawBytesForImage); - // GL_EXT_read_format_bgra - // glReadPixels(0, 0, imageSize.width, imageSize.height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, _rawBytesForImage); - } - - hasReadFromTheCurrentFrame = YES; - - }); - - return _rawBytesForImage; - } -} - -- (NSUInteger)bytesPerRowInOutput; -{ - return [retainedFramebuffer bytesPerRow]; -} - -- (void)setImageSize:(CGSize)newImageSize { - imageSize = newImageSize; - if (_rawBytesForImage != NULL && (![GPUImageContext supportsFastTextureUpload])) - { - free(_rawBytesForImage); - _rawBytesForImage = NULL; - } -} - -- (void)lockFramebufferForReading; -{ - lockNextFramebuffer = YES; -} - -- (void)unlockFramebufferAfterReading; -{ - [retainedFramebuffer unlockAfterReading]; - [retainedFramebuffer unlock]; - retainedFramebuffer = nil; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSaturationBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSaturationBlendFilter.h deleted file mode 100644 index 767892a5..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSaturationBlendFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageSaturationBlendFilter : GPUImageTwoInputFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSaturationBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSaturationBlendFilter.m deleted file mode 100644 index da37f6aa..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSaturationBlendFilter.m +++ /dev/null @@ -1,213 +0,0 @@ -#import "GPUImageSaturationBlendFilter.h" - -/** - * Saturation blend mode based upon pseudo code from the PDF specification. - */ -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageSaturationBlendFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - highp float lum(lowp vec3 c) { - return dot(c, vec3(0.3, 0.59, 0.11)); - } - - lowp vec3 clipcolor(lowp vec3 c) { - highp float l = lum(c); - lowp float n = min(min(c.r, c.g), c.b); - lowp float x = max(max(c.r, c.g), c.b); - - if (n < 0.0) { - c.r = l + ((c.r - l) * l) / (l - n); - c.g = l + ((c.g - l) * l) / (l - n); - c.b = l + ((c.b - l) * l) / (l - n); - } - if (x > 1.0) { - c.r = l + ((c.r - l) * (1.0 - l)) / (x - l); - c.g = l + ((c.g - l) * (1.0 - l)) / (x - l); - c.b = l + ((c.b - l) * (1.0 - l)) / (x - l); - } - - return c; - } - - lowp vec3 setlum(lowp vec3 c, highp float l) { - highp float d = l - lum(c); - c = c + vec3(d); - return clipcolor(c); - } - - highp float sat(lowp vec3 c) { - lowp float n = min(min(c.r, c.g), c.b); - lowp float x = max(max(c.r, c.g), c.b); - return x - n; - } - - lowp float mid(lowp float cmin, lowp float cmid, lowp float cmax, highp float s) { - return ((cmid - cmin) * s) / (cmax - cmin); - } - - lowp vec3 setsat(lowp vec3 c, highp float s) { - if (c.r > c.g) { - if (c.r > c.b) { - if (c.g > c.b) { - /* g is mid, b is min */ - c.g = mid(c.b, c.g, c.r, s); - c.b = 0.0; - } else { - /* b is mid, g is min */ - c.b = mid(c.g, c.b, c.r, s); - c.g = 0.0; - } - c.r = s; - } else { - /* b is max, r is mid, g is min */ - c.r = mid(c.g, c.r, c.b, s); - c.b = s; - c.r = 0.0; - } - } else if (c.r > c.b) { - /* g is max, r is mid, b is min */ - c.r = mid(c.b, c.r, c.g, s); - c.g = s; - c.b = 0.0; - } else if (c.g > c.b) { - /* g is max, b is mid, r is min */ - c.b = mid(c.r, c.b, c.g, s); - c.g = s; - c.r = 0.0; - } else if (c.b > c.g) { - /* b is max, g is mid, r is min */ - c.g = mid(c.r, c.g, c.b, s); - c.b = s; - c.r = 0.0; - } else { - c = vec3(0.0); - } - return c; - } - - void main() - { - highp vec4 baseColor = texture2D(inputImageTexture, textureCoordinate); - highp vec4 overlayColor = texture2D(inputImageTexture2, textureCoordinate2); - - gl_FragColor = vec4(baseColor.rgb * (1.0 - overlayColor.a) + setlum(setsat(baseColor.rgb, sat(overlayColor.rgb)), lum(baseColor.rgb)) * overlayColor.a, baseColor.a); - } -); -#else -NSString *const kGPUImageSaturationBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - float lum(vec3 c) { - return dot(c, vec3(0.3, 0.59, 0.11)); - } - - vec3 clipcolor(vec3 c) { - float l = lum(c); - float n = min(min(c.r, c.g), c.b); - float x = max(max(c.r, c.g), c.b); - - if (n < 0.0) { - c.r = l + ((c.r - l) * l) / (l - n); - c.g = l + ((c.g - l) * l) / (l - n); - c.b = l + ((c.b - l) * l) / (l - n); - } - if (x > 1.0) { - c.r = l + ((c.r - l) * (1.0 - l)) / (x - l); - c.g = l + ((c.g - l) * (1.0 - l)) / (x - l); - c.b = l + ((c.b - l) * (1.0 - l)) / (x - l); - } - - return c; - } - - vec3 setlum(vec3 c, float l) { - float d = l - lum(c); - c = c + vec3(d); - return clipcolor(c); - } - - float sat(vec3 c) { - float n = min(min(c.r, c.g), c.b); - float x = max(max(c.r, c.g), c.b); - return x - n; - } - - float mid(float cmin, float cmid, float cmax, float s) { - return ((cmid - cmin) * s) / (cmax - cmin); - } - - vec3 setsat(vec3 c, float s) { - if (c.r > c.g) { - if (c.r > c.b) { - if (c.g > c.b) { - /* g is mid, b is min */ - c.g = mid(c.b, c.g, c.r, s); - c.b = 0.0; - } else { - /* b is mid, g is min */ - c.b = mid(c.g, c.b, c.r, s); - c.g = 0.0; - } - c.r = s; - } else { - /* b is max, r is mid, g is min */ - c.r = mid(c.g, c.r, c.b, s); - c.b = s; - c.r = 0.0; - } - } else if (c.r > c.b) { - /* g is max, r is mid, b is min */ - c.r = mid(c.b, c.r, c.g, s); - c.g = s; - c.b = 0.0; - } else if (c.g > c.b) { - /* g is max, b is mid, r is min */ - c.b = mid(c.r, c.b, c.g, s); - c.g = s; - c.r = 0.0; - } else if (c.b > c.g) { - /* b is max, g is mid, r is min */ - c.g = mid(c.r, c.g, c.b, s); - c.b = s; - c.r = 0.0; - } else { - c = vec3(0.0); - } - return c; - } - - void main() - { - vec4 baseColor = texture2D(inputImageTexture, textureCoordinate); - vec4 overlayColor = texture2D(inputImageTexture2, textureCoordinate2); - - gl_FragColor = vec4(baseColor.rgb * (1.0 - overlayColor.a) + setlum(setsat(baseColor.rgb, sat(overlayColor.rgb)), lum(baseColor.rgb)) * overlayColor.a, baseColor.a); - } -); -#endif - - -@implementation GPUImageSaturationBlendFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageSaturationBlendFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSaturationFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSaturationFilter.h deleted file mode 100755 index 1c6ff5bd..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSaturationFilter.h +++ /dev/null @@ -1,14 +0,0 @@ -#import "GPUImageFilter.h" - -/** Adjusts the saturation of an image - */ -@interface GPUImageSaturationFilter : GPUImageFilter -{ - GLint saturationUniform; -} - -/** Saturation ranges from 0.0 (fully desaturated) to 2.0 (max saturation), with 1.0 as the normal level - */ -@property(readwrite, nonatomic) CGFloat saturation; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSaturationFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSaturationFilter.m deleted file mode 100755 index fc373d4a..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSaturationFilter.m +++ /dev/null @@ -1,78 +0,0 @@ -#import "GPUImageSaturationFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageSaturationFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform lowp float saturation; - - // Values from "Graphics Shaders: Theory and Practice" by Bailey and Cunningham - const mediump vec3 luminanceWeighting = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - lowp float luminance = dot(textureColor.rgb, luminanceWeighting); - lowp vec3 greyScaleColor = vec3(luminance); - - gl_FragColor = vec4(mix(greyScaleColor, textureColor.rgb, saturation), textureColor.w); - - } -); -#else -NSString *const kGPUImageSaturationFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float saturation; - - // Values from "Graphics Shaders: Theory and Practice" by Bailey and Cunningham - const vec3 luminanceWeighting = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - float luminance = dot(textureColor.rgb, luminanceWeighting); - vec3 greyScaleColor = vec3(luminance); - - gl_FragColor = vec4(mix(greyScaleColor, textureColor.rgb, saturation), textureColor.w); - - } - ); -#endif - -@implementation GPUImageSaturationFilter - -@synthesize saturation = _saturation; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageSaturationFragmentShaderString])) - { - return nil; - } - - saturationUniform = [filterProgram uniformIndex:@"saturation"]; - self.saturation = 1.0; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setSaturation:(CGFloat)newValue; -{ - _saturation = newValue; - - [self setFloat:_saturation forUniform:saturationUniform program:filterProgram]; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageScreenBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageScreenBlendFilter.h deleted file mode 100755 index 2df3abf3..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageScreenBlendFilter.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageScreenBlendFilter : GPUImageTwoInputFilter -{ -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageScreenBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageScreenBlendFilter.m deleted file mode 100755 index d871e7db..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageScreenBlendFilter.m +++ /dev/null @@ -1,52 +0,0 @@ -#import "GPUImageScreenBlendFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageScreenBlendFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - mediump vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - mediump vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2); - mediump vec4 whiteColor = vec4(1.0); - gl_FragColor = whiteColor - ((whiteColor - textureColor2) * (whiteColor - textureColor)); - } -); -#else -NSString *const kGPUImageScreenBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2); - vec4 whiteColor = vec4(1.0); - gl_FragColor = whiteColor - ((whiteColor - textureColor2) * (whiteColor - textureColor)); - } -); -#endif - -@implementation GPUImageScreenBlendFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageScreenBlendFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSepiaFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSepiaFilter.h deleted file mode 100755 index a45164fe..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSepiaFilter.h +++ /dev/null @@ -1,6 +0,0 @@ -#import "GPUImageColorMatrixFilter.h" - -/// Simple sepia tone filter -@interface GPUImageSepiaFilter : GPUImageColorMatrixFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSepiaFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSepiaFilter.m deleted file mode 100755 index 71668d63..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSepiaFilter.m +++ /dev/null @@ -1,24 +0,0 @@ -#import "GPUImageSepiaFilter.h" - -@implementation GPUImageSepiaFilter - -- (id)init; -{ - if (!(self = [super init])) - { - return nil; - } - - self.intensity = 1.0; - self.colorMatrix = (GPUMatrix4x4){ - {0.3588, 0.7044, 0.1368, 0.0}, - {0.2990, 0.5870, 0.1140, 0.0}, - {0.2392, 0.4696, 0.0912 ,0.0}, - {0,0,0,1.0}, - }; - - return self; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSharpenFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSharpenFilter.h deleted file mode 100755 index 739df503..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSharpenFilter.h +++ /dev/null @@ -1,12 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageSharpenFilter : GPUImageFilter -{ - GLint sharpnessUniform; - GLint imageWidthFactorUniform, imageHeightFactorUniform; -} - -// Sharpness ranges from -4.0 to 4.0, with 0.0 as the normal level -@property(readwrite, nonatomic) CGFloat sharpness; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSharpenFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSharpenFilter.m deleted file mode 100755 index 6d7367a9..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSharpenFilter.m +++ /dev/null @@ -1,147 +0,0 @@ -#import "GPUImageSharpenFilter.h" - -NSString *const kGPUImageSharpenVertexShaderString = SHADER_STRING -( - attribute vec4 position; - attribute vec4 inputTextureCoordinate; - - uniform float imageWidthFactor; - uniform float imageHeightFactor; - uniform float sharpness; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - varying vec2 topTextureCoordinate; - varying vec2 bottomTextureCoordinate; - - varying float centerMultiplier; - varying float edgeMultiplier; - - void main() - { - gl_Position = position; - - vec2 widthStep = vec2(imageWidthFactor, 0.0); - vec2 heightStep = vec2(0.0, imageHeightFactor); - - textureCoordinate = inputTextureCoordinate.xy; - leftTextureCoordinate = inputTextureCoordinate.xy - widthStep; - rightTextureCoordinate = inputTextureCoordinate.xy + widthStep; - topTextureCoordinate = inputTextureCoordinate.xy + heightStep; - bottomTextureCoordinate = inputTextureCoordinate.xy - heightStep; - - centerMultiplier = 1.0 + 4.0 * sharpness; - edgeMultiplier = sharpness; - } -); - - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageSharpenFragmentShaderString = SHADER_STRING -( - precision highp float; - - varying highp vec2 textureCoordinate; - varying highp vec2 leftTextureCoordinate; - varying highp vec2 rightTextureCoordinate; - varying highp vec2 topTextureCoordinate; - varying highp vec2 bottomTextureCoordinate; - - varying highp float centerMultiplier; - varying highp float edgeMultiplier; - - uniform sampler2D inputImageTexture; - - void main() - { - mediump vec3 textureColor = texture2D(inputImageTexture, textureCoordinate).rgb; - mediump vec3 leftTextureColor = texture2D(inputImageTexture, leftTextureCoordinate).rgb; - mediump vec3 rightTextureColor = texture2D(inputImageTexture, rightTextureCoordinate).rgb; - mediump vec3 topTextureColor = texture2D(inputImageTexture, topTextureCoordinate).rgb; - mediump vec3 bottomTextureColor = texture2D(inputImageTexture, bottomTextureCoordinate).rgb; - - gl_FragColor = vec4((textureColor * centerMultiplier - (leftTextureColor * edgeMultiplier + rightTextureColor * edgeMultiplier + topTextureColor * edgeMultiplier + bottomTextureColor * edgeMultiplier)), texture2D(inputImageTexture, bottomTextureCoordinate).w); - } -); -#else -NSString *const kGPUImageSharpenFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - varying vec2 topTextureCoordinate; - varying vec2 bottomTextureCoordinate; - - varying float centerMultiplier; - varying float edgeMultiplier; - - uniform sampler2D inputImageTexture; - - void main() - { - vec3 textureColor = texture2D(inputImageTexture, textureCoordinate).rgb; - vec3 leftTextureColor = texture2D(inputImageTexture, leftTextureCoordinate).rgb; - vec3 rightTextureColor = texture2D(inputImageTexture, rightTextureCoordinate).rgb; - vec3 topTextureColor = texture2D(inputImageTexture, topTextureCoordinate).rgb; - vec3 bottomTextureColor = texture2D(inputImageTexture, bottomTextureCoordinate).rgb; - - gl_FragColor = vec4((textureColor * centerMultiplier - (leftTextureColor * edgeMultiplier + rightTextureColor * edgeMultiplier + topTextureColor * edgeMultiplier + bottomTextureColor * edgeMultiplier)), texture2D(inputImageTexture, bottomTextureCoordinate).w); - } -); -#endif - - -@implementation GPUImageSharpenFilter - -@synthesize sharpness = _sharpness; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithVertexShaderFromString:kGPUImageSharpenVertexShaderString fragmentShaderFromString:kGPUImageSharpenFragmentShaderString])) - { - return nil; - } - - sharpnessUniform = [filterProgram uniformIndex:@"sharpness"]; - self.sharpness = 0.0; - - imageWidthFactorUniform = [filterProgram uniformIndex:@"imageWidthFactor"]; - imageHeightFactorUniform = [filterProgram uniformIndex:@"imageHeightFactor"]; - - return self; -} - -- (void)setupFilterForSize:(CGSize)filterFrameSize; -{ - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext setActiveShaderProgram:filterProgram]; - - if (GPUImageRotationSwapsWidthAndHeight(inputRotation)) - { - glUniform1f(imageWidthFactorUniform, 1.0 / filterFrameSize.height); - glUniform1f(imageHeightFactorUniform, 1.0 / filterFrameSize.width); - } - else - { - glUniform1f(imageWidthFactorUniform, 1.0 / filterFrameSize.width); - glUniform1f(imageHeightFactorUniform, 1.0 / filterFrameSize.height); - } - }); -} - -#pragma mark - -#pragma mark Accessors - -- (void)setSharpness:(CGFloat)newValue; -{ - _sharpness = newValue; - - [self setFloat:_sharpness forUniform:sharpnessUniform program:filterProgram]; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageShiTomasiFeatureDetectionFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageShiTomasiFeatureDetectionFilter.h deleted file mode 100644 index b16ebc01..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageShiTomasiFeatureDetectionFilter.h +++ /dev/null @@ -1,13 +0,0 @@ -#import "GPUImageHarrisCornerDetectionFilter.h" - -/** Shi-Tomasi feature detector - - This is the Shi-Tomasi feature detector, as described in - J. Shi and C. Tomasi. Good features to track. Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition, pages 593-600, June 1994. - */ - -@interface GPUImageShiTomasiFeatureDetectionFilter : GPUImageHarrisCornerDetectionFilter - -// Compared to the Harris corner detector, the default sensitivity value for this detector is set to 1.5 - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageShiTomasiFeatureDetectionFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageShiTomasiFeatureDetectionFilter.m deleted file mode 100644 index e58cbb4f..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageShiTomasiFeatureDetectionFilter.m +++ /dev/null @@ -1,65 +0,0 @@ -#import "GPUImageShiTomasiFeatureDetectionFilter.h" - -@implementation GPUImageShiTomasiFeatureDetectionFilter - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageShiTomasiCornerDetectionFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform lowp float sensitivity; - - void main() - { - mediump vec3 derivativeElements = texture2D(inputImageTexture, textureCoordinate).rgb; - - mediump float derivativeDifference = derivativeElements.x - derivativeElements.y; - mediump float zElement = (derivativeElements.z * 2.0) - 1.0; - - // R = Ix^2 + Iy^2 - sqrt( (Ix^2 - Iy^2)^2 + 4 * Ixy * Ixy) - mediump float cornerness = derivativeElements.x + derivativeElements.y - sqrt(derivativeDifference * derivativeDifference + 4.0 * zElement * zElement); - - gl_FragColor = vec4(vec3(cornerness * sensitivity), 1.0); - } -); -#else -NSString *const kGPUImageShiTomasiCornerDetectionFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float sensitivity; - - void main() - { - vec3 derivativeElements = texture2D(inputImageTexture, textureCoordinate).rgb; - - float derivativeDifference = derivativeElements.x - derivativeElements.y; - float zElement = (derivativeElements.z * 2.0) - 1.0; - - // R = Ix^2 + Iy^2 - sqrt( (Ix^2 - Iy^2)^2 + 4 * Ixy * Ixy) - float cornerness = derivativeElements.x + derivativeElements.y - sqrt(derivativeDifference * derivativeDifference + 4.0 * zElement * zElement); - - gl_FragColor = vec4(vec3(cornerness * sensitivity), 1.0); - } -); -#endif - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [self initWithCornerDetectionFragmentShader:kGPUImageShiTomasiCornerDetectionFragmentShaderString])) - { - return nil; - } - - self.sensitivity = 1.5; - - return self; -} - - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSingleComponentGaussianBlurFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSingleComponentGaussianBlurFilter.h deleted file mode 100644 index 934b1e3a..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSingleComponentGaussianBlurFilter.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "GPUImageGaussianBlurFilter.h" - -// This filter merely performs the standard Gaussian blur on the red color channel (assuming a luminance image) - -@interface GPUImageSingleComponentGaussianBlurFilter : GPUImageGaussianBlurFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSingleComponentGaussianBlurFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSingleComponentGaussianBlurFilter.m deleted file mode 100644 index 4ff0d91d..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSingleComponentGaussianBlurFilter.m +++ /dev/null @@ -1,189 +0,0 @@ -#import "GPUImageSingleComponentGaussianBlurFilter.h" - -@implementation GPUImageSingleComponentGaussianBlurFilter - -+ (NSString *)vertexShaderForOptimizedBlurOfRadius:(NSUInteger)blurRadius sigma:(CGFloat)sigma; -{ - if (blurRadius < 1) - { - return kGPUImageVertexShaderString; - } - - // First, generate the normal Gaussian weights for a given sigma - GLfloat *standardGaussianWeights = calloc(blurRadius + 1, sizeof(GLfloat)); - GLfloat sumOfWeights = 0.0; - for (NSUInteger currentGaussianWeightIndex = 0; currentGaussianWeightIndex < blurRadius + 1; currentGaussianWeightIndex++) - { - standardGaussianWeights[currentGaussianWeightIndex] = (1.0 / sqrt(2.0 * M_PI * pow(sigma, 2.0))) * exp(-pow(currentGaussianWeightIndex, 2.0) / (2.0 * pow(sigma, 2.0))); - - if (currentGaussianWeightIndex == 0) - { - sumOfWeights += standardGaussianWeights[currentGaussianWeightIndex]; - } - else - { - sumOfWeights += 2.0 * standardGaussianWeights[currentGaussianWeightIndex]; - } - } - - // Next, normalize these weights to prevent the clipping of the Gaussian curve at the end of the discrete samples from reducing luminance - for (NSUInteger currentGaussianWeightIndex = 0; currentGaussianWeightIndex < blurRadius + 1; currentGaussianWeightIndex++) - { - standardGaussianWeights[currentGaussianWeightIndex] = standardGaussianWeights[currentGaussianWeightIndex] / sumOfWeights; - } - - // From these weights we calculate the offsets to read interpolated values from - NSUInteger numberOfOptimizedOffsets = MIN(blurRadius / 2 + (blurRadius % 2), 7); - GLfloat *optimizedGaussianOffsets = calloc(numberOfOptimizedOffsets, sizeof(GLfloat)); - - for (NSUInteger currentOptimizedOffset = 0; currentOptimizedOffset < numberOfOptimizedOffsets; currentOptimizedOffset++) - { - GLfloat firstWeight = standardGaussianWeights[currentOptimizedOffset*2 + 1]; - GLfloat secondWeight = standardGaussianWeights[currentOptimizedOffset*2 + 2]; - - GLfloat optimizedWeight = firstWeight + secondWeight; - - optimizedGaussianOffsets[currentOptimizedOffset] = (firstWeight * (currentOptimizedOffset*2 + 1) + secondWeight * (currentOptimizedOffset*2 + 2)) / optimizedWeight; - } - - NSMutableString *shaderString = [[NSMutableString alloc] init]; - // Header - [shaderString appendFormat:@"\ - attribute vec4 position;\n\ - attribute vec4 inputTextureCoordinate;\n\ - \n\ - uniform float texelWidthOffset;\n\ - uniform float texelHeightOffset;\n\ - \n\ - varying vec2 blurCoordinates[%lu];\n\ - \n\ - void main()\n\ - {\n\ - gl_Position = position;\n\ - \n\ - vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset);\n", (unsigned long)(1 + (numberOfOptimizedOffsets * 2))]; - - // Inner offset loop - [shaderString appendString:@"blurCoordinates[0] = inputTextureCoordinate.xy;\n"]; - for (NSUInteger currentOptimizedOffset = 0; currentOptimizedOffset < numberOfOptimizedOffsets; currentOptimizedOffset++) - { - [shaderString appendFormat:@"\ - blurCoordinates[%lu] = inputTextureCoordinate.xy + singleStepOffset * %f;\n\ - blurCoordinates[%lu] = inputTextureCoordinate.xy - singleStepOffset * %f;\n", (unsigned long)((currentOptimizedOffset * 2) + 1), optimizedGaussianOffsets[currentOptimizedOffset], (unsigned long)((currentOptimizedOffset * 2) + 2), optimizedGaussianOffsets[currentOptimizedOffset]]; - } - - // Footer - [shaderString appendString:@"}\n"]; - - free(optimizedGaussianOffsets); - free(standardGaussianWeights); - return shaderString; -} - -+ (NSString *)fragmentShaderForOptimizedBlurOfRadius:(NSUInteger)blurRadius sigma:(CGFloat)sigma; -{ - if (blurRadius < 1) - { - return kGPUImagePassthroughFragmentShaderString; - } - - // First, generate the normal Gaussian weights for a given sigma - GLfloat *standardGaussianWeights = calloc(blurRadius + 1, sizeof(GLfloat)); - GLfloat sumOfWeights = 0.0; - for (NSUInteger currentGaussianWeightIndex = 0; currentGaussianWeightIndex < blurRadius + 1; currentGaussianWeightIndex++) - { - standardGaussianWeights[currentGaussianWeightIndex] = (1.0 / sqrt(2.0 * M_PI * pow(sigma, 2.0))) * exp(-pow(currentGaussianWeightIndex, 2.0) / (2.0 * pow(sigma, 2.0))); - - if (currentGaussianWeightIndex == 0) - { - sumOfWeights += standardGaussianWeights[currentGaussianWeightIndex]; - } - else - { - sumOfWeights += 2.0 * standardGaussianWeights[currentGaussianWeightIndex]; - } - } - - // Next, normalize these weights to prevent the clipping of the Gaussian curve at the end of the discrete samples from reducing luminance - for (NSUInteger currentGaussianWeightIndex = 0; currentGaussianWeightIndex < blurRadius + 1; currentGaussianWeightIndex++) - { - standardGaussianWeights[currentGaussianWeightIndex] = standardGaussianWeights[currentGaussianWeightIndex] / sumOfWeights; - } - - // From these weights we calculate the offsets to read interpolated values from - NSUInteger numberOfOptimizedOffsets = MIN(blurRadius / 2 + (blurRadius % 2), 7); - NSUInteger trueNumberOfOptimizedOffsets = blurRadius / 2 + (blurRadius % 2); - - NSMutableString *shaderString = [[NSMutableString alloc] init]; - - // Header -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - [shaderString appendFormat:@"\ - uniform sampler2D inputImageTexture;\n\ - uniform highp float texelWidthOffset;\n\ - uniform highp float texelHeightOffset;\n\ - \n\ - varying highp vec2 blurCoordinates[%lu];\n\ - \n\ - void main()\n\ - {\n\ - lowp float sum = 0.0;\n", (unsigned long)(1 + (numberOfOptimizedOffsets * 2)) ]; -#else - [shaderString appendFormat:@"\ - uniform sampler2D inputImageTexture;\n\ - uniform float texelWidthOffset;\n\ - uniform float texelHeightOffset;\n\ - \n\ - varying vec2 blurCoordinates[%lu];\n\ - \n\ - void main()\n\ - {\n\ - float sum = 0.0;\n", 1 + (numberOfOptimizedOffsets * 2) ]; -#endif - - // Inner texture loop - [shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[0]).r * %f;\n", standardGaussianWeights[0]]; - - for (NSUInteger currentBlurCoordinateIndex = 0; currentBlurCoordinateIndex < numberOfOptimizedOffsets; currentBlurCoordinateIndex++) - { - GLfloat firstWeight = standardGaussianWeights[currentBlurCoordinateIndex * 2 + 1]; - GLfloat secondWeight = standardGaussianWeights[currentBlurCoordinateIndex * 2 + 2]; - GLfloat optimizedWeight = firstWeight + secondWeight; - - [shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[%lu]).r * %f;\n", (unsigned long)((currentBlurCoordinateIndex * 2) + 1), optimizedWeight]; - [shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[%lu]).r * %f;\n", (unsigned long)((currentBlurCoordinateIndex * 2) + 2), optimizedWeight]; - } - - // If the number of required samples exceeds the amount we can pass in via varyings, we have to do dependent texture reads in the fragment shader - if (trueNumberOfOptimizedOffsets > numberOfOptimizedOffsets) - { -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - [shaderString appendString:@"highp vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset);\n"]; -#else - [shaderString appendString:@"highp vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset);\n"]; -#endif - - for (NSUInteger currentOverlowTextureRead = numberOfOptimizedOffsets; currentOverlowTextureRead < trueNumberOfOptimizedOffsets; currentOverlowTextureRead++) - { - GLfloat firstWeight = standardGaussianWeights[currentOverlowTextureRead * 2 + 1]; - GLfloat secondWeight = standardGaussianWeights[currentOverlowTextureRead * 2 + 2]; - - GLfloat optimizedWeight = firstWeight + secondWeight; - GLfloat optimizedOffset = (firstWeight * (currentOverlowTextureRead * 2 + 1) + secondWeight * (currentOverlowTextureRead * 2 + 2)) / optimizedWeight; - - [shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[0] + singleStepOffset * %f).r * %f;\n", optimizedOffset, optimizedWeight]; - [shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[0] - singleStepOffset * %f).r * %f;\n", optimizedOffset, optimizedWeight]; - } - } - - // Footer - [shaderString appendString:@"\ - gl_FragColor = vec4(sum, sum, sum, 1.0);\n\ - }\n"]; - - free(standardGaussianWeights); - return shaderString; -} - - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSketchFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSketchFilter.h deleted file mode 100755 index 598145ae..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSketchFilter.h +++ /dev/null @@ -1,11 +0,0 @@ -#import "GPUImageSobelEdgeDetectionFilter.h" - -/** Converts video to look like a sketch. - - This is just the Sobel edge detection filter with the colors inverted. - */ -@interface GPUImageSketchFilter : GPUImageSobelEdgeDetectionFilter -{ -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSketchFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSketchFilter.m deleted file mode 100755 index 3cda2203..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSketchFilter.m +++ /dev/null @@ -1,98 +0,0 @@ -#import "GPUImageSketchFilter.h" - -@implementation GPUImageSketchFilter - -// Invert the colorspace for a sketch -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageSketchFragmentShaderString = SHADER_STRING -( - precision mediump float; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform float edgeStrength; - - uniform sampler2D inputImageTexture; - - void main() - { - float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r; - float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r; - float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r; - float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r; - float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r; - float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity; - float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity; - - float mag = 1.0 - (length(vec2(h, v)) * edgeStrength); - - gl_FragColor = vec4(vec3(mag), 1.0); - } -); -#else -NSString *const kGPUImageSketchFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform float edgeStrength; - - uniform sampler2D inputImageTexture; - - void main() - { - float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r; - float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r; - float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r; - float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r; - float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r; - float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity; - float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity; - - float mag = 1.0 - (length(vec2(h, v)) * edgeStrength); - - gl_FragColor = vec4(vec3(mag), 1.0); - } -); -#endif - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [self initWithFragmentShaderFromString:kGPUImageSketchFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSmoothToonFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSmoothToonFilter.h deleted file mode 100755 index f89caac5..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSmoothToonFilter.h +++ /dev/null @@ -1,28 +0,0 @@ -#import "GPUImageFilterGroup.h" - -@class GPUImageGaussianBlurFilter; -@class GPUImageToonFilter; - -/** This uses a similar process as the GPUImageToonFilter, only it precedes the toon effect with a Gaussian blur to smooth out noise. - */ -@interface GPUImageSmoothToonFilter : GPUImageFilterGroup -{ - GPUImageGaussianBlurFilter *blurFilter; - GPUImageToonFilter *toonFilter; -} - -/// The image width and height factors tweak the appearance of the edges. By default, they match the filter size in pixels -@property(readwrite, nonatomic) CGFloat texelWidth; -/// The image width and height factors tweak the appearance of the edges. By default, they match the filter size in pixels -@property(readwrite, nonatomic) CGFloat texelHeight; - -/// The radius of the underlying Gaussian blur. The default is 2.0. -@property (readwrite, nonatomic) CGFloat blurRadiusInPixels; - -/// The threshold at which to apply the edges, default of 0.2 -@property(readwrite, nonatomic) CGFloat threshold; - -/// The levels of quantization for the posterization of colors within the scene, with a default of 10.0 -@property(readwrite, nonatomic) CGFloat quantizationLevels; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSmoothToonFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSmoothToonFilter.m deleted file mode 100755 index 03828f48..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSmoothToonFilter.m +++ /dev/null @@ -1,94 +0,0 @@ -#import "GPUImageSmoothToonFilter.h" -#import "GPUImageGaussianBlurFilter.h" -#import "GPUImageToonFilter.h" - -@implementation GPUImageSmoothToonFilter - -@synthesize threshold; -@synthesize blurRadiusInPixels; -@synthesize quantizationLevels; -@synthesize texelWidth; -@synthesize texelHeight; - -- (id)init; -{ - if (!(self = [super init])) - { - return nil; - } - - // First pass: apply a variable Gaussian blur - blurFilter = [[GPUImageGaussianBlurFilter alloc] init]; - [self addFilter:blurFilter]; - - // Second pass: run the Sobel edge detection on this blurred image, along with a posterization effect - toonFilter = [[GPUImageToonFilter alloc] init]; - [self addFilter:toonFilter]; - - // Texture location 0 needs to be the sharp image for both the blur and the second stage processing - [blurFilter addTarget:toonFilter]; - - self.initialFilters = [NSArray arrayWithObject:blurFilter]; - self.terminalFilter = toonFilter; - - self.blurRadiusInPixels = 2.0; - self.threshold = 0.2; - self.quantizationLevels = 10.0; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setBlurRadiusInPixels:(CGFloat)newValue; -{ - blurFilter.blurRadiusInPixels = newValue; -} - -- (CGFloat)blurRadiusInPixels; -{ - return blurFilter.blurRadiusInPixels; -} - -- (void)setTexelWidth:(CGFloat)newValue; -{ - toonFilter.texelWidth = newValue; -} - -- (CGFloat)texelWidth; -{ - return toonFilter.texelWidth; -} - -- (void)setTexelHeight:(CGFloat)newValue; -{ - toonFilter.texelHeight = newValue; -} - -- (CGFloat)texelHeight; -{ - return toonFilter.texelHeight; -} - -- (void)setThreshold:(CGFloat)newValue; -{ - toonFilter.threshold = newValue; -} - -- (CGFloat)threshold; -{ - return toonFilter.threshold; -} - -- (void)setQuantizationLevels:(CGFloat)newValue; -{ - toonFilter.quantizationLevels = newValue; -} - -- (CGFloat)quantizationLevels; -{ - return toonFilter.quantizationLevels; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSobelEdgeDetectionFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSobelEdgeDetectionFilter.h deleted file mode 100755 index d6b2c13a..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSobelEdgeDetectionFilter.h +++ /dev/null @@ -1,16 +0,0 @@ -#import "GPUImageTwoPassFilter.h" - -@interface GPUImageSobelEdgeDetectionFilter : GPUImageTwoPassFilter -{ - GLint texelWidthUniform, texelHeightUniform, edgeStrengthUniform; - BOOL hasOverriddenImageSizeFactor; -} - -// The texel width and height factors tweak the appearance of the edges. By default, they match the inverse of the filter size in pixels -@property(readwrite, nonatomic) CGFloat texelWidth; -@property(readwrite, nonatomic) CGFloat texelHeight; - -// The filter strength property affects the dynamic range of the filter. High values can make edges more visible, but can lead to saturation. Default of 1.0. -@property(readwrite, nonatomic) CGFloat edgeStrength; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSobelEdgeDetectionFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSobelEdgeDetectionFilter.m deleted file mode 100755 index e193f027..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSobelEdgeDetectionFilter.m +++ /dev/null @@ -1,188 +0,0 @@ -#import "GPUImageSobelEdgeDetectionFilter.h" -#import "GPUImageGrayscaleFilter.h" -#import "GPUImage3x3ConvolutionFilter.h" - -// Code from "Graphics Shaders: Theory and Practice" by M. Bailey and S. Cunningham -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageSobelEdgeDetectionFragmentShaderString = SHADER_STRING -( - precision mediump float; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float edgeStrength; - - void main() - { - float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r; - float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r; - float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r; - float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r; - float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r; - float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity; - float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity; - - float mag = length(vec2(h, v)) * edgeStrength; - - gl_FragColor = vec4(vec3(mag), 1.0); - } -); -#else -NSString *const kGPUImageSobelEdgeDetectionFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float edgeStrength; - - void main() - { - float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r; - float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r; - float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r; - float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r; - float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r; - float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity; - float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity; - - float mag = length(vec2(h, v)) * edgeStrength; - - gl_FragColor = vec4(vec3(mag), 1.0); - } -); -#endif - -@implementation GPUImageSobelEdgeDetectionFilter - -@synthesize texelWidth = _texelWidth; -@synthesize texelHeight = _texelHeight; -@synthesize edgeStrength = _edgeStrength; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [self initWithFragmentShaderFromString:kGPUImageSobelEdgeDetectionFragmentShaderString])) - { - return nil; - } - - return self; -} - -- (id)initWithFragmentShaderFromString:(NSString *)fragmentShaderString; -{ - // Do a luminance pass first to reduce the calculations performed at each fragment in the edge detection phase - - if (!(self = [super initWithFirstStageVertexShaderFromString:kGPUImageVertexShaderString firstStageFragmentShaderFromString:kGPUImageLuminanceFragmentShaderString secondStageVertexShaderFromString:kGPUImageNearbyTexelSamplingVertexShaderString secondStageFragmentShaderFromString:fragmentShaderString])) - { - return nil; - } - - hasOverriddenImageSizeFactor = NO; - - texelWidthUniform = [secondFilterProgram uniformIndex:@"texelWidth"]; - texelHeightUniform = [secondFilterProgram uniformIndex:@"texelHeight"]; - edgeStrengthUniform = [secondFilterProgram uniformIndex:@"edgeStrength"]; - - self.edgeStrength = 1.0; - return self; -} - -- (void)setupFilterForSize:(CGSize)filterFrameSize; -{ - if (!hasOverriddenImageSizeFactor) - { - _texelWidth = 1.0 / filterFrameSize.width; - _texelHeight = 1.0 / filterFrameSize.height; - - runSynchronouslyOnVideoProcessingQueue(^{ - GLProgram *previousProgram = [GPUImageContext sharedImageProcessingContext].currentShaderProgram; - [GPUImageContext setActiveShaderProgram:secondFilterProgram]; - glUniform1f(texelWidthUniform, _texelWidth); - glUniform1f(texelHeightUniform, _texelHeight); - [GPUImageContext setActiveShaderProgram:previousProgram]; - }); - } -} - -- (void)setUniformsForProgramAtIndex:(NSUInteger)programIndex; -{ - [super setUniformsForProgramAtIndex:programIndex]; - - if (programIndex == 1) - { - glUniform1f(texelWidthUniform, _texelWidth); - glUniform1f(texelHeightUniform, _texelHeight); - } -} - -- (BOOL)wantsMonochromeInput; -{ -// return YES; - return NO; -} - -- (BOOL)providesMonochromeOutput; -{ -// return YES; - return NO; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setTexelWidth:(CGFloat)newValue; -{ - hasOverriddenImageSizeFactor = YES; - _texelWidth = newValue; - - [self setFloat:_texelWidth forUniform:texelWidthUniform program:secondFilterProgram]; -} - -- (void)setTexelHeight:(CGFloat)newValue; -{ - hasOverriddenImageSizeFactor = YES; - _texelHeight = newValue; - - [self setFloat:_texelHeight forUniform:texelHeightUniform program:secondFilterProgram]; -} - -- (void)setEdgeStrength:(CGFloat)newValue; -{ - _edgeStrength = newValue; - - [self setFloat:_edgeStrength forUniform:edgeStrengthUniform program:secondFilterProgram]; -} - - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSoftEleganceFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSoftEleganceFilter.h deleted file mode 100755 index 596e1567..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSoftEleganceFilter.h +++ /dev/null @@ -1,19 +0,0 @@ -#import "GPUImageFilterGroup.h" - -@class GPUImagePicture; - -/** A photo filter based on Soft Elegance Photoshop action - http://h-d-stock.deviantart.com/art/H-D-A-soft-elegance-70107603 - */ - -// Note: If you want to use this effect you have to add -// lookup_soft_elegance_1.png and lookup_soft_elegance_2.png -// from Resources folder to your application bundle. - -@interface GPUImageSoftEleganceFilter : GPUImageFilterGroup -{ - GPUImagePicture *lookupImageSource1; - GPUImagePicture *lookupImageSource2; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSoftEleganceFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSoftEleganceFilter.m deleted file mode 100755 index e1d4e02d..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSoftEleganceFilter.m +++ /dev/null @@ -1,62 +0,0 @@ -#import "GPUImageSoftEleganceFilter.h" -#import "GPUImagePicture.h" -#import "GPUImageLookupFilter.h" -#import "GPUImageGaussianBlurFilter.h" -#import "GPUImageAlphaBlendFilter.h" - -@implementation GPUImageSoftEleganceFilter - -- (id)init; -{ - if (!(self = [super init])) - { - return nil; - } - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - UIImage *image1 = [UIImage imageNamed:@"lookup_soft_elegance_1.png"]; - UIImage *image2 = [UIImage imageNamed:@"lookup_soft_elegance_2.png"]; -#else - NSImage *image1 = [NSImage imageNamed:@"lookup_soft_elegance_1.png"]; - NSImage *image2 = [NSImage imageNamed:@"lookup_soft_elegance_2.png"]; -#endif - - NSAssert(image1 && image2, - @"To use GPUImageSoftEleganceFilter you need to add lookup_soft_elegance_1.png and lookup_soft_elegance_2.png from GPUImage/framework/Resources to your application bundle."); - - lookupImageSource1 = [[GPUImagePicture alloc] initWithImage:image1]; - GPUImageLookupFilter *lookupFilter1 = [[GPUImageLookupFilter alloc] init]; - [self addFilter:lookupFilter1]; - - [lookupImageSource1 addTarget:lookupFilter1 atTextureLocation:1]; - [lookupImageSource1 processImage]; - - GPUImageGaussianBlurFilter *gaussianBlur = [[GPUImageGaussianBlurFilter alloc] init]; - gaussianBlur.blurRadiusInPixels = 10.0; - [lookupFilter1 addTarget:gaussianBlur]; - [self addFilter:gaussianBlur]; - - GPUImageAlphaBlendFilter *alphaBlend = [[GPUImageAlphaBlendFilter alloc] init]; - alphaBlend.mix = 0.14; - [lookupFilter1 addTarget:alphaBlend]; - [gaussianBlur addTarget:alphaBlend]; - [self addFilter:alphaBlend]; - - lookupImageSource2 = [[GPUImagePicture alloc] initWithImage:image2]; - - GPUImageLookupFilter *lookupFilter2 = [[GPUImageLookupFilter alloc] init]; - [alphaBlend addTarget:lookupFilter2]; - [lookupImageSource2 addTarget:lookupFilter2]; - [lookupImageSource2 processImage]; - [self addFilter:lookupFilter2]; - - self.initialFilters = [NSArray arrayWithObjects:lookupFilter1, nil]; - self.terminalFilter = lookupFilter2; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSoftLightBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSoftLightBlendFilter.h deleted file mode 100755 index 13fc877c..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSoftLightBlendFilter.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageSoftLightBlendFilter : GPUImageTwoInputFilter -{ -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSoftLightBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSoftLightBlendFilter.m deleted file mode 100755 index 368bce0a..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSoftLightBlendFilter.m +++ /dev/null @@ -1,54 +0,0 @@ -#import "GPUImageSoftLightBlendFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageSoftLightBlendFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - mediump vec4 base = texture2D(inputImageTexture, textureCoordinate); - mediump vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2); - - lowp float alphaDivisor = base.a + step(base.a, 0.0); // Protect against a divide-by-zero blacking out things in the output - gl_FragColor = base * (overlay.a * (base / alphaDivisor) + (2.0 * overlay * (1.0 - (base / alphaDivisor)))) + overlay * (1.0 - base.a) + base * (1.0 - overlay.a); - } -); -#else -NSString *const kGPUImageSoftLightBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 base = texture2D(inputImageTexture, textureCoordinate); - vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2); - - float alphaDivisor = base.a + step(base.a, 0.0); // Protect against a divide-by-zero blacking out things in the output - gl_FragColor = base * (overlay.a * (base / alphaDivisor) + (2.0 * overlay * (1.0 - (base / alphaDivisor)))) + overlay * (1.0 - base.a) + base * (1.0 - overlay.a); - } -); -#endif - -@implementation GPUImageSoftLightBlendFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageSoftLightBlendFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSolidColorGenerator.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSolidColorGenerator.h deleted file mode 100644 index 58b1383e..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSolidColorGenerator.h +++ /dev/null @@ -1,19 +0,0 @@ -#import "GPUImageFilter.h" - -// This outputs an image with a constant color. You need to use -forceProcessingAtSize: in order to set the output image -// dimensions, or this won't work correctly - - -@interface GPUImageSolidColorGenerator : GPUImageFilter -{ - GLint colorUniform; - GLint useExistingAlphaUniform; -} - -// This color dictates what the output image will be filled with -@property(readwrite, nonatomic) GPUVector4 color; -@property(readwrite, nonatomic, assign) BOOL useExistingAlpha; // whether to use the alpha of the existing image or not, default is NO - -- (void)setColorRed:(CGFloat)redComponent green:(CGFloat)greenComponent blue:(CGFloat)blueComponent alpha:(CGFloat)alphaComponent; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSolidColorGenerator.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSolidColorGenerator.m deleted file mode 100644 index 9b555ce0..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSolidColorGenerator.m +++ /dev/null @@ -1,123 +0,0 @@ -#import "GPUImageSolidColorGenerator.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUSolidColorFragmentShaderString = SHADER_STRING -( - precision lowp float; - - varying highp vec2 textureCoordinate; - uniform sampler2D inputImageTexture; - uniform vec4 color; - uniform float useExistingAlpha; - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - gl_FragColor = vec4(color.rgb, max(textureColor.a, 1.0 - useExistingAlpha)); - } - ); -#else -NSString *const kGPUSolidColorFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - uniform sampler2D inputImageTexture; - uniform vec4 color; - uniform float useExistingAlpha; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - gl_FragColor = vec4(color.rgb, max(textureColor.a, 1.0 - useExistingAlpha)); - } - ); -#endif - -@implementation GPUImageSolidColorGenerator - -@synthesize color = _color; - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUSolidColorFragmentShaderString])) - { - return nil; - } - - colorUniform = [filterProgram uniformIndex:@"color"]; - useExistingAlphaUniform = [filterProgram uniformIndex:@"useExistingAlpha"]; - - _color = (GPUVector4){0.0f, 0.0f, 0.5f, 1.0f}; - self.useExistingAlpha = NO; - - return self; -} - -- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates; -{ - if (self.preventRendering) - { - return; - } - - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext setActiveShaderProgram:filterProgram]; - - outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:[self sizeOfFBO] textureOptions:self.outputTextureOptions onlyTexture:NO]; - [outputFramebuffer activateFramebuffer]; - - glClearColor(_color.one, _color.two, _color.three, _color.four); - glClear(GL_COLOR_BUFFER_BIT); - }); -} - - -#pragma mark - -#pragma mark Accessors - -- (void)forceProcessingAtSize:(CGSize)frameSize; -{ - [super forceProcessingAtSize:frameSize]; - - if (!CGSizeEqualToSize(inputTextureSize, CGSizeZero)) - { - [self newFrameReadyAtTime:kCMTimeIndefinite atIndex:0]; - } -} - -- (void)addTarget:(id)newTarget atTextureLocation:(NSInteger)textureLocation; -{ - [super addTarget:newTarget atTextureLocation:textureLocation]; - - if (!CGSizeEqualToSize(inputTextureSize, CGSizeZero)) - { - [newTarget setInputSize:inputTextureSize atIndex:textureLocation]; - [newTarget newFrameReadyAtTime:kCMTimeIndefinite atIndex:textureLocation]; - } -} - -- (void)setColor:(GPUVector4)newValue; -{ - [self setColorRed:newValue.one green:newValue.two blue:newValue.three alpha:newValue.four]; -} - -- (void)setColorRed:(CGFloat)redComponent green:(CGFloat)greenComponent blue:(CGFloat)blueComponent alpha:(CGFloat)alphaComponent; -{ - _color.one = (GLfloat)redComponent; - _color.two = (GLfloat)greenComponent; - _color.three = (GLfloat)blueComponent; - _color.four = (GLfloat)alphaComponent; - -// [self setVec4:_color forUniform:colorUniform program:filterProgram]; - runAsynchronouslyOnVideoProcessingQueue(^{ - [self newFrameReadyAtTime:kCMTimeIndefinite atIndex:0]; - }); -} - -- (void)setUseExistingAlpha:(BOOL)useExistingAlpha; -{ - _useExistingAlpha = useExistingAlpha; - - [self setInteger:(useExistingAlpha ? 1 : 0) forUniform:useExistingAlphaUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSourceOverBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSourceOverBlendFilter.h deleted file mode 100644 index 29e30635..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSourceOverBlendFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageSourceOverBlendFilter : GPUImageTwoInputFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSourceOverBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSourceOverBlendFilter.m deleted file mode 100644 index 432adc4b..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSourceOverBlendFilter.m +++ /dev/null @@ -1,51 +0,0 @@ -#import "GPUImageSourceOverBlendFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageSourceOverBlendFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - lowp vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate); - - gl_FragColor = mix(textureColor, textureColor2, textureColor2.a); - } -); -#else -NSString *const kGPUImageSourceOverBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate); - - gl_FragColor = mix(textureColor, textureColor2, textureColor2.a); - } - ); -#endif - -@implementation GPUImageSourceOverBlendFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageSourceOverBlendFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSphereRefractionFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSphereRefractionFilter.h deleted file mode 100644 index cbbd2afa..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSphereRefractionFilter.h +++ /dev/null @@ -1,15 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageSphereRefractionFilter : GPUImageFilter -{ - GLint radiusUniform, centerUniform, aspectRatioUniform, refractiveIndexUniform; -} - -/// The center about which to apply the distortion, with a default of (0.5, 0.5) -@property(readwrite, nonatomic) CGPoint center; -/// The radius of the distortion, ranging from 0.0 to 1.0, with a default of 0.25 -@property(readwrite, nonatomic) CGFloat radius; -/// The index of refraction for the sphere, with a default of 0.71 -@property(readwrite, nonatomic) CGFloat refractiveIndex; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSphereRefractionFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSphereRefractionFilter.m deleted file mode 100644 index b0f54042..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSphereRefractionFilter.m +++ /dev/null @@ -1,179 +0,0 @@ -#import "GPUImageSphereRefractionFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageSphereRefractionFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform highp vec2 center; - uniform highp float radius; - uniform highp float aspectRatio; - uniform highp float refractiveIndex; - - void main() - { - highp vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); - highp float distanceFromCenter = distance(center, textureCoordinateToUse); - lowp float checkForPresenceWithinSphere = step(distanceFromCenter, radius); - - distanceFromCenter = distanceFromCenter / radius; - - highp float normalizedDepth = radius * sqrt(1.0 - distanceFromCenter * distanceFromCenter); - highp vec3 sphereNormal = normalize(vec3(textureCoordinateToUse - center, normalizedDepth)); - - highp vec3 refractedVector = refract(vec3(0.0, 0.0, -1.0), sphereNormal, refractiveIndex); - - gl_FragColor = texture2D(inputImageTexture, (refractedVector.xy + 1.0) * 0.5) * checkForPresenceWithinSphere; - } -); -#else -NSString *const kGPUImageSphereRefractionFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform vec2 center; - uniform float radius; - uniform float aspectRatio; - uniform float refractiveIndex; - - void main() - { - vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); - float distanceFromCenter = distance(center, textureCoordinateToUse); - float checkForPresenceWithinSphere = step(distanceFromCenter, radius); - - distanceFromCenter = distanceFromCenter / radius; - - float normalizedDepth = radius * sqrt(1.0 - distanceFromCenter * distanceFromCenter); - vec3 sphereNormal = normalize(vec3(textureCoordinateToUse - center, normalizedDepth)); - - vec3 refractedVector = refract(vec3(0.0, 0.0, -1.0), sphereNormal, refractiveIndex); - - gl_FragColor = texture2D(inputImageTexture, (refractedVector.xy + 1.0) * 0.5) * checkForPresenceWithinSphere; - } -); -#endif - -@interface GPUImageSphereRefractionFilter () - -- (void)adjustAspectRatio; - -@property (readwrite, nonatomic) CGFloat aspectRatio; - -@end - - -@implementation GPUImageSphereRefractionFilter - -@synthesize center = _center; -@synthesize radius = _radius; -@synthesize aspectRatio = _aspectRatio; -@synthesize refractiveIndex = _refractiveIndex; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [self initWithFragmentShaderFromString:kGPUImageSphereRefractionFragmentShaderString])) - { - return nil; - } - - return self; -} - -- (id)initWithFragmentShaderFromString:(NSString *)fragmentShaderString; -{ - if (!(self = [super initWithFragmentShaderFromString:fragmentShaderString])) - { - return nil; - } - - radiusUniform = [filterProgram uniformIndex:@"radius"]; - aspectRatioUniform = [filterProgram uniformIndex:@"aspectRatio"]; - centerUniform = [filterProgram uniformIndex:@"center"]; - refractiveIndexUniform = [filterProgram uniformIndex:@"refractiveIndex"]; - - self.radius = 0.25; - self.center = CGPointMake(0.5, 0.5); - self.refractiveIndex = 0.71; - - [self setBackgroundColorRed:0.0 green:0.0 blue:0.0 alpha:0.0]; - - return self; -} - -- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex; -{ - CGSize oldInputSize = inputTextureSize; - [super setInputSize:newSize atIndex:textureIndex]; - - if (!CGSizeEqualToSize(oldInputSize, inputTextureSize) && (!CGSizeEqualToSize(newSize, CGSizeZero)) ) - { - [self adjustAspectRatio]; - } -} - -#pragma mark - -#pragma mark Accessors - -- (void)adjustAspectRatio; -{ - if (GPUImageRotationSwapsWidthAndHeight(inputRotation)) - { - [self setAspectRatio:(inputTextureSize.width / inputTextureSize.height)]; - } - else - { - [self setAspectRatio:(inputTextureSize.height / inputTextureSize.width)]; - } -} - -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -{ - [super setInputRotation:newInputRotation atIndex:textureIndex]; - [self setCenter:self.center]; - [self adjustAspectRatio]; -} - -- (void)forceProcessingAtSize:(CGSize)frameSize; -{ - [super forceProcessingAtSize:frameSize]; - [self adjustAspectRatio]; -} - -- (void)setRadius:(CGFloat)newValue; -{ - _radius = newValue; - - [self setFloat:_radius forUniform:radiusUniform program:filterProgram]; -} - -- (void)setCenter:(CGPoint)newValue; -{ - _center = newValue; - - CGPoint rotatedPoint = [self rotatedPoint:_center forRotation:inputRotation]; - [self setPoint:rotatedPoint forUniform:centerUniform program:filterProgram]; -} - -- (void)setAspectRatio:(CGFloat)newValue; -{ - _aspectRatio = newValue; - - [self setFloat:_aspectRatio forUniform:aspectRatioUniform program:filterProgram]; -} - -- (void)setRefractiveIndex:(CGFloat)newValue; -{ - _refractiveIndex = newValue; - - [self setFloat:_refractiveIndex forUniform:refractiveIndexUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageStillCamera.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageStillCamera.h deleted file mode 100755 index e4db59b2..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageStillCamera.h +++ /dev/null @@ -1,24 +0,0 @@ -#import "GPUImageVideoCamera.h" - -void stillImageDataReleaseCallback(void *releaseRefCon, const void *baseAddress); -void GPUImageCreateResizedSampleBuffer(CVPixelBufferRef cameraFrame, CGSize finalSize, CMSampleBufferRef *sampleBuffer); - -@interface GPUImageStillCamera : GPUImageVideoCamera - -/** The JPEG compression quality to use when capturing a photo as a JPEG. - */ -@property CGFloat jpegCompressionQuality; - -// Only reliably set inside the context of the completion handler of one of the capture methods -@property (readonly) NSDictionary *currentCaptureMetadata; - -// Photography controls -- (void)capturePhotoAsSampleBufferWithCompletionHandler:(void (^)(CMSampleBufferRef imageSampleBuffer, NSError *error))block; -- (void)capturePhotoAsImageProcessedUpToFilter:(GPUImageOutput *)finalFilterInChain withCompletionHandler:(void (^)(UIImage *processedImage, NSError *error))block; -- (void)capturePhotoAsImageProcessedUpToFilter:(GPUImageOutput *)finalFilterInChain withOrientation:(UIImageOrientation)orientation withCompletionHandler:(void (^)(UIImage *processedImage, NSError *error))block; -- (void)capturePhotoAsJPEGProcessedUpToFilter:(GPUImageOutput *)finalFilterInChain withCompletionHandler:(void (^)(NSData *processedJPEG, NSError *error))block; -- (void)capturePhotoAsJPEGProcessedUpToFilter:(GPUImageOutput *)finalFilterInChain withOrientation:(UIImageOrientation)orientation withCompletionHandler:(void (^)(NSData *processedJPEG, NSError *error))block; -- (void)capturePhotoAsPNGProcessedUpToFilter:(GPUImageOutput *)finalFilterInChain withCompletionHandler:(void (^)(NSData *processedPNG, NSError *error))block; -- (void)capturePhotoAsPNGProcessedUpToFilter:(GPUImageOutput *)finalFilterInChain withOrientation:(UIImageOrientation)orientation withCompletionHandler:(void (^)(NSData *processedPNG, NSError *error))block; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageStillCamera.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageStillCamera.m deleted file mode 100755 index 447f79f6..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageStillCamera.m +++ /dev/null @@ -1,338 +0,0 @@ -// 2448x3264 pixel image = 31,961,088 bytes for uncompressed RGBA - -#import "GPUImageStillCamera.h" - -void stillImageDataReleaseCallback(void *releaseRefCon, const void *baseAddress) -{ - free((void *)baseAddress); -} - -void GPUImageCreateResizedSampleBuffer(CVPixelBufferRef cameraFrame, CGSize finalSize, CMSampleBufferRef *sampleBuffer) -{ - // CVPixelBufferCreateWithPlanarBytes for YUV input - - CGSize originalSize = CGSizeMake(CVPixelBufferGetWidth(cameraFrame), CVPixelBufferGetHeight(cameraFrame)); - - CVPixelBufferLockBaseAddress(cameraFrame, 0); - GLubyte *sourceImageBytes = CVPixelBufferGetBaseAddress(cameraFrame); - CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, sourceImageBytes, CVPixelBufferGetBytesPerRow(cameraFrame) * originalSize.height, NULL); - CGColorSpaceRef genericRGBColorspace = CGColorSpaceCreateDeviceRGB(); - CGImageRef cgImageFromBytes = CGImageCreate((int)originalSize.width, (int)originalSize.height, 8, 32, CVPixelBufferGetBytesPerRow(cameraFrame), genericRGBColorspace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst, dataProvider, NULL, NO, kCGRenderingIntentDefault); - - GLubyte *imageData = (GLubyte *) calloc(1, (int)finalSize.width * (int)finalSize.height * 4); - - CGContextRef imageContext = CGBitmapContextCreate(imageData, (int)finalSize.width, (int)finalSize.height, 8, (int)finalSize.width * 4, genericRGBColorspace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); - CGContextDrawImage(imageContext, CGRectMake(0.0, 0.0, finalSize.width, finalSize.height), cgImageFromBytes); - CGImageRelease(cgImageFromBytes); - CGContextRelease(imageContext); - CGColorSpaceRelease(genericRGBColorspace); - CGDataProviderRelease(dataProvider); - - CVPixelBufferRef pixel_buffer = NULL; - CVPixelBufferCreateWithBytes(kCFAllocatorDefault, finalSize.width, finalSize.height, kCVPixelFormatType_32BGRA, imageData, finalSize.width * 4, stillImageDataReleaseCallback, NULL, NULL, &pixel_buffer); - CMVideoFormatDescriptionRef videoInfo = NULL; - CMVideoFormatDescriptionCreateForImageBuffer(NULL, pixel_buffer, &videoInfo); - - CMTime frameTime = CMTimeMake(1, 30); - CMSampleTimingInfo timing = {frameTime, frameTime, kCMTimeInvalid}; - - CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, pixel_buffer, YES, NULL, NULL, videoInfo, &timing, sampleBuffer); - CVPixelBufferUnlockBaseAddress(cameraFrame, 0); - CFRelease(videoInfo); - CVPixelBufferRelease(pixel_buffer); -} - -@interface GPUImageStillCamera () -{ - AVCaptureStillImageOutput *photoOutput; -} - -// Methods calling this are responsible for calling dispatch_semaphore_signal(frameRenderingSemaphore) somewhere inside the block -- (void)capturePhotoProcessedUpToFilter:(GPUImageOutput *)finalFilterInChain withImageOnGPUHandler:(void (^)(NSError *error))block; - -@end - -@implementation GPUImageStillCamera { - BOOL requiresFrontCameraTextureCacheCorruptionWorkaround; -} - -@synthesize currentCaptureMetadata = _currentCaptureMetadata; -@synthesize jpegCompressionQuality = _jpegCompressionQuality; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithSessionPreset:(NSString *)sessionPreset cameraPosition:(AVCaptureDevicePosition)cameraPosition; -{ - if (!(self = [super initWithSessionPreset:sessionPreset cameraPosition:cameraPosition])) - { - return nil; - } - - /* Detect iOS version < 6 which require a texture cache corruption workaround */ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - requiresFrontCameraTextureCacheCorruptionWorkaround = [[[UIDevice currentDevice] systemVersion] compare:@"6.0" options:NSNumericSearch] == NSOrderedAscending; -#pragma clang diagnostic pop - - [self.captureSession beginConfiguration]; - - photoOutput = [[AVCaptureStillImageOutput alloc] init]; - - // Having a still photo input set to BGRA and video to YUV doesn't work well, so since I don't have YUV resizing for iPhone 4 yet, kick back to BGRA for that device -// if (captureAsYUV && [GPUImageContext supportsFastTextureUpload]) - if (captureAsYUV && [GPUImageContext deviceSupportsRedTextures]) - { - BOOL supportsFullYUVRange = NO; - NSArray *supportedPixelFormats = photoOutput.availableImageDataCVPixelFormatTypes; - for (NSNumber *currentPixelFormat in supportedPixelFormats) - { - if ([currentPixelFormat intValue] == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) - { - supportsFullYUVRange = YES; - } - } - - if (supportsFullYUVRange) - { - [photoOutput setOutputSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange] forKey:(id)kCVPixelBufferPixelFormatTypeKey]]; - } - else - { - [photoOutput setOutputSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange] forKey:(id)kCVPixelBufferPixelFormatTypeKey]]; - } - } - else - { - captureAsYUV = NO; - [photoOutput setOutputSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]]; - [videoOutput setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]]; - } - - [self.captureSession addOutput:photoOutput]; - - [self.captureSession commitConfiguration]; - - self.jpegCompressionQuality = 0.8; - - return self; -} - -- (id)init; -{ - if (!(self = [self initWithSessionPreset:AVCaptureSessionPresetPhoto cameraPosition:AVCaptureDevicePositionBack])) - { - return nil; - } - return self; -} - -- (void)removeInputsAndOutputs; -{ - [self.captureSession removeOutput:photoOutput]; - [super removeInputsAndOutputs]; -} - -#pragma mark - -#pragma mark Photography controls - -- (void)capturePhotoAsSampleBufferWithCompletionHandler:(void (^)(CMSampleBufferRef imageSampleBuffer, NSError *error))block -{ - NSLog(@"If you want to use the method capturePhotoAsSampleBufferWithCompletionHandler:, you must comment out the line in GPUImageStillCamera.m in the method initWithSessionPreset:cameraPosition: which sets the CVPixelBufferPixelFormatTypeKey, as well as uncomment the rest of the method capturePhotoAsSampleBufferWithCompletionHandler:. However, if you do this you cannot use any of the photo capture methods to take a photo if you also supply a filter."); - - /*dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_FOREVER); - - [photoOutput captureStillImageAsynchronouslyFromConnection:[[photoOutput connections] objectAtIndex:0] completionHandler:^(CMSampleBufferRef imageSampleBuffer, NSError *error) { - block(imageSampleBuffer, error); - }]; - - dispatch_semaphore_signal(frameRenderingSemaphore); - - */ - - return; -} - -- (void)capturePhotoAsImageProcessedUpToFilter:(GPUImageOutput *)finalFilterInChain withCompletionHandler:(void (^)(UIImage *processedImage, NSError *error))block; -{ - [self capturePhotoProcessedUpToFilter:finalFilterInChain withImageOnGPUHandler:^(NSError *error) { - UIImage *filteredPhoto = nil; - - if(!error){ - filteredPhoto = [finalFilterInChain imageFromCurrentFramebuffer]; - } - dispatch_semaphore_signal(frameRenderingSemaphore); - - block(filteredPhoto, error); - }]; -} - -- (void)capturePhotoAsImageProcessedUpToFilter:(GPUImageOutput *)finalFilterInChain withOrientation:(UIImageOrientation)orientation withCompletionHandler:(void (^)(UIImage *processedImage, NSError *error))block { - [self capturePhotoProcessedUpToFilter:finalFilterInChain withImageOnGPUHandler:^(NSError *error) { - UIImage *filteredPhoto = nil; - - if(!error) { - filteredPhoto = [finalFilterInChain imageFromCurrentFramebufferWithOrientation:orientation]; - } - dispatch_semaphore_signal(frameRenderingSemaphore); - - block(filteredPhoto, error); - }]; -} - -- (void)capturePhotoAsJPEGProcessedUpToFilter:(GPUImageOutput *)finalFilterInChain withCompletionHandler:(void (^)(NSData *processedJPEG, NSError *error))block; -{ -// reportAvailableMemoryForGPUImage(@"Before Capture"); - - [self capturePhotoProcessedUpToFilter:finalFilterInChain withImageOnGPUHandler:^(NSError *error) { - NSData *dataForJPEGFile = nil; - - if(!error){ - @autoreleasepool { - UIImage *filteredPhoto = [finalFilterInChain imageFromCurrentFramebuffer]; - dispatch_semaphore_signal(frameRenderingSemaphore); -// reportAvailableMemoryForGPUImage(@"After UIImage generation"); - - dataForJPEGFile = UIImageJPEGRepresentation(filteredPhoto,self.jpegCompressionQuality); -// reportAvailableMemoryForGPUImage(@"After JPEG generation"); - } - -// reportAvailableMemoryForGPUImage(@"After autorelease pool"); - }else{ - dispatch_semaphore_signal(frameRenderingSemaphore); - } - - block(dataForJPEGFile, error); - }]; -} - -- (void)capturePhotoAsJPEGProcessedUpToFilter:(GPUImageOutput *)finalFilterInChain withOrientation:(UIImageOrientation)orientation withCompletionHandler:(void (^)(NSData *processedImage, NSError *error))block { - [self capturePhotoProcessedUpToFilter:finalFilterInChain withImageOnGPUHandler:^(NSError *error) { - NSData *dataForJPEGFile = nil; - - if(!error) { - @autoreleasepool { - UIImage *filteredPhoto = [finalFilterInChain imageFromCurrentFramebufferWithOrientation:orientation]; - dispatch_semaphore_signal(frameRenderingSemaphore); - - dataForJPEGFile = UIImageJPEGRepresentation(filteredPhoto, self.jpegCompressionQuality); - } - } else { - dispatch_semaphore_signal(frameRenderingSemaphore); - } - - block(dataForJPEGFile, error); - }]; -} - -- (void)capturePhotoAsPNGProcessedUpToFilter:(GPUImageOutput *)finalFilterInChain withCompletionHandler:(void (^)(NSData *processedPNG, NSError *error))block; -{ - - [self capturePhotoProcessedUpToFilter:finalFilterInChain withImageOnGPUHandler:^(NSError *error) { - NSData *dataForPNGFile = nil; - - if(!error){ - @autoreleasepool { - UIImage *filteredPhoto = [finalFilterInChain imageFromCurrentFramebuffer]; - dispatch_semaphore_signal(frameRenderingSemaphore); - dataForPNGFile = UIImagePNGRepresentation(filteredPhoto); - } - }else{ - dispatch_semaphore_signal(frameRenderingSemaphore); - } - - block(dataForPNGFile, error); - }]; - - return; -} - -- (void)capturePhotoAsPNGProcessedUpToFilter:(GPUImageOutput *)finalFilterInChain withOrientation:(UIImageOrientation)orientation withCompletionHandler:(void (^)(NSData *processedPNG, NSError *error))block; -{ - - [self capturePhotoProcessedUpToFilter:finalFilterInChain withImageOnGPUHandler:^(NSError *error) { - NSData *dataForPNGFile = nil; - - if(!error){ - @autoreleasepool { - UIImage *filteredPhoto = [finalFilterInChain imageFromCurrentFramebufferWithOrientation:orientation]; - dispatch_semaphore_signal(frameRenderingSemaphore); - dataForPNGFile = UIImagePNGRepresentation(filteredPhoto); - } - }else{ - dispatch_semaphore_signal(frameRenderingSemaphore); - } - - block(dataForPNGFile, error); - }]; - - return; -} - -#pragma mark - Private Methods - -- (void)capturePhotoProcessedUpToFilter:(GPUImageOutput *)finalFilterInChain withImageOnGPUHandler:(void (^)(NSError *error))block -{ - dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_FOREVER); - - if(photoOutput.isCapturingStillImage){ - block([NSError errorWithDomain:AVFoundationErrorDomain code:AVErrorMaximumStillImageCaptureRequestsExceeded userInfo:nil]); - return; - } - - [photoOutput captureStillImageAsynchronouslyFromConnection:[[photoOutput connections] objectAtIndex:0] completionHandler:^(CMSampleBufferRef imageSampleBuffer, NSError *error) { - if(imageSampleBuffer == NULL){ - block(error); - return; - } - - // For now, resize photos to fix within the max texture size of the GPU - CVImageBufferRef cameraFrame = CMSampleBufferGetImageBuffer(imageSampleBuffer); - - CGSize sizeOfPhoto = CGSizeMake(CVPixelBufferGetWidth(cameraFrame), CVPixelBufferGetHeight(cameraFrame)); - CGSize scaledImageSizeToFitOnGPU = [GPUImageContext sizeThatFitsWithinATextureForSize:sizeOfPhoto]; - if (!CGSizeEqualToSize(sizeOfPhoto, scaledImageSizeToFitOnGPU)) - { - CMSampleBufferRef sampleBuffer = NULL; - - if (CVPixelBufferGetPlaneCount(cameraFrame) > 0) - { - NSAssert(NO, @"Error: no downsampling for YUV input in the framework yet"); - } - else - { - GPUImageCreateResizedSampleBuffer(cameraFrame, scaledImageSizeToFitOnGPU, &sampleBuffer); - } - - dispatch_semaphore_signal(frameRenderingSemaphore); - [finalFilterInChain useNextFrameForImageCapture]; - [self captureOutput:photoOutput didOutputSampleBuffer:sampleBuffer fromConnection:[[photoOutput connections] objectAtIndex:0]]; - dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_FOREVER); - if (sampleBuffer != NULL) - CFRelease(sampleBuffer); - } - else - { - // This is a workaround for the corrupt images that are sometimes returned when taking a photo with the front camera and using the iOS 5.0 texture caches - AVCaptureDevicePosition currentCameraPosition = [[videoInput device] position]; - if ( (currentCameraPosition != AVCaptureDevicePositionFront) || (![GPUImageContext supportsFastTextureUpload]) || !requiresFrontCameraTextureCacheCorruptionWorkaround) - { - dispatch_semaphore_signal(frameRenderingSemaphore); - [finalFilterInChain useNextFrameForImageCapture]; - [self captureOutput:photoOutput didOutputSampleBuffer:imageSampleBuffer fromConnection:[[photoOutput connections] objectAtIndex:0]]; - dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_FOREVER); - } - } - - CFDictionaryRef metadata = CMCopyDictionaryOfAttachments(NULL, imageSampleBuffer, kCMAttachmentMode_ShouldPropagate); - _currentCaptureMetadata = (__bridge_transfer NSDictionary *)metadata; - - block(nil); - - _currentCaptureMetadata = nil; - }]; -} - - - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageStretchDistortionFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageStretchDistortionFilter.h deleted file mode 100755 index 07803095..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageStretchDistortionFilter.h +++ /dev/null @@ -1,13 +0,0 @@ -#import "GPUImageFilter.h" - -/** Creates a stretch distortion of the image - */ -@interface GPUImageStretchDistortionFilter : GPUImageFilter { - GLint centerUniform; -} - -/** The center about which to apply the distortion, with a default of (0.5, 0.5) - */ -@property(readwrite, nonatomic) CGPoint center; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageStretchDistortionFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageStretchDistortionFilter.m deleted file mode 100755 index d38cac34..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageStretchDistortionFilter.m +++ /dev/null @@ -1,99 +0,0 @@ -#import "GPUImageStretchDistortionFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageStretchDistortionFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform highp vec2 center; - - void main() - { - highp vec2 normCoord = 2.0 * textureCoordinate - 1.0; - highp vec2 normCenter = 2.0 * center - 1.0; - - normCoord -= normCenter; - mediump vec2 s = sign(normCoord); - normCoord = abs(normCoord); - normCoord = 0.5 * normCoord + 0.5 * smoothstep(0.25, 0.5, normCoord) * normCoord; - normCoord = s * normCoord; - - normCoord += normCenter; - - mediump vec2 textureCoordinateToUse = normCoord / 2.0 + 0.5; - - - gl_FragColor = texture2D(inputImageTexture, textureCoordinateToUse ); - - } -); -#else -NSString *const kGPUImageStretchDistortionFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform vec2 center; - - void main() - { - vec2 normCoord = 2.0 * textureCoordinate - 1.0; - vec2 normCenter = 2.0 * center - 1.0; - - normCoord -= normCenter; - vec2 s = sign(normCoord); - normCoord = abs(normCoord); - normCoord = 0.5 * normCoord + 0.5 * smoothstep(0.25, 0.5, normCoord) * normCoord; - normCoord = s * normCoord; - - normCoord += normCenter; - - vec2 textureCoordinateToUse = normCoord / 2.0 + 0.5; - - gl_FragColor = texture2D(inputImageTexture, textureCoordinateToUse); - } -); -#endif - -@implementation GPUImageStretchDistortionFilter - -@synthesize center = _center; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageStretchDistortionFragmentShaderString])) - { - return nil; - } - - centerUniform = [filterProgram uniformIndex:@"center"]; - - self.center = CGPointMake(0.5, 0.5); - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -{ - [super setInputRotation:newInputRotation atIndex:textureIndex]; - [self setCenter:self.center]; -} - -- (void)setCenter:(CGPoint)newValue; -{ - _center = newValue; - - CGPoint rotatedPoint = [self rotatedPoint:_center forRotation:inputRotation]; - [self setPoint:rotatedPoint forUniform:centerUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSubtractBlendFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSubtractBlendFilter.h deleted file mode 100755 index 8dee8215..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSubtractBlendFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageSubtractBlendFilter : GPUImageTwoInputFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSubtractBlendFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSubtractBlendFilter.m deleted file mode 100755 index 8938baea..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSubtractBlendFilter.m +++ /dev/null @@ -1,52 +0,0 @@ -#import "GPUImageSubtractBlendFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageSubtractBlendFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - lowp vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2); - - gl_FragColor = vec4(textureColor.rgb - textureColor2.rgb, textureColor.a); - } -); -#else -NSString *const kGPUImageSubtractBlendFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2); - - gl_FragColor = vec4(textureColor.rgb - textureColor2.rgb, textureColor.a); - } -); -#endif - -@implementation GPUImageSubtractBlendFilter - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageSubtractBlendFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSwirlFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSwirlFilter.h deleted file mode 100755 index ed7d0122..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSwirlFilter.h +++ /dev/null @@ -1,17 +0,0 @@ -#import "GPUImageFilter.h" - -/** Creates a swirl distortion on the image - */ -@interface GPUImageSwirlFilter : GPUImageFilter -{ - GLint radiusUniform, centerUniform, angleUniform; -} - -/// The center about which to apply the distortion, with a default of (0.5, 0.5) -@property(readwrite, nonatomic) CGPoint center; -/// The radius of the distortion, ranging from 0.0 to 1.0, with a default of 0.5 -@property(readwrite, nonatomic) CGFloat radius; -/// The amount of distortion to apply, with a minimum of 0.0 and a default of 1.0 -@property(readwrite, nonatomic) CGFloat angle; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSwirlFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSwirlFilter.m deleted file mode 100755 index 5462bc65..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageSwirlFilter.m +++ /dev/null @@ -1,123 +0,0 @@ -#import "GPUImageSwirlFilter.h" - -// Adapted from the shader example here: http://www.geeks3d.com/20110428/shader-library-swirl-post-processing-filter-in-glsl/ -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageSwirlFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform highp vec2 center; - uniform highp float radius; - uniform highp float angle; - - void main() - { - highp vec2 textureCoordinateToUse = textureCoordinate; - highp float dist = distance(center, textureCoordinate); - if (dist < radius) - { - textureCoordinateToUse -= center; - highp float percent = (radius - dist) / radius; - highp float theta = percent * percent * angle * 8.0; - highp float s = sin(theta); - highp float c = cos(theta); - textureCoordinateToUse = vec2(dot(textureCoordinateToUse, vec2(c, -s)), dot(textureCoordinateToUse, vec2(s, c))); - textureCoordinateToUse += center; - } - - gl_FragColor = texture2D(inputImageTexture, textureCoordinateToUse ); - - } -); -#else -NSString *const kGPUImageSwirlFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform vec2 center; - uniform float radius; - uniform float angle; - - void main() - { - vec2 textureCoordinateToUse = textureCoordinate; - float dist = distance(center, textureCoordinate); - if (dist < radius) - { - textureCoordinateToUse -= center; - float percent = (radius - dist) / radius; - float theta = percent * percent * angle * 8.0; - float s = sin(theta); - float c = cos(theta); - textureCoordinateToUse = vec2(dot(textureCoordinateToUse, vec2(c, -s)), dot(textureCoordinateToUse, vec2(s, c))); - textureCoordinateToUse += center; - } - - gl_FragColor = texture2D(inputImageTexture, textureCoordinateToUse ); - } -); -#endif - -@implementation GPUImageSwirlFilter - -@synthesize center = _center; -@synthesize radius = _radius; -@synthesize angle = _angle; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageSwirlFragmentShaderString])) - { - return nil; - } - - radiusUniform = [filterProgram uniformIndex:@"radius"]; - angleUniform = [filterProgram uniformIndex:@"angle"]; - centerUniform = [filterProgram uniformIndex:@"center"]; - - self.radius = 0.5; - self.angle = 1.0; - self.center = CGPointMake(0.5, 0.5); - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -{ - [super setInputRotation:newInputRotation atIndex:textureIndex]; - [self setCenter:self.center]; -} - -- (void)setRadius:(CGFloat)newValue; -{ - _radius = newValue; - - [self setFloat:_radius forUniform:radiusUniform program:filterProgram]; -} - -- (void)setAngle:(CGFloat)newValue; -{ - _angle = newValue; - - [self setFloat:_angle forUniform:angleUniform program:filterProgram]; -} - -- (void)setCenter:(CGPoint)newValue; -{ - _center = newValue; - - CGPoint rotatedPoint = [self rotatedPoint:_center forRotation:inputRotation]; - [self setPoint:rotatedPoint forUniform:centerUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTextureInput.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTextureInput.h deleted file mode 100755 index 8190305d..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTextureInput.h +++ /dev/null @@ -1,14 +0,0 @@ -#import "GPUImageOutput.h" - -@interface GPUImageTextureInput : GPUImageOutput -{ - CGSize textureSize; -} - -// Initialization and teardown -- (id)initWithTexture:(GLuint)newInputTexture size:(CGSize)newTextureSize; - -// Image rendering -- (void)processTextureWithFrameTime:(CMTime)frameTime; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTextureInput.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTextureInput.m deleted file mode 100755 index ad3ca1d1..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTextureInput.m +++ /dev/null @@ -1,46 +0,0 @@ -#import "GPUImageTextureInput.h" - -@implementation GPUImageTextureInput - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithTexture:(GLuint)newInputTexture size:(CGSize)newTextureSize; -{ - if (!(self = [super init])) - { - return nil; - } - - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext useImageProcessingContext]; - }); - - textureSize = newTextureSize; - - runSynchronouslyOnVideoProcessingQueue(^{ - outputFramebuffer = [[GPUImageFramebuffer alloc] initWithSize:newTextureSize overriddenTexture:newInputTexture]; - }); - - return self; -} - -#pragma mark - -#pragma mark Image rendering - -- (void)processTextureWithFrameTime:(CMTime)frameTime; -{ - runAsynchronouslyOnVideoProcessingQueue(^{ - for (id currentTarget in targets) - { - NSInteger indexOfObject = [targets indexOfObject:currentTarget]; - NSInteger targetTextureIndex = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; - - [currentTarget setInputSize:textureSize atIndex:targetTextureIndex]; - [currentTarget setInputFramebuffer:outputFramebuffer atIndex:targetTextureIndex]; - [currentTarget newFrameReadyAtTime:frameTime atIndex:targetTextureIndex]; - } - }); -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTextureOutput.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTextureOutput.h deleted file mode 100755 index 05e1f36e..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTextureOutput.h +++ /dev/null @@ -1,21 +0,0 @@ -#import -#import "GPUImageContext.h" - -@protocol GPUImageTextureOutputDelegate; - -@interface GPUImageTextureOutput : NSObject -{ - GPUImageFramebuffer *firstInputFramebuffer; -} - -@property(readwrite, unsafe_unretained, nonatomic) id delegate; -@property(readonly) GLuint texture; -@property(nonatomic) BOOL enabled; - -- (void)doneWithTexture; - -@end - -@protocol GPUImageTextureOutputDelegate -- (void)newFrameReadyFromTextureOutput:(GPUImageTextureOutput *)callbackTextureOutput; -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTextureOutput.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTextureOutput.m deleted file mode 100755 index 1e1f24f2..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTextureOutput.m +++ /dev/null @@ -1,83 +0,0 @@ -#import "GPUImageTextureOutput.h" - -@implementation GPUImageTextureOutput - -@synthesize delegate = _delegate; -@synthesize texture = _texture; -@synthesize enabled; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super init])) - { - return nil; - } - - self.enabled = YES; - - return self; -} - -- (void)doneWithTexture; -{ - [firstInputFramebuffer unlock]; -} - -#pragma mark - -#pragma mark GPUImageInput protocol - -- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex; -{ - [_delegate newFrameReadyFromTextureOutput:self]; -} - -- (NSInteger)nextAvailableTextureIndex; -{ - return 0; -} - -// TODO: Deal with the fact that the texture changes regularly as a result of the caching -- (void)setInputFramebuffer:(GPUImageFramebuffer *)newInputFramebuffer atIndex:(NSInteger)textureIndex; -{ - firstInputFramebuffer = newInputFramebuffer; - [firstInputFramebuffer lock]; - - _texture = [firstInputFramebuffer texture]; -} - -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -{ -} - -- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex; -{ -} - -- (CGSize)maximumOutputSize; -{ - return CGSizeZero; -} - -- (void)endProcessing -{ -} - -- (BOOL)shouldIgnoreUpdatesToThisTarget; -{ - return NO; -} - -- (BOOL)wantsMonochromeInput; -{ - return NO; -} - -- (void)setCurrentlyReceivingMonochromeInput:(BOOL)newValue; -{ - -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThreeInputFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThreeInputFilter.h deleted file mode 100644 index 5ecd53e0..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThreeInputFilter.h +++ /dev/null @@ -1,21 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -extern NSString *const kGPUImageThreeInputTextureVertexShaderString; - -@interface GPUImageThreeInputFilter : GPUImageTwoInputFilter -{ - GPUImageFramebuffer *thirdInputFramebuffer; - - GLint filterThirdTextureCoordinateAttribute; - GLint filterInputTextureUniform3; - GPUImageRotationMode inputRotation3; - GLuint filterSourceTexture3; - CMTime thirdFrameTime; - - BOOL hasSetSecondTexture, hasReceivedThirdFrame, thirdFrameWasVideo; - BOOL thirdFrameCheckDisabled; -} - -- (void)disableThirdFrameCheck; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThreeInputFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThreeInputFilter.m deleted file mode 100644 index 2f4f113f..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThreeInputFilter.m +++ /dev/null @@ -1,328 +0,0 @@ -#import "GPUImageThreeInputFilter.h" - - -NSString *const kGPUImageThreeInputTextureVertexShaderString = SHADER_STRING -( - attribute vec4 position; - attribute vec4 inputTextureCoordinate; - attribute vec4 inputTextureCoordinate2; - attribute vec4 inputTextureCoordinate3; - - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - varying vec2 textureCoordinate3; - - void main() - { - gl_Position = position; - textureCoordinate = inputTextureCoordinate.xy; - textureCoordinate2 = inputTextureCoordinate2.xy; - textureCoordinate3 = inputTextureCoordinate3.xy; - } -); - -@implementation GPUImageThreeInputFilter - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithFragmentShaderFromString:(NSString *)fragmentShaderString; -{ - if (!(self = [self initWithVertexShaderFromString:kGPUImageThreeInputTextureVertexShaderString fragmentShaderFromString:fragmentShaderString])) - { - return nil; - } - - return self; -} - -- (id)initWithVertexShaderFromString:(NSString *)vertexShaderString fragmentShaderFromString:(NSString *)fragmentShaderString; -{ - if (!(self = [super initWithVertexShaderFromString:vertexShaderString fragmentShaderFromString:fragmentShaderString])) - { - return nil; - } - - inputRotation3 = kGPUImageNoRotation; - - hasSetSecondTexture = NO; - - hasReceivedThirdFrame = NO; - thirdFrameWasVideo = NO; - thirdFrameCheckDisabled = NO; - - thirdFrameTime = kCMTimeInvalid; - - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext useImageProcessingContext]; - filterThirdTextureCoordinateAttribute = [filterProgram attributeIndex:@"inputTextureCoordinate3"]; - - filterInputTextureUniform3 = [filterProgram uniformIndex:@"inputImageTexture3"]; // This does assume a name of "inputImageTexture3" for the third input texture in the fragment shader - glEnableVertexAttribArray(filterThirdTextureCoordinateAttribute); - }); - - return self; -} - -- (void)initializeAttributes; -{ - [super initializeAttributes]; - [filterProgram addAttribute:@"inputTextureCoordinate3"]; -} - -- (void)disableThirdFrameCheck; -{ - thirdFrameCheckDisabled = YES; -} - -#pragma mark - -#pragma mark Rendering - -- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates; -{ - if (self.preventRendering) - { - [firstInputFramebuffer unlock]; - [secondInputFramebuffer unlock]; - [thirdInputFramebuffer unlock]; - return; - } - - [GPUImageContext setActiveShaderProgram:filterProgram]; - outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:[self sizeOfFBO] textureOptions:self.outputTextureOptions onlyTexture:NO]; - [outputFramebuffer activateFramebuffer]; - if (usingNextFrameForImageCapture) - { - [outputFramebuffer lock]; - } - - [self setUniformsForProgramAtIndex:0]; - - glClearColor(backgroundColorRed, backgroundColorGreen, backgroundColorBlue, backgroundColorAlpha); - glClear(GL_COLOR_BUFFER_BIT); - - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, [firstInputFramebuffer texture]); - glUniform1i(filterInputTextureUniform, 2); - - glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D, [secondInputFramebuffer texture]); - glUniform1i(filterInputTextureUniform2, 3); - - glActiveTexture(GL_TEXTURE4); - glBindTexture(GL_TEXTURE_2D, [thirdInputFramebuffer texture]); - glUniform1i(filterInputTextureUniform3, 4); - - glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, vertices); - glVertexAttribPointer(filterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates); - glVertexAttribPointer(filterSecondTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, [[self class] textureCoordinatesForRotation:inputRotation2]); - glVertexAttribPointer(filterThirdTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, [[self class] textureCoordinatesForRotation:inputRotation3]); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - [firstInputFramebuffer unlock]; - [secondInputFramebuffer unlock]; - [thirdInputFramebuffer unlock]; - if (usingNextFrameForImageCapture) - { - dispatch_semaphore_signal(imageCaptureSemaphore); - } -} - -#pragma mark - -#pragma mark GPUImageInput - -- (NSInteger)nextAvailableTextureIndex; -{ - if (hasSetSecondTexture) - { - return 2; - } - else if (hasSetFirstTexture) - { - return 1; - } - else - { - return 0; - } -} - -- (void)setInputFramebuffer:(GPUImageFramebuffer *)newInputFramebuffer atIndex:(NSInteger)textureIndex; -{ - if (textureIndex == 0) - { - firstInputFramebuffer = newInputFramebuffer; - hasSetFirstTexture = YES; - [firstInputFramebuffer lock]; - } - else if (textureIndex == 1) - { - secondInputFramebuffer = newInputFramebuffer; - hasSetSecondTexture = YES; - [secondInputFramebuffer lock]; - } - else - { - thirdInputFramebuffer = newInputFramebuffer; - [thirdInputFramebuffer lock]; - } -} - -- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex; -{ - if (textureIndex == 0) - { - [super setInputSize:newSize atIndex:textureIndex]; - - if (CGSizeEqualToSize(newSize, CGSizeZero)) - { - hasSetFirstTexture = NO; - } - } - else if (textureIndex == 1) - { - if (CGSizeEqualToSize(newSize, CGSizeZero)) - { - hasSetSecondTexture = NO; - } - } -} - -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -{ - if (textureIndex == 0) - { - inputRotation = newInputRotation; - } - else if (textureIndex == 1) - { - inputRotation2 = newInputRotation; - } - else - { - inputRotation3 = newInputRotation; - } -} - -- (CGSize)rotatedSize:(CGSize)sizeToRotate forIndex:(NSInteger)textureIndex; -{ - CGSize rotatedSize = sizeToRotate; - - GPUImageRotationMode rotationToCheck; - if (textureIndex == 0) - { - rotationToCheck = inputRotation; - } - else if (textureIndex == 1) - { - rotationToCheck = inputRotation2; - } - else - { - rotationToCheck = inputRotation3; - } - - if (GPUImageRotationSwapsWidthAndHeight(rotationToCheck)) - { - rotatedSize.width = sizeToRotate.height; - rotatedSize.height = sizeToRotate.width; - } - - return rotatedSize; -} - -- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex; -{ - // You can set up infinite update loops, so this helps to short circuit them - if (hasReceivedFirstFrame && hasReceivedSecondFrame && hasReceivedThirdFrame) - { - return; - } - - BOOL updatedMovieFrameOppositeStillImage = NO; - - if (textureIndex == 0) - { - hasReceivedFirstFrame = YES; - firstFrameTime = frameTime; - if (secondFrameCheckDisabled) - { - hasReceivedSecondFrame = YES; - } - if (thirdFrameCheckDisabled) - { - hasReceivedThirdFrame = YES; - } - - if (!CMTIME_IS_INDEFINITE(frameTime)) - { - if CMTIME_IS_INDEFINITE(secondFrameTime) - { - updatedMovieFrameOppositeStillImage = YES; - } - } - } - else if (textureIndex == 1) - { - hasReceivedSecondFrame = YES; - secondFrameTime = frameTime; - if (firstFrameCheckDisabled) - { - hasReceivedFirstFrame = YES; - } - if (thirdFrameCheckDisabled) - { - hasReceivedThirdFrame = YES; - } - - if (!CMTIME_IS_INDEFINITE(frameTime)) - { - if CMTIME_IS_INDEFINITE(firstFrameTime) - { - updatedMovieFrameOppositeStillImage = YES; - } - } - } - else - { - hasReceivedThirdFrame = YES; - thirdFrameTime = frameTime; - if (firstFrameCheckDisabled) - { - hasReceivedFirstFrame = YES; - } - if (secondFrameCheckDisabled) - { - hasReceivedSecondFrame = YES; - } - - if (!CMTIME_IS_INDEFINITE(frameTime)) - { - if CMTIME_IS_INDEFINITE(firstFrameTime) - { - updatedMovieFrameOppositeStillImage = YES; - } - } - } - - // || (hasReceivedFirstFrame && secondFrameCheckDisabled) || (hasReceivedSecondFrame && firstFrameCheckDisabled) - if ((hasReceivedFirstFrame && hasReceivedSecondFrame && hasReceivedThirdFrame) || updatedMovieFrameOppositeStillImage) - { - static const GLfloat imageVertices[] = { - -1.0f, -1.0f, - 1.0f, -1.0f, - -1.0f, 1.0f, - 1.0f, 1.0f, - }; - - [self renderToTextureWithVertices:imageVertices textureCoordinates:[[self class] textureCoordinatesForRotation:inputRotation]]; - - [self informTargetsAboutNewFrameAtTime:frameTime]; - - hasReceivedFirstFrame = NO; - hasReceivedSecondFrame = NO; - hasReceivedThirdFrame = NO; - } -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdEdgeDetectionFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdEdgeDetectionFilter.h deleted file mode 100755 index 2036030c..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdEdgeDetectionFilter.h +++ /dev/null @@ -1,12 +0,0 @@ -#import "GPUImageSobelEdgeDetectionFilter.h" - -@interface GPUImageThresholdEdgeDetectionFilter : GPUImageSobelEdgeDetectionFilter -{ - GLint thresholdUniform; -} - -/** Any edge above this threshold will be black, and anything below white. Ranges from 0.0 to 1.0, with 0.8 as the default - */ -@property(readwrite, nonatomic) CGFloat threshold; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdEdgeDetectionFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdEdgeDetectionFilter.m deleted file mode 100755 index 553c600f..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdEdgeDetectionFilter.m +++ /dev/null @@ -1,145 +0,0 @@ -#import "GPUImageThresholdEdgeDetectionFilter.h" - -@implementation GPUImageThresholdEdgeDetectionFilter - -// Invert the colorspace for a sketch -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageThresholdEdgeDetectionFragmentShaderString = SHADER_STRING -( - precision highp float; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - uniform lowp float threshold; - - uniform float edgeStrength; - - void main() - { -// float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; -// float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r; -// float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r; -// float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r; - float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r; - float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r; - float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r; - float centerIntensity = texture2D(inputImageTexture, textureCoordinate).r; -// float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity; -// float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity; -// float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + leftIntensity + 2.0 * centerIntensity + rightIntensity; -// float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomIntensity + 2.0 * centerIntensity + topIntensity; - float h = (centerIntensity - topIntensity) + (bottomIntensity - centerIntensity); - float v = (centerIntensity - leftIntensity) + (rightIntensity - centerIntensity); -// float h = (centerIntensity - topIntensity); -// float j = (topIntensity - centerIntensity); -// h = max(h,j); -// j = abs(h); -// float v = (centerIntensity - leftIntensity); - - float mag = length(vec2(h, v)) * edgeStrength; - mag = step(threshold, mag); - -// float mag = abs(h); - -// gl_FragColor = vec4(h, h, h, 1.0); -// gl_FragColor = vec4(texture2D(inputImageTexture, textureCoordinate)); -// gl_FragColor = vec4(h, centerIntensity, j, 1.0); - gl_FragColor = vec4(mag, mag, mag, 1.0); - } -); -#else -NSString *const kGPUImageThresholdEdgeDetectionFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float threshold; - - uniform float edgeStrength; - - void main() - { - float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r; - float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r; - float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r; - float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r; - float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r; - float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity; - h = max(0.0, h); - float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity; - v = max(0.0, v); - - float mag = length(vec2(h, v)) * edgeStrength; - mag = step(threshold, mag); - - gl_FragColor = vec4(vec3(mag), 1.0); - } -); -#endif - -#pragma mark - -#pragma mark Initialization and teardown - -@synthesize threshold = _threshold; - -- (id)initWithFragmentShaderFromString:(NSString *)fragmentShaderString; -{ - if (!(self = [super initWithFragmentShaderFromString:fragmentShaderString])) - { - return nil; - } - - thresholdUniform = [secondFilterProgram uniformIndex:@"threshold"]; - self.threshold = 0.25; - self.edgeStrength = 1.0; - - return self; -} - - -- (id)init; -{ - if (!(self = [self initWithFragmentShaderFromString:kGPUImageThresholdEdgeDetectionFragmentShaderString])) - { - return nil; - } - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setThreshold:(CGFloat)newValue; -{ - _threshold = newValue; - - [self setFloat:_threshold forUniform:thresholdUniform program:secondFilterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdSketchFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdSketchFilter.h deleted file mode 100644 index fda58979..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdSketchFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImageThresholdEdgeDetectionFilter.h" - -@interface GPUImageThresholdSketchFilter : GPUImageThresholdEdgeDetectionFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdSketchFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdSketchFilter.m deleted file mode 100644 index d24e9dea..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdSketchFilter.m +++ /dev/null @@ -1,103 +0,0 @@ -#import "GPUImageThresholdSketchFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageThresholdSketchFragmentShaderString = SHADER_STRING -( - precision highp float; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - uniform lowp float threshold; - uniform float edgeStrength; - - const highp vec3 W = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r; - float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r; - float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r; - float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r; - float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r; - float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity; - float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity; - - float mag = (length(vec2(h, v)) * edgeStrength); - mag = step(threshold, mag); - mag = 1.0 - mag; - - gl_FragColor = vec4(vec3(mag), 1.0); - } -); -#else -NSString *const kGPUImageThresholdSketchFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - uniform float threshold; - uniform float edgeStrength; - - const vec3 W = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r; - float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r; - float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r; - float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r; - float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r; - float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity; - float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity; - - float mag = 1.0 - length(vec2(h, v) * edgeStrength); - mag = step(threshold, mag); - - gl_FragColor = vec4(vec3(mag), 1.0); - } -); -#endif - -@implementation GPUImageThresholdSketchFilter - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [self initWithFragmentShaderFromString:kGPUImageThresholdSketchFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdedNonMaximumSuppressionFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdedNonMaximumSuppressionFilter.h deleted file mode 100644 index 9c6e5d72..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdedNonMaximumSuppressionFilter.h +++ /dev/null @@ -1,14 +0,0 @@ -#import "GPUImage3x3TextureSamplingFilter.h" - -@interface GPUImageThresholdedNonMaximumSuppressionFilter : GPUImage3x3TextureSamplingFilter -{ - GLint thresholdUniform; -} - -/** Any local maximum above this threshold will be white, and anything below black. Ranges from 0.0 to 1.0, with 0.8 as the default - */ -@property(readwrite, nonatomic) CGFloat threshold; - -- (id)initWithPackedColorspace:(BOOL)inputUsesPackedColorspace; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdedNonMaximumSuppressionFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdedNonMaximumSuppressionFilter.m deleted file mode 100644 index 439d3119..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageThresholdedNonMaximumSuppressionFilter.m +++ /dev/null @@ -1,297 +0,0 @@ -#import "GPUImageThresholdedNonMaximumSuppressionFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageThresholdedNonMaximumSuppressionFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - - varying highp vec2 textureCoordinate; - varying highp vec2 leftTextureCoordinate; - varying highp vec2 rightTextureCoordinate; - - varying highp vec2 topTextureCoordinate; - varying highp vec2 topLeftTextureCoordinate; - varying highp vec2 topRightTextureCoordinate; - - varying highp vec2 bottomTextureCoordinate; - varying highp vec2 bottomLeftTextureCoordinate; - varying highp vec2 bottomRightTextureCoordinate; - - uniform lowp float threshold; - - void main() - { - lowp float bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate).r; - lowp float bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - lowp float bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - lowp vec4 centerColor = texture2D(inputImageTexture, textureCoordinate); - lowp float leftColor = texture2D(inputImageTexture, leftTextureCoordinate).r; - lowp float rightColor = texture2D(inputImageTexture, rightTextureCoordinate).r; - lowp float topColor = texture2D(inputImageTexture, topTextureCoordinate).r; - lowp float topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate).r; - lowp float topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - - // Use a tiebreaker for pixels to the left and immediately above this one - lowp float multiplier = 1.0 - step(centerColor.r, topColor); - multiplier = multiplier * (1.0 - step(centerColor.r, topLeftColor)); - multiplier = multiplier * (1.0 - step(centerColor.r, leftColor)); - multiplier = multiplier * (1.0 - step(centerColor.r, bottomLeftColor)); - - lowp float maxValue = max(centerColor.r, bottomColor); - maxValue = max(maxValue, bottomRightColor); - maxValue = max(maxValue, rightColor); - maxValue = max(maxValue, topRightColor); - - lowp float finalValue = centerColor.r * step(maxValue, centerColor.r) * multiplier; - finalValue = step(threshold, finalValue); - - gl_FragColor = vec4(finalValue, finalValue, finalValue, 1.0); -// -// gl_FragColor = vec4((centerColor.rgb * step(maxValue, step(threshold, centerColor.r)) * multiplier), 1.0); - } -); - -NSString *const kGPUImageThresholdedNonMaximumSuppressionPackedColorspaceFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - - varying highp vec2 textureCoordinate; - varying highp vec2 leftTextureCoordinate; - varying highp vec2 rightTextureCoordinate; - - varying highp vec2 topTextureCoordinate; - varying highp vec2 topLeftTextureCoordinate; - varying highp vec2 topRightTextureCoordinate; - - varying highp vec2 bottomTextureCoordinate; - varying highp vec2 bottomLeftTextureCoordinate; - varying highp vec2 bottomRightTextureCoordinate; - - uniform lowp float threshold; - uniform highp float texelWidth; - uniform highp float texelHeight; - - highp float encodedIntensity(highp vec3 sourceColor) - { - return (sourceColor.b * 256.0 * 256.0 + sourceColor.g * 256.0 + sourceColor.r); - } - - void main() - { - highp float bottomColor = encodedIntensity(texture2D(inputImageTexture, bottomTextureCoordinate).rgb); - highp float bottomLeftColor = encodedIntensity(texture2D(inputImageTexture, bottomLeftTextureCoordinate).rgb); - highp float bottomRightColor = encodedIntensity(texture2D(inputImageTexture, bottomRightTextureCoordinate).rgb); - highp float centerColor = encodedIntensity(texture2D(inputImageTexture, textureCoordinate).rgb); - highp float leftColor = encodedIntensity(texture2D(inputImageTexture, leftTextureCoordinate).rgb); - highp float rightColor = encodedIntensity(texture2D(inputImageTexture, rightTextureCoordinate).rgb); - highp float topColor = encodedIntensity(texture2D(inputImageTexture, topTextureCoordinate).rgb); - highp float topRightColor = encodedIntensity(texture2D(inputImageTexture, topRightTextureCoordinate).rgb); - highp float topLeftColor = encodedIntensity(texture2D(inputImageTexture, topLeftTextureCoordinate).rgb); - - highp float secondStageColor1 = encodedIntensity(texture2D(inputImageTexture, textureCoordinate + vec2(-2.0 * texelWidth, -2.0 * texelHeight)).rgb); - highp float secondStageColor2 = encodedIntensity(texture2D(inputImageTexture, textureCoordinate + vec2(-2.0 * texelWidth, -1.0 * texelHeight)).rgb); - highp float secondStageColor3 = encodedIntensity(texture2D(inputImageTexture, textureCoordinate + vec2(-2.0 * texelWidth, 0.0)).rgb); - highp float secondStageColor4 = encodedIntensity(texture2D(inputImageTexture, textureCoordinate + vec2(-2.0 * texelWidth, 1.0 * texelHeight)).rgb); - highp float secondStageColor5 = encodedIntensity(texture2D(inputImageTexture, textureCoordinate + vec2(-2.0 * texelWidth, 2.0 * texelHeight)).rgb); - highp float secondStageColor6 = encodedIntensity(texture2D(inputImageTexture, textureCoordinate + vec2(-1.0 * texelWidth, 2.0 * texelHeight)).rgb); - highp float secondStageColor7 = encodedIntensity(texture2D(inputImageTexture, textureCoordinate + vec2(0.0, 2.0 * texelHeight)).rgb); - highp float secondStageColor8 = encodedIntensity(texture2D(inputImageTexture, textureCoordinate + vec2(1.0 * texelWidth, 2.0 * texelHeight)).rgb); - - highp float thirdStageColor1 = encodedIntensity(texture2D(inputImageTexture, textureCoordinate + vec2(-1.0 * texelWidth, -2.0 * texelHeight)).rgb); - highp float thirdStageColor2 = encodedIntensity(texture2D(inputImageTexture, textureCoordinate + vec2(0.0, -2.0 * texelHeight)).rgb); - highp float thirdStageColor3 = encodedIntensity(texture2D(inputImageTexture, textureCoordinate + vec2(1.0 * texelWidth, -2.0 * texelHeight)).rgb); - highp float thirdStageColor4 = encodedIntensity(texture2D(inputImageTexture, textureCoordinate + vec2(2.0 * texelWidth, -2.0 * texelHeight)).rgb); - highp float thirdStageColor5 = encodedIntensity(texture2D(inputImageTexture, textureCoordinate + vec2(2.0 * texelWidth, -1.0 * texelHeight)).rgb); - highp float thirdStageColor6 = encodedIntensity(texture2D(inputImageTexture, textureCoordinate + vec2(2.0 * texelWidth, 0.0)).rgb); - highp float thirdStageColor7 = encodedIntensity(texture2D(inputImageTexture, textureCoordinate + vec2(2.0 * texelWidth, 1.0 * texelHeight)).rgb); - highp float thirdStageColor8 = encodedIntensity(texture2D(inputImageTexture, textureCoordinate + vec2(2.0 * texelWidth, 2.0 * texelHeight)).rgb); - - // Use a tiebreaker for pixels to the left and immediately above this one - highp float multiplier = 1.0 - step(centerColor, topColor); - multiplier = multiplier * (1.0 - step(centerColor, topLeftColor)); - multiplier = multiplier * (1.0 - step(centerColor, leftColor)); - multiplier = multiplier * (1.0 - step(centerColor, bottomLeftColor)); - - multiplier = multiplier * (1.0 - step(centerColor, secondStageColor1)); - multiplier = multiplier * (1.0 - step(centerColor, secondStageColor2)); - multiplier = multiplier * (1.0 - step(centerColor, secondStageColor3)); - multiplier = multiplier * (1.0 - step(centerColor, secondStageColor4)); - multiplier = multiplier * (1.0 - step(centerColor, secondStageColor5)); - multiplier = multiplier * (1.0 - step(centerColor, secondStageColor6)); - multiplier = multiplier * (1.0 - step(centerColor, secondStageColor7)); - multiplier = multiplier * (1.0 - step(centerColor, secondStageColor8)); - - highp float maxValue = max(centerColor, bottomColor); - maxValue = max(maxValue, bottomRightColor); - maxValue = max(maxValue, rightColor); - maxValue = max(maxValue, topRightColor); - - maxValue = max(maxValue, thirdStageColor1); - maxValue = max(maxValue, thirdStageColor2); - maxValue = max(maxValue, thirdStageColor3); - maxValue = max(maxValue, thirdStageColor4); - maxValue = max(maxValue, thirdStageColor5); - maxValue = max(maxValue, thirdStageColor6); - maxValue = max(maxValue, thirdStageColor7); - maxValue = max(maxValue, thirdStageColor8); - - highp float midValue = centerColor * step(maxValue, centerColor) * multiplier; - highp float finalValue = step(threshold, midValue); - - gl_FragColor = vec4(finalValue * centerColor, topLeftColor, topRightColor, topColor); - } -); -#else -NSString *const kGPUImageThresholdedNonMaximumSuppressionFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform float threshold; - - void main() - { - float bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate).r; - float bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - float bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - vec4 centerColor = texture2D(inputImageTexture, textureCoordinate); - float leftColor = texture2D(inputImageTexture, leftTextureCoordinate).r; - float rightColor = texture2D(inputImageTexture, rightTextureCoordinate).r; - float topColor = texture2D(inputImageTexture, topTextureCoordinate).r; - float topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate).r; - float topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - - // Use a tiebreaker for pixels to the left and immediately above this one - float multiplier = 1.0 - step(centerColor.r, topColor); - multiplier = multiplier * (1.0 - step(centerColor.r, topLeftColor)); - multiplier = multiplier * (1.0 - step(centerColor.r, leftColor)); - multiplier = multiplier * (1.0 - step(centerColor.r, bottomLeftColor)); - - float maxValue = max(centerColor.r, bottomColor); - maxValue = max(maxValue, bottomRightColor); - maxValue = max(maxValue, rightColor); - maxValue = max(maxValue, topRightColor); - - float finalValue = centerColor.r * step(maxValue, centerColor.r) * multiplier; - finalValue = step(threshold, finalValue); - - gl_FragColor = vec4(finalValue, finalValue, finalValue, 1.0); - // - // gl_FragColor = vec4((centerColor.rgb * step(maxValue, step(threshold, centerColor.r)) * multiplier), 1.0); - } -); - -NSString *const kGPUImageThresholdedNonMaximumSuppressionPackedColorspaceFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform float threshold; - - void main() - { - float bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate).r; - float bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - float bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - vec4 centerColor = texture2D(inputImageTexture, textureCoordinate); - float leftColor = texture2D(inputImageTexture, leftTextureCoordinate).r; - float rightColor = texture2D(inputImageTexture, rightTextureCoordinate).r; - float topColor = texture2D(inputImageTexture, topTextureCoordinate).r; - float topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate).r; - float topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - - // Use a tiebreaker for pixels to the left and immediately above this one - float multiplier = 1.0 - step(centerColor.r, topColor); - multiplier = multiplier * (1.0 - step(centerColor.r, topLeftColor)); - multiplier = multiplier * (1.0 - step(centerColor.r, leftColor)); - multiplier = multiplier * (1.0 - step(centerColor.r, bottomLeftColor)); - - float maxValue = max(centerColor.r, bottomColor); - maxValue = max(maxValue, bottomRightColor); - maxValue = max(maxValue, rightColor); - maxValue = max(maxValue, topRightColor); - - float finalValue = centerColor.r * step(maxValue, centerColor.r) * multiplier; - finalValue = step(threshold, finalValue); - - gl_FragColor = vec4(finalValue, finalValue, finalValue, 1.0); - // - // gl_FragColor = vec4((centerColor.rgb * step(maxValue, step(threshold, centerColor.r)) * multiplier), 1.0); - } - ); -#endif - -@implementation GPUImageThresholdedNonMaximumSuppressionFilter - -@synthesize threshold = _threshold; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [self initWithPackedColorspace:NO])) - { - return nil; - } - - return self; -} - -- (id)initWithPackedColorspace:(BOOL)inputUsesPackedColorspace; -{ - NSString *shaderString; - if (inputUsesPackedColorspace) - { - shaderString = kGPUImageThresholdedNonMaximumSuppressionPackedColorspaceFragmentShaderString; - } - else - { - shaderString = kGPUImageThresholdedNonMaximumSuppressionFragmentShaderString; - } - - - if (!(self = [super initWithFragmentShaderFromString:shaderString])) - { - return nil; - } - - thresholdUniform = [filterProgram uniformIndex:@"threshold"]; - self.threshold = 0.9; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setThreshold:(CGFloat)newValue; -{ - _threshold = newValue; - - [self setFloat:_threshold forUniform:thresholdUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTiltShiftFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTiltShiftFilter.h deleted file mode 100755 index e41adee7..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTiltShiftFilter.h +++ /dev/null @@ -1,24 +0,0 @@ -#import "GPUImageFilterGroup.h" - -@class GPUImageGaussianBlurFilter; - -/// A simulated tilt shift lens effect -@interface GPUImageTiltShiftFilter : GPUImageFilterGroup -{ - GPUImageGaussianBlurFilter *blurFilter; - GPUImageFilter *tiltShiftFilter; -} - -/// The radius of the underlying blur, in pixels. This is 7.0 by default. -@property(readwrite, nonatomic) CGFloat blurRadiusInPixels; - -/// The normalized location of the top of the in-focus area in the image, this value should be lower than bottomFocusLevel, default 0.4 -@property(readwrite, nonatomic) CGFloat topFocusLevel; - -/// The normalized location of the bottom of the in-focus area in the image, this value should be higher than topFocusLevel, default 0.6 -@property(readwrite, nonatomic) CGFloat bottomFocusLevel; - -/// The rate at which the image gets blurry away from the in-focus region, default 0.2 -@property(readwrite, nonatomic) CGFloat focusFallOffRate; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTiltShiftFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTiltShiftFilter.m deleted file mode 100755 index e2f632b1..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTiltShiftFilter.m +++ /dev/null @@ -1,126 +0,0 @@ -#import "GPUImageTiltShiftFilter.h" -#import "GPUImageFilter.h" -#import "GPUImageTwoInputFilter.h" -#import "GPUImageGaussianBlurFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageTiltShiftFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - uniform highp float topFocusLevel; - uniform highp float bottomFocusLevel; - uniform highp float focusFallOffRate; - - void main() - { - lowp vec4 sharpImageColor = texture2D(inputImageTexture, textureCoordinate); - lowp vec4 blurredImageColor = texture2D(inputImageTexture2, textureCoordinate2); - - lowp float blurIntensity = 1.0 - smoothstep(topFocusLevel - focusFallOffRate, topFocusLevel, textureCoordinate2.y); - blurIntensity += smoothstep(bottomFocusLevel, bottomFocusLevel + focusFallOffRate, textureCoordinate2.y); - - gl_FragColor = mix(sharpImageColor, blurredImageColor, blurIntensity); - } -); -#else -NSString *const kGPUImageTiltShiftFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - uniform float topFocusLevel; - uniform float bottomFocusLevel; - uniform float focusFallOffRate; - - void main() - { - vec4 sharpImageColor = texture2D(inputImageTexture, textureCoordinate); - vec4 blurredImageColor = texture2D(inputImageTexture2, textureCoordinate2); - - float blurIntensity = 1.0 - smoothstep(topFocusLevel - focusFallOffRate, topFocusLevel, textureCoordinate2.y); - blurIntensity += smoothstep(bottomFocusLevel, bottomFocusLevel + focusFallOffRate, textureCoordinate2.y); - - gl_FragColor = mix(sharpImageColor, blurredImageColor, blurIntensity); - } -); -#endif - -@implementation GPUImageTiltShiftFilter - -@synthesize blurRadiusInPixels; -@synthesize topFocusLevel = _topFocusLevel; -@synthesize bottomFocusLevel = _bottomFocusLevel; -@synthesize focusFallOffRate = _focusFallOffRate; - -- (id)init; -{ - if (!(self = [super init])) - { - return nil; - } - - // First pass: apply a variable Gaussian blur - blurFilter = [[GPUImageGaussianBlurFilter alloc] init]; - [self addFilter:blurFilter]; - - // Second pass: combine the blurred image with the original sharp one - tiltShiftFilter = [[GPUImageTwoInputFilter alloc] initWithFragmentShaderFromString:kGPUImageTiltShiftFragmentShaderString]; - [self addFilter:tiltShiftFilter]; - - // Texture location 0 needs to be the sharp image for both the blur and the second stage processing - [blurFilter addTarget:tiltShiftFilter atTextureLocation:1]; - - // To prevent double updating of this filter, disable updates from the sharp image side -// self.inputFilterToIgnoreForUpdates = tiltShiftFilter; - - self.initialFilters = [NSArray arrayWithObjects:blurFilter, tiltShiftFilter, nil]; - self.terminalFilter = tiltShiftFilter; - - self.topFocusLevel = 0.4; - self.bottomFocusLevel = 0.6; - self.focusFallOffRate = 0.2; - self.blurRadiusInPixels = 7.0; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setBlurRadiusInPixels:(CGFloat)newValue; -{ - blurFilter.blurRadiusInPixels = newValue; -} - -- (CGFloat)blurRadiusInPixels; -{ - return blurFilter.blurRadiusInPixels; -} - -- (void)setTopFocusLevel:(CGFloat)newValue; -{ - _topFocusLevel = newValue; - [tiltShiftFilter setFloat:newValue forUniformName:@"topFocusLevel"]; -} - -- (void)setBottomFocusLevel:(CGFloat)newValue; -{ - _bottomFocusLevel = newValue; - [tiltShiftFilter setFloat:newValue forUniformName:@"bottomFocusLevel"]; -} - -- (void)setFocusFallOffRate:(CGFloat)newValue; -{ - _focusFallOffRate = newValue; - [tiltShiftFilter setFloat:newValue forUniformName:@"focusFallOffRate"]; -} - -@end \ No newline at end of file diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageToneCurveFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageToneCurveFilter.h deleted file mode 100755 index ff4ae92e..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageToneCurveFilter.h +++ /dev/null @@ -1,30 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageToneCurveFilter : GPUImageFilter - -@property(readwrite, nonatomic, copy) NSArray *redControlPoints; -@property(readwrite, nonatomic, copy) NSArray *greenControlPoints; -@property(readwrite, nonatomic, copy) NSArray *blueControlPoints; -@property(readwrite, nonatomic, copy) NSArray *rgbCompositeControlPoints; - -// Initialization and teardown -- (id)initWithACVData:(NSData*)data; - -- (id)initWithACV:(NSString*)curveFilename; -- (id)initWithACVURL:(NSURL*)curveFileURL; - -// This lets you set all three red, green, and blue tone curves at once. -// NOTE: Deprecated this function because this effect can be accomplished -// using the rgbComposite channel rather then setting all 3 R, G, and B channels. -- (void)setRGBControlPoints:(NSArray *)points DEPRECATED_ATTRIBUTE; - -- (void)setPointsWithACV:(NSString*)curveFilename; -- (void)setPointsWithACVURL:(NSURL*)curveFileURL; - -// Curve calculation -- (NSMutableArray *)getPreparedSplineCurve:(NSArray *)points; -- (NSMutableArray *)splineCurve:(NSArray *)points; -- (NSMutableArray *)secondDerivative:(NSArray *)cgPoints; -- (void)updateToneCurveTexture; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageToneCurveFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageToneCurveFilter.m deleted file mode 100644 index 18a717e0..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageToneCurveFilter.m +++ /dev/null @@ -1,621 +0,0 @@ -#import "GPUImageToneCurveFilter.h" - -#pragma mark - -#pragma mark GPUImageACVFile Helper - -// GPUImageACVFile -// -// ACV File format Parser -// Please refer to http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/PhotoshopFileFormats.htm#50577411_pgfId-1056330 -// - -@interface GPUImageACVFile : NSObject{ - short version; - short totalCurves; - - NSArray *rgbCompositeCurvePoints; - NSArray *redCurvePoints; - NSArray *greenCurvePoints; - NSArray *blueCurvePoints; -} - -@property(strong,nonatomic) NSArray *rgbCompositeCurvePoints; -@property(strong,nonatomic) NSArray *redCurvePoints; -@property(strong,nonatomic) NSArray *greenCurvePoints; -@property(strong,nonatomic) NSArray *blueCurvePoints; - -- (id) initWithACVFileData:(NSData*)data; - - -unsigned short int16WithBytes(Byte* bytes); -@end - -@implementation GPUImageACVFile - -@synthesize rgbCompositeCurvePoints, redCurvePoints, greenCurvePoints, blueCurvePoints; - -- (id) initWithACVFileData:(NSData *)data { - self = [super init]; - if (self != nil) - { - if (data.length == 0) - { - NSLog(@"failed to init ACVFile with data:%@", data); - - return self; - } - - Byte* rawBytes = (Byte*) [data bytes]; - version = int16WithBytes(rawBytes); - rawBytes+=2; - - totalCurves = int16WithBytes(rawBytes); - rawBytes+=2; - - NSMutableArray *curves = [NSMutableArray new]; - - float pointRate = (1.0 / 255); - // The following is the data for each curve specified by count above - for (NSInteger x = 0; x 0) - { - // Sort the array. - NSArray *sortedPoints = [points sortedArrayUsingComparator:^NSComparisonResult(id a, id b) { -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - float x1 = [(NSValue *)a CGPointValue].x; - float x2 = [(NSValue *)b CGPointValue].x; -#else - float x1 = [(NSValue *)a pointValue].x; - float x2 = [(NSValue *)b pointValue].x; -#endif - return x1 > x2; - }]; - - // Convert from (0, 1) to (0, 255). - NSMutableArray *convertedPoints = [NSMutableArray arrayWithCapacity:[sortedPoints count]]; - for (int i=0; i<[points count]; i++){ -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - CGPoint point = [[sortedPoints objectAtIndex:i] CGPointValue]; -#else - NSPoint point = [[sortedPoints objectAtIndex:i] pointValue]; -#endif - point.x = point.x * 255; - point.y = point.y * 255; - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - [convertedPoints addObject:[NSValue valueWithCGPoint:point]]; -#else - [convertedPoints addObject:[NSValue valueWithPoint:point]]; -#endif - } - - - NSMutableArray *splinePoints = [self splineCurve:convertedPoints]; - - // If we have a first point like (0.3, 0) we'll be missing some points at the beginning - // that should be 0. -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - CGPoint firstSplinePoint = [[splinePoints objectAtIndex:0] CGPointValue]; -#else - NSPoint firstSplinePoint = [[splinePoints objectAtIndex:0] pointValue]; -#endif - - if (firstSplinePoint.x > 0) { - for (int i=firstSplinePoint.x; i >= 0; i--) { -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - CGPoint newCGPoint = CGPointMake(i, 0); - [splinePoints insertObject:[NSValue valueWithCGPoint:newCGPoint] atIndex:0]; -#else - NSPoint newNSPoint = NSMakePoint(i, 0); - [splinePoints insertObject:[NSValue valueWithPoint:newNSPoint] atIndex:0]; -#endif - } - } - - // Insert points similarly at the end, if necessary. -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - CGPoint lastSplinePoint = [[splinePoints lastObject] CGPointValue]; - - if (lastSplinePoint.x < 255) { - for (int i = lastSplinePoint.x + 1; i <= 255; i++) { - CGPoint newCGPoint = CGPointMake(i, 255); - [splinePoints addObject:[NSValue valueWithCGPoint:newCGPoint]]; - } - } -#else - NSPoint lastSplinePoint = [[splinePoints lastObject] pointValue]; - - if (lastSplinePoint.x < 255) { - for (int i = lastSplinePoint.x + 1; i <= 255; i++) { - NSPoint newNSPoint = NSMakePoint(i, 255); - [splinePoints addObject:[NSValue valueWithPoint:newNSPoint]]; - } - } -#endif - - // Prepare the spline points. - NSMutableArray *preparedSplinePoints = [NSMutableArray arrayWithCapacity:[splinePoints count]]; - for (int i=0; i<[splinePoints count]; i++) - { -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - CGPoint newPoint = [[splinePoints objectAtIndex:i] CGPointValue]; -#else - NSPoint newPoint = [[splinePoints objectAtIndex:i] pointValue]; -#endif - CGPoint origPoint = CGPointMake(newPoint.x, newPoint.x); - - float distance = sqrt(pow((origPoint.x - newPoint.x), 2.0) + pow((origPoint.y - newPoint.y), 2.0)); - - if (origPoint.y > newPoint.y) - { - distance = -distance; - } - - [preparedSplinePoints addObject:[NSNumber numberWithFloat:distance]]; - } - - return preparedSplinePoints; - } - - return nil; -} - - -- (NSMutableArray *)splineCurve:(NSArray *)points -{ - NSMutableArray *sdA = [self secondDerivative:points]; - - // [points count] is equal to [sdA count] - NSInteger n = [sdA count]; - if (n < 1) - { - return nil; - } - double sd[n]; - - // From NSMutableArray to sd[n]; - for (int i=0; i 255.0) - { - y = 255.0; - } - else if (y < 0.0) - { - y = 0.0; - } -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE - [output addObject:[NSValue valueWithCGPoint:CGPointMake(x, y)]]; -#else - [output addObject:[NSValue valueWithPoint:NSMakePoint(x, y)]]; -#endif - } - } - - // The above always misses the last point because the last point is the last next, so we approach but don't equal it. - [output addObject:[points lastObject]]; - return output; -} - -- (NSMutableArray *)secondDerivative:(NSArray *)points -{ - const NSInteger n = [points count]; - if ((n <= 0) || (n == 1)) - { - return nil; - } - - double matrix[n][3]; - double result[n]; - matrix[0][1]=1; - // What about matrix[0][1] and matrix[0][0]? Assuming 0 for now (Brad L.) - matrix[0][0]=0; - matrix[0][2]=0; - - for(int i=1;idown) - for(int i=1;iup) - for(NSInteger i=n-2;i>=0;i--) - { - double k = matrix[i][2]/matrix[i+1][1]; - matrix[i][1] -= k*matrix[i+1][0]; - matrix[i][2] = 0; - result[i] -= k*result[i+1]; - } - - double y2[n]; - for(int i=0;i= 256) && ([_greenCurve count] >= 256) && ([_blueCurve count] >= 256) && ([_rgbCompositeCurve count] >= 256)) - { - for (unsigned int currentCurveIndex = 0; currentCurveIndex < 256; currentCurveIndex++) - { - // BGRA for upload to texture - GLubyte b = fmin(fmax(currentCurveIndex + [[_blueCurve objectAtIndex:currentCurveIndex] floatValue], 0), 255); - toneCurveByteArray[currentCurveIndex * 4] = fmin(fmax(b + [[_rgbCompositeCurve objectAtIndex:b] floatValue], 0), 255); - GLubyte g = fmin(fmax(currentCurveIndex + [[_greenCurve objectAtIndex:currentCurveIndex] floatValue], 0), 255); - toneCurveByteArray[currentCurveIndex * 4 + 1] = fmin(fmax(g + [[_rgbCompositeCurve objectAtIndex:g] floatValue], 0), 255); - GLubyte r = fmin(fmax(currentCurveIndex + [[_redCurve objectAtIndex:currentCurveIndex] floatValue], 0), 255); - toneCurveByteArray[currentCurveIndex * 4 + 2] = fmin(fmax(r + [[_rgbCompositeCurve objectAtIndex:r] floatValue], 0), 255); - toneCurveByteArray[currentCurveIndex * 4 + 3] = 255; - } - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256 /*width*/, 1 /*height*/, 0, GL_BGRA, GL_UNSIGNED_BYTE, toneCurveByteArray); - } - }); -} - -#pragma mark - -#pragma mark Rendering - -- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates; -{ - if (self.preventRendering) - { - [firstInputFramebuffer unlock]; - return; - } - - [GPUImageContext setActiveShaderProgram:filterProgram]; - outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:[self sizeOfFBO] textureOptions:self.outputTextureOptions onlyTexture:NO]; - [outputFramebuffer activateFramebuffer]; - if (usingNextFrameForImageCapture) - { - [outputFramebuffer lock]; - } - - glClearColor(backgroundColorRed, backgroundColorGreen, backgroundColorBlue, backgroundColorAlpha); - glClear(GL_COLOR_BUFFER_BIT); - - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, [firstInputFramebuffer texture]); - glUniform1i(filterInputTextureUniform, 2); - - glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D, toneCurveTexture); - glUniform1i(toneCurveTextureUniform, 3); - - glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, vertices); - glVertexAttribPointer(filterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - [firstInputFramebuffer unlock]; - if (usingNextFrameForImageCapture) - { - dispatch_semaphore_signal(imageCaptureSemaphore); - } -} - -#pragma mark - -#pragma mark Accessors - -- (void)setRGBControlPoints:(NSArray *)points -{ - _redControlPoints = [points copy]; - _redCurve = [self getPreparedSplineCurve:_redControlPoints]; - - _greenControlPoints = [points copy]; - _greenCurve = [self getPreparedSplineCurve:_greenControlPoints]; - - _blueControlPoints = [points copy]; - _blueCurve = [self getPreparedSplineCurve:_blueControlPoints]; - - [self updateToneCurveTexture]; -} - - -- (void)setRgbCompositeControlPoints:(NSArray *)newValue -{ - _rgbCompositeControlPoints = [newValue copy]; - _rgbCompositeCurve = [self getPreparedSplineCurve:_rgbCompositeControlPoints]; - - [self updateToneCurveTexture]; -} - - -- (void)setRedControlPoints:(NSArray *)newValue; -{ - _redControlPoints = [newValue copy]; - _redCurve = [self getPreparedSplineCurve:_redControlPoints]; - - [self updateToneCurveTexture]; -} - - -- (void)setGreenControlPoints:(NSArray *)newValue -{ - _greenControlPoints = [newValue copy]; - _greenCurve = [self getPreparedSplineCurve:_greenControlPoints]; - - [self updateToneCurveTexture]; -} - - -- (void)setBlueControlPoints:(NSArray *)newValue -{ - _blueControlPoints = [newValue copy]; - _blueCurve = [self getPreparedSplineCurve:_blueControlPoints]; - - [self updateToneCurveTexture]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageToonFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageToonFilter.h deleted file mode 100755 index ef8e17c3..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageToonFilter.h +++ /dev/null @@ -1,19 +0,0 @@ -#import "GPUImage3x3TextureSamplingFilter.h" - -/** This uses Sobel edge detection to place a black border around objects, - and then it quantizes the colors present in the image to give a cartoon-like quality to the image. - */ -@interface GPUImageToonFilter : GPUImage3x3TextureSamplingFilter -{ - GLint thresholdUniform, quantizationLevelsUniform; -} - -/** The threshold at which to apply the edges, default of 0.2 - */ -@property(readwrite, nonatomic) CGFloat threshold; - -/** The levels of quantization for the posterization of colors within the scene, with a default of 10.0 - */ -@property(readwrite, nonatomic) CGFloat quantizationLevels; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageToonFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageToonFilter.m deleted file mode 100755 index e8ff104e..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageToonFilter.m +++ /dev/null @@ -1,149 +0,0 @@ -#import "GPUImageToonFilter.h" -#import "GPUImageSobelEdgeDetectionFilter.h" -#import "GPUImage3x3ConvolutionFilter.h" - -// Code from "Graphics Shaders: Theory and Practice" by M. Bailey and S. Cunningham -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageToonFragmentShaderString = SHADER_STRING -( - precision highp float; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform highp float intensity; - uniform highp float threshold; - uniform highp float quantizationLevels; - - const highp vec3 W = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r; - float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r; - float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r; - float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r; - float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r; - float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity; - float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity; - - float mag = length(vec2(h, v)); - - vec3 posterizedImageColor = floor((textureColor.rgb * quantizationLevels) + 0.5) / quantizationLevels; - - float thresholdTest = 1.0 - step(threshold, mag); - - gl_FragColor = vec4(posterizedImageColor * thresholdTest, textureColor.a); - } -); -#else -NSString *const kGPUImageToonFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform float intensity; - uniform float threshold; - uniform float quantizationLevels; - - const vec3 W = vec3(0.2125, 0.7154, 0.0721); - - void main() - { - vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); - - float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r; - float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r; - float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r; - float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r; - float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r; - float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity; - float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity; - - float mag = length(vec2(h, v)); - - vec3 posterizedImageColor = floor((textureColor.rgb * quantizationLevels) + 0.5) / quantizationLevels; - - float thresholdTest = 1.0 - step(threshold, mag); - - gl_FragColor = vec4(posterizedImageColor * thresholdTest, textureColor.a); - } -); -#endif - -@implementation GPUImageToonFilter - -@synthesize threshold = _threshold; -@synthesize quantizationLevels = _quantizationLevels; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageToonFragmentShaderString])) - { - return nil; - } - - hasOverriddenImageSizeFactor = NO; - - thresholdUniform = [filterProgram uniformIndex:@"threshold"]; - quantizationLevelsUniform = [filterProgram uniformIndex:@"quantizationLevels"]; - - self.threshold = 0.2; - self.quantizationLevels = 10.0; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setThreshold:(CGFloat)newValue; -{ - _threshold = newValue; - - [self setFloat:_threshold forUniform:thresholdUniform program:filterProgram]; -} - -- (void)setQuantizationLevels:(CGFloat)newValue; -{ - _quantizationLevels = newValue; - - [self setFloat:_quantizationLevels forUniform:quantizationLevelsUniform program:filterProgram]; -} - - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTransformFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTransformFilter.h deleted file mode 100755 index 9865b853..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTransformFilter.h +++ /dev/null @@ -1,19 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageTransformFilter : GPUImageFilter -{ - GLint transformMatrixUniform, orthographicMatrixUniform; - GPUMatrix4x4 orthographicMatrix; -} - -// You can either set the transform to apply to be a 2-D affine transform or a 3-D transform. The default is the identity transform (the output image is identical to the input). -@property(readwrite, nonatomic) CGAffineTransform affineTransform; -@property(readwrite, nonatomic) CATransform3D transform3D; - -// This applies the transform to the raw frame data if set to YES, the default of NO takes the aspect ratio of the image input into account when rotating -@property(readwrite, nonatomic) BOOL ignoreAspectRatio; - -// sets the anchor point to top left corner -@property(readwrite, nonatomic) BOOL anchorTopLeft; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTransformFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTransformFilter.m deleted file mode 100755 index 17933092..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTransformFilter.m +++ /dev/null @@ -1,260 +0,0 @@ -#import "GPUImageTransformFilter.h" - -NSString *const kGPUImageTransformVertexShaderString = SHADER_STRING -( - attribute vec4 position; - attribute vec4 inputTextureCoordinate; - - uniform mat4 transformMatrix; - uniform mat4 orthographicMatrix; - - varying vec2 textureCoordinate; - - void main() - { - gl_Position = transformMatrix * vec4(position.xyz, 1.0) * orthographicMatrix; - textureCoordinate = inputTextureCoordinate.xy; - } -); - -@implementation GPUImageTransformFilter - -@synthesize affineTransform; -@synthesize transform3D = _transform3D; -@synthesize ignoreAspectRatio = _ignoreAspectRatio; -@synthesize anchorTopLeft = _anchorTopLeft; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithVertexShaderFromString:kGPUImageTransformVertexShaderString fragmentShaderFromString:kGPUImagePassthroughFragmentShaderString])) - { - return nil; - } - - transformMatrixUniform = [filterProgram uniformIndex:@"transformMatrix"]; - orthographicMatrixUniform = [filterProgram uniformIndex:@"orthographicMatrix"]; - - self.transform3D = CATransform3DIdentity; - - return self; -} - -#pragma mark - -#pragma mark Conversion from matrix formats - -- (void)loadOrthoMatrix:(GLfloat *)matrix left:(GLfloat)left right:(GLfloat)right bottom:(GLfloat)bottom top:(GLfloat)top near:(GLfloat)near far:(GLfloat)far; -{ - GLfloat r_l = right - left; - GLfloat t_b = top - bottom; - GLfloat f_n = far - near; - GLfloat tx = - (right + left) / (right - left); - GLfloat ty = - (top + bottom) / (top - bottom); - GLfloat tz = - (far + near) / (far - near); - - float scale = 2.0f; - if (_anchorTopLeft) - { - scale = 4.0f; - tx=-1.0f; - ty=-1.0f; - } - - matrix[0] = scale / r_l; - matrix[1] = 0.0f; - matrix[2] = 0.0f; - matrix[3] = tx; - - matrix[4] = 0.0f; - matrix[5] = scale / t_b; - matrix[6] = 0.0f; - matrix[7] = ty; - - matrix[8] = 0.0f; - matrix[9] = 0.0f; - matrix[10] = scale / f_n; - matrix[11] = tz; - - matrix[12] = 0.0f; - matrix[13] = 0.0f; - matrix[14] = 0.0f; - matrix[15] = 1.0f; -} - -//- (void)convert3DTransform:(CATransform3D *)transform3D toMatrix:(GLfloat *)matrix; -//{ -// // struct CATransform3D -// // { -// // CGFloat m11, m12, m13, m14; -// // CGFloat m21, m22, m23, m24; -// // CGFloat m31, m32, m33, m34; -// // CGFloat m41, m42, m43, m44; -// // }; -// -// matrix[0] = (GLfloat)transform3D->m11; -// matrix[1] = (GLfloat)transform3D->m12; -// matrix[2] = (GLfloat)transform3D->m13; -// matrix[3] = (GLfloat)transform3D->m14; -// matrix[4] = (GLfloat)transform3D->m21; -// matrix[5] = (GLfloat)transform3D->m22; -// matrix[6] = (GLfloat)transform3D->m23; -// matrix[7] = (GLfloat)transform3D->m24; -// matrix[8] = (GLfloat)transform3D->m31; -// matrix[9] = (GLfloat)transform3D->m32; -// matrix[10] = (GLfloat)transform3D->m33; -// matrix[11] = (GLfloat)transform3D->m34; -// matrix[12] = (GLfloat)transform3D->m41; -// matrix[13] = (GLfloat)transform3D->m42; -// matrix[14] = (GLfloat)transform3D->m43; -// matrix[15] = (GLfloat)transform3D->m44; -//} - -- (void)convert3DTransform:(CATransform3D *)transform3D toMatrix:(GPUMatrix4x4 *)matrix; -{ - // struct CATransform3D - // { - // CGFloat m11, m12, m13, m14; - // CGFloat m21, m22, m23, m24; - // CGFloat m31, m32, m33, m34; - // CGFloat m41, m42, m43, m44; - // }; - - GLfloat *mappedMatrix = (GLfloat *)matrix; - - mappedMatrix[0] = (GLfloat)transform3D->m11; - mappedMatrix[1] = (GLfloat)transform3D->m12; - mappedMatrix[2] = (GLfloat)transform3D->m13; - mappedMatrix[3] = (GLfloat)transform3D->m14; - mappedMatrix[4] = (GLfloat)transform3D->m21; - mappedMatrix[5] = (GLfloat)transform3D->m22; - mappedMatrix[6] = (GLfloat)transform3D->m23; - mappedMatrix[7] = (GLfloat)transform3D->m24; - mappedMatrix[8] = (GLfloat)transform3D->m31; - mappedMatrix[9] = (GLfloat)transform3D->m32; - mappedMatrix[10] = (GLfloat)transform3D->m33; - mappedMatrix[11] = (GLfloat)transform3D->m34; - mappedMatrix[12] = (GLfloat)transform3D->m41; - mappedMatrix[13] = (GLfloat)transform3D->m42; - mappedMatrix[14] = (GLfloat)transform3D->m43; - mappedMatrix[15] = (GLfloat)transform3D->m44; -} - -#pragma mark - -#pragma mark GPUImageInput - -- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex; -{ - CGSize currentFBOSize = [self sizeOfFBO]; - CGFloat normalizedHeight = currentFBOSize.height / currentFBOSize.width; - - GLfloat adjustedVertices[] = { - -1.0f, -normalizedHeight, - 1.0f, -normalizedHeight, - -1.0f, normalizedHeight, - 1.0f, normalizedHeight, - }; - static const GLfloat squareVertices[] = { - -1.0f, -1.0f, - 1.0f, -1.0f, - -1.0f, 1.0f, - 1.0f, 1.0f, - }; - - GLfloat adjustedVerticesAnchorTL[] = { - 0.0f, 0.0f, - 1.0f, 0.0f, - 0.0f, normalizedHeight, - 1.0f, normalizedHeight, - }; - - static const GLfloat squareVerticesAnchorTL[] = { - 0.0f, 0.0f, - 1.0f, 0.0f, - 0.0f, 1.0f, - 1.0f, 1.0f, - }; - - if (_ignoreAspectRatio) - { - if (_anchorTopLeft) - { - [self renderToTextureWithVertices:squareVerticesAnchorTL textureCoordinates:[[self class] textureCoordinatesForRotation:inputRotation]]; - } - else - { - [self renderToTextureWithVertices:squareVertices textureCoordinates:[[self class] textureCoordinatesForRotation:inputRotation]]; - } - } - else - { - if (_anchorTopLeft) - { - [self renderToTextureWithVertices:adjustedVerticesAnchorTL textureCoordinates:[[self class] textureCoordinatesForRotation:inputRotation]]; - } - else - { - [self renderToTextureWithVertices:adjustedVertices textureCoordinates:[[self class] textureCoordinatesForRotation:inputRotation]]; - } - } - - [self informTargetsAboutNewFrameAtTime:frameTime]; -} - -- (void)setupFilterForSize:(CGSize)filterFrameSize; -{ - if (!_ignoreAspectRatio) - { - [self loadOrthoMatrix:(GLfloat *)&orthographicMatrix left:-1.0 right:1.0 bottom:(-1.0 * filterFrameSize.height / filterFrameSize.width) top:(1.0 * filterFrameSize.height / filterFrameSize.width) near:-1.0 far:1.0]; - // [self loadOrthoMatrix:orthographicMatrix left:-1.0 right:1.0 bottom:(-1.0 * (GLfloat)backingHeight / (GLfloat)backingWidth) top:(1.0 * (GLfloat)backingHeight / (GLfloat)backingWidth) near:-2.0 far:2.0]; - - [self setMatrix4f:orthographicMatrix forUniform:orthographicMatrixUniform program:filterProgram]; - } -} - -#pragma mark - -#pragma mark Accessors - -- (void)setAffineTransform:(CGAffineTransform)newValue; -{ - self.transform3D = CATransform3DMakeAffineTransform(newValue); -} - -- (CGAffineTransform)affineTransform; -{ - return CATransform3DGetAffineTransform(self.transform3D); -} - -- (void)setTransform3D:(CATransform3D)newValue; -{ - _transform3D = newValue; - - GPUMatrix4x4 temporaryMatrix; - - [self convert3DTransform:&_transform3D toMatrix:&temporaryMatrix]; - [self setMatrix4f:temporaryMatrix forUniform:transformMatrixUniform program:filterProgram]; -} - -- (void)setIgnoreAspectRatio:(BOOL)newValue; -{ - _ignoreAspectRatio = newValue; - - if (_ignoreAspectRatio) - { - [self loadOrthoMatrix:(GLfloat *)&orthographicMatrix left:-1.0 right:1.0 bottom:-1.0 top:1.0 near:-1.0 far:1.0]; - [self setMatrix4f:orthographicMatrix forUniform:orthographicMatrixUniform program:filterProgram]; - } - else - { - [self setupFilterForSize:[self sizeOfFBO]]; - } -} - -- (void)setAnchorTopLeft:(BOOL)newValue -{ - _anchorTopLeft = newValue; - [self setIgnoreAspectRatio:_ignoreAspectRatio]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoInputCrossTextureSamplingFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoInputCrossTextureSamplingFilter.h deleted file mode 100644 index 64eac9dc..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoInputCrossTextureSamplingFilter.h +++ /dev/null @@ -1,15 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageTwoInputCrossTextureSamplingFilter : GPUImageTwoInputFilter -{ - GLint texelWidthUniform, texelHeightUniform; - - CGFloat texelWidth, texelHeight; - BOOL hasOverriddenImageSizeFactor; -} - -// The texel width and height determines how far out to sample from this texel. By default, this is the normalized width of a pixel, but this can be overridden for different effects. -@property(readwrite, nonatomic) CGFloat texelWidth; -@property(readwrite, nonatomic) CGFloat texelHeight; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoInputCrossTextureSamplingFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoInputCrossTextureSamplingFilter.m deleted file mode 100644 index aa338f81..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoInputCrossTextureSamplingFilter.m +++ /dev/null @@ -1,108 +0,0 @@ -#import "GPUImageTwoInputCrossTextureSamplingFilter.h" - -NSString *const kGPUImageTwoInputNearbyTexelSamplingVertexShaderString = SHADER_STRING -( - attribute vec4 position; - attribute vec4 inputTextureCoordinate; - attribute vec4 inputTextureCoordinate2; - - uniform float texelWidth; - uniform float texelHeight; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - varying vec2 topTextureCoordinate; - varying vec2 bottomTextureCoordinate; - - varying vec2 textureCoordinate2; - varying vec2 leftTextureCoordinate2; - varying vec2 rightTextureCoordinate2; - varying vec2 topTextureCoordinate2; - varying vec2 bottomTextureCoordinate2; - - void main() - { - gl_Position = position; - - vec2 widthStep = vec2(texelWidth, 0.0); - vec2 heightStep = vec2(0.0, texelHeight); - - textureCoordinate = inputTextureCoordinate.xy; - leftTextureCoordinate = inputTextureCoordinate.xy - widthStep; - rightTextureCoordinate = inputTextureCoordinate.xy + widthStep; - topTextureCoordinate = inputTextureCoordinate.xy - heightStep; - bottomTextureCoordinate = inputTextureCoordinate.xy + heightStep; - - textureCoordinate2 = inputTextureCoordinate2.xy; - leftTextureCoordinate2 = inputTextureCoordinate2.xy - widthStep; - rightTextureCoordinate2 = inputTextureCoordinate2.xy + widthStep; - topTextureCoordinate2 = inputTextureCoordinate2.xy - heightStep; - bottomTextureCoordinate2 = inputTextureCoordinate2.xy + heightStep; - } -); - -@implementation GPUImageTwoInputCrossTextureSamplingFilter - -@synthesize texelWidth = _texelWidth; -@synthesize texelHeight = _texelHeight; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithFragmentShaderFromString:(NSString *)fragmentShaderString; -{ - if (!(self = [super initWithVertexShaderFromString:kGPUImageTwoInputNearbyTexelSamplingVertexShaderString fragmentShaderFromString:fragmentShaderString])) - { - return nil; - } - - texelWidthUniform = [filterProgram uniformIndex:@"texelWidth"]; - texelHeightUniform = [filterProgram uniformIndex:@"texelHeight"]; - - return self; -} - -- (void)setupFilterForSize:(CGSize)filterFrameSize; -{ - if (!hasOverriddenImageSizeFactor) - { - _texelWidth = 1.0 / filterFrameSize.width; - _texelHeight = 1.0 / filterFrameSize.height; - - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext setActiveShaderProgram:filterProgram]; - if (GPUImageRotationSwapsWidthAndHeight(inputRotation)) - { - glUniform1f(texelWidthUniform, _texelHeight); - glUniform1f(texelHeightUniform, _texelWidth); - } - else - { - glUniform1f(texelWidthUniform, _texelWidth); - glUniform1f(texelHeightUniform, _texelHeight); - } - }); - } -} - -#pragma mark - -#pragma mark Accessors - -- (void)setTexelWidth:(CGFloat)newValue; -{ - hasOverriddenImageSizeFactor = YES; - _texelWidth = newValue; - - [self setFloat:_texelWidth forUniform:texelWidthUniform program:filterProgram]; -} - -- (void)setTexelHeight:(CGFloat)newValue; -{ - hasOverriddenImageSizeFactor = YES; - _texelHeight = newValue; - - [self setFloat:_texelHeight forUniform:texelHeightUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoInputFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoInputFilter.h deleted file mode 100644 index da3a1345..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoInputFilter.h +++ /dev/null @@ -1,21 +0,0 @@ -#import "GPUImageFilter.h" - -extern NSString *const kGPUImageTwoInputTextureVertexShaderString; - -@interface GPUImageTwoInputFilter : GPUImageFilter -{ - GPUImageFramebuffer *secondInputFramebuffer; - - GLint filterSecondTextureCoordinateAttribute; - GLint filterInputTextureUniform2; - GPUImageRotationMode inputRotation2; - CMTime firstFrameTime, secondFrameTime; - - BOOL hasSetFirstTexture, hasReceivedFirstFrame, hasReceivedSecondFrame, firstFrameWasVideo, secondFrameWasVideo; - BOOL firstFrameCheckDisabled, secondFrameCheckDisabled; -} - -- (void)disableFirstFrameCheck; -- (void)disableSecondFrameCheck; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoInputFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoInputFilter.m deleted file mode 100644 index cf318737..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoInputFilter.m +++ /dev/null @@ -1,264 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -NSString *const kGPUImageTwoInputTextureVertexShaderString = SHADER_STRING -( - attribute vec4 position; - attribute vec4 inputTextureCoordinate; - attribute vec4 inputTextureCoordinate2; - - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - void main() - { - gl_Position = position; - textureCoordinate = inputTextureCoordinate.xy; - textureCoordinate2 = inputTextureCoordinate2.xy; - } -); - - -@implementation GPUImageTwoInputFilter - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithFragmentShaderFromString:(NSString *)fragmentShaderString; -{ - if (!(self = [self initWithVertexShaderFromString:kGPUImageTwoInputTextureVertexShaderString fragmentShaderFromString:fragmentShaderString])) - { - return nil; - } - - return self; -} - -- (id)initWithVertexShaderFromString:(NSString *)vertexShaderString fragmentShaderFromString:(NSString *)fragmentShaderString; -{ - if (!(self = [super initWithVertexShaderFromString:vertexShaderString fragmentShaderFromString:fragmentShaderString])) - { - return nil; - } - - inputRotation2 = kGPUImageNoRotation; - - hasSetFirstTexture = NO; - - hasReceivedFirstFrame = NO; - hasReceivedSecondFrame = NO; - firstFrameWasVideo = NO; - secondFrameWasVideo = NO; - firstFrameCheckDisabled = NO; - secondFrameCheckDisabled = NO; - - firstFrameTime = kCMTimeInvalid; - secondFrameTime = kCMTimeInvalid; - - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext useImageProcessingContext]; - filterSecondTextureCoordinateAttribute = [filterProgram attributeIndex:@"inputTextureCoordinate2"]; - - filterInputTextureUniform2 = [filterProgram uniformIndex:@"inputImageTexture2"]; // This does assume a name of "inputImageTexture2" for second input texture in the fragment shader - glEnableVertexAttribArray(filterSecondTextureCoordinateAttribute); - }); - - return self; -} - -- (void)initializeAttributes; -{ - [super initializeAttributes]; - [filterProgram addAttribute:@"inputTextureCoordinate2"]; -} - -- (void)disableFirstFrameCheck; -{ - firstFrameCheckDisabled = YES; -} - -- (void)disableSecondFrameCheck; -{ - secondFrameCheckDisabled = YES; -} - -#pragma mark - -#pragma mark Rendering - -- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates; -{ - if (self.preventRendering) - { - [firstInputFramebuffer unlock]; - [secondInputFramebuffer unlock]; - return; - } - - [GPUImageContext setActiveShaderProgram:filterProgram]; - outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:[self sizeOfFBO] textureOptions:self.outputTextureOptions onlyTexture:NO]; - [outputFramebuffer activateFramebuffer]; - if (usingNextFrameForImageCapture) - { - [outputFramebuffer lock]; - } - - [self setUniformsForProgramAtIndex:0]; - - glClearColor(backgroundColorRed, backgroundColorGreen, backgroundColorBlue, backgroundColorAlpha); - glClear(GL_COLOR_BUFFER_BIT); - - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, [firstInputFramebuffer texture]); - glUniform1i(filterInputTextureUniform, 2); - - glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D, [secondInputFramebuffer texture]); - glUniform1i(filterInputTextureUniform2, 3); - - glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, vertices); - glVertexAttribPointer(filterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates); - glVertexAttribPointer(filterSecondTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, [[self class] textureCoordinatesForRotation:inputRotation2]); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - [firstInputFramebuffer unlock]; - [secondInputFramebuffer unlock]; - if (usingNextFrameForImageCapture) - { - dispatch_semaphore_signal(imageCaptureSemaphore); - } -} - -#pragma mark - -#pragma mark GPUImageInput - -- (NSInteger)nextAvailableTextureIndex; -{ - if (hasSetFirstTexture) - { - return 1; - } - else - { - return 0; - } -} - -- (void)setInputFramebuffer:(GPUImageFramebuffer *)newInputFramebuffer atIndex:(NSInteger)textureIndex; -{ - if (textureIndex == 0) - { - firstInputFramebuffer = newInputFramebuffer; - hasSetFirstTexture = YES; - [firstInputFramebuffer lock]; - } - else - { - secondInputFramebuffer = newInputFramebuffer; - [secondInputFramebuffer lock]; - } -} - -- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex; -{ - if (textureIndex == 0) - { - [super setInputSize:newSize atIndex:textureIndex]; - - if (CGSizeEqualToSize(newSize, CGSizeZero)) - { - hasSetFirstTexture = NO; - } - } -} - -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -{ - if (textureIndex == 0) - { - inputRotation = newInputRotation; - } - else - { - inputRotation2 = newInputRotation; - } -} - -- (CGSize)rotatedSize:(CGSize)sizeToRotate forIndex:(NSInteger)textureIndex; -{ - CGSize rotatedSize = sizeToRotate; - - GPUImageRotationMode rotationToCheck; - if (textureIndex == 0) - { - rotationToCheck = inputRotation; - } - else - { - rotationToCheck = inputRotation2; - } - - if (GPUImageRotationSwapsWidthAndHeight(rotationToCheck)) - { - rotatedSize.width = sizeToRotate.height; - rotatedSize.height = sizeToRotate.width; - } - - return rotatedSize; -} - -- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex; -{ - // You can set up infinite update loops, so this helps to short circuit them - if (hasReceivedFirstFrame && hasReceivedSecondFrame) - { - return; - } - - BOOL updatedMovieFrameOppositeStillImage = NO; - - if (textureIndex == 0) - { - hasReceivedFirstFrame = YES; - firstFrameTime = frameTime; - if (secondFrameCheckDisabled) - { - hasReceivedSecondFrame = YES; - } - - if (!CMTIME_IS_INDEFINITE(frameTime)) - { - if CMTIME_IS_INDEFINITE(secondFrameTime) - { - updatedMovieFrameOppositeStillImage = YES; - } - } - } - else - { - hasReceivedSecondFrame = YES; - secondFrameTime = frameTime; - if (firstFrameCheckDisabled) - { - hasReceivedFirstFrame = YES; - } - - if (!CMTIME_IS_INDEFINITE(frameTime)) - { - if CMTIME_IS_INDEFINITE(firstFrameTime) - { - updatedMovieFrameOppositeStillImage = YES; - } - } - } - - // || (hasReceivedFirstFrame && secondFrameCheckDisabled) || (hasReceivedSecondFrame && firstFrameCheckDisabled) - if ((hasReceivedFirstFrame && hasReceivedSecondFrame) || updatedMovieFrameOppositeStillImage) - { - CMTime passOnFrameTime = (!CMTIME_IS_INDEFINITE(firstFrameTime)) ? firstFrameTime : secondFrameTime; - [super newFrameReadyAtTime:passOnFrameTime atIndex:0]; // Bugfix when trying to record: always use time from first input (unless indefinite, in which case use the second input) - hasReceivedFirstFrame = NO; - hasReceivedSecondFrame = NO; - } -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoPassFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoPassFilter.h deleted file mode 100755 index 23087f35..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoPassFilter.h +++ /dev/null @@ -1,19 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageTwoPassFilter : GPUImageFilter -{ - GPUImageFramebuffer *secondOutputFramebuffer; - - GLProgram *secondFilterProgram; - GLint secondFilterPositionAttribute, secondFilterTextureCoordinateAttribute; - GLint secondFilterInputTextureUniform, secondFilterInputTextureUniform2; - - NSMutableDictionary *secondProgramUniformStateRestorationBlocks; -} - -// Initialization and teardown -- (id)initWithFirstStageVertexShaderFromString:(NSString *)firstStageVertexShaderString firstStageFragmentShaderFromString:(NSString *)firstStageFragmentShaderString secondStageVertexShaderFromString:(NSString *)secondStageVertexShaderString secondStageFragmentShaderFromString:(NSString *)secondStageFragmentShaderString; -- (id)initWithFirstStageFragmentShaderFromString:(NSString *)firstStageFragmentShaderString secondStageFragmentShaderFromString:(NSString *)secondStageFragmentShaderString; -- (void)initializeSecondaryAttributes; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoPassFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoPassFilter.m deleted file mode 100755 index 9eb292b4..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoPassFilter.m +++ /dev/null @@ -1,201 +0,0 @@ -#import "GPUImageTwoPassFilter.h" - -@implementation GPUImageTwoPassFilter - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithFirstStageVertexShaderFromString:(NSString *)firstStageVertexShaderString firstStageFragmentShaderFromString:(NSString *)firstStageFragmentShaderString secondStageVertexShaderFromString:(NSString *)secondStageVertexShaderString secondStageFragmentShaderFromString:(NSString *)secondStageFragmentShaderString; -{ - if (!(self = [super initWithVertexShaderFromString:firstStageVertexShaderString fragmentShaderFromString:firstStageFragmentShaderString])) - { - return nil; - } - - secondProgramUniformStateRestorationBlocks = [NSMutableDictionary dictionaryWithCapacity:10]; - - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext useImageProcessingContext]; - - secondFilterProgram = [[GPUImageContext sharedImageProcessingContext] programForVertexShaderString:secondStageVertexShaderString fragmentShaderString:secondStageFragmentShaderString]; - - if (!secondFilterProgram.initialized) - { - [self initializeSecondaryAttributes]; - - if (![secondFilterProgram link]) - { - NSString *progLog = [secondFilterProgram programLog]; - NSLog(@"Program link log: %@", progLog); - NSString *fragLog = [secondFilterProgram fragmentShaderLog]; - NSLog(@"Fragment shader compile log: %@", fragLog); - NSString *vertLog = [secondFilterProgram vertexShaderLog]; - NSLog(@"Vertex shader compile log: %@", vertLog); - secondFilterProgram = nil; - NSAssert(NO, @"Filter shader link failed"); - } - } - - secondFilterPositionAttribute = [secondFilterProgram attributeIndex:@"position"]; - secondFilterTextureCoordinateAttribute = [secondFilterProgram attributeIndex:@"inputTextureCoordinate"]; - secondFilterInputTextureUniform = [secondFilterProgram uniformIndex:@"inputImageTexture"]; // This does assume a name of "inputImageTexture" for the fragment shader - secondFilterInputTextureUniform2 = [secondFilterProgram uniformIndex:@"inputImageTexture2"]; // This does assume a name of "inputImageTexture2" for second input texture in the fragment shader - - [GPUImageContext setActiveShaderProgram:secondFilterProgram]; - - glEnableVertexAttribArray(secondFilterPositionAttribute); - glEnableVertexAttribArray(secondFilterTextureCoordinateAttribute); - }); - - return self; -} - -- (id)initWithFirstStageFragmentShaderFromString:(NSString *)firstStageFragmentShaderString secondStageFragmentShaderFromString:(NSString *)secondStageFragmentShaderString; -{ - if (!(self = [self initWithFirstStageVertexShaderFromString:kGPUImageVertexShaderString firstStageFragmentShaderFromString:firstStageFragmentShaderString secondStageVertexShaderFromString:kGPUImageVertexShaderString secondStageFragmentShaderFromString:secondStageFragmentShaderString])) - { - return nil; - } - - return self; -} - -- (void)initializeSecondaryAttributes; -{ - [secondFilterProgram addAttribute:@"position"]; - [secondFilterProgram addAttribute:@"inputTextureCoordinate"]; -} - -#pragma mark - -#pragma mark Managing targets - -- (GPUImageFramebuffer *)framebufferForOutput; -{ - return secondOutputFramebuffer; -} - -- (void)removeOutputFramebuffer; -{ - secondOutputFramebuffer = nil; -} - -#pragma mark - -#pragma mark Rendering - -- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates; -{ - if (self.preventRendering) - { - [firstInputFramebuffer unlock]; - return; - } - - [GPUImageContext setActiveShaderProgram:filterProgram]; - - outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:[self sizeOfFBO] textureOptions:self.outputTextureOptions onlyTexture:NO]; - [outputFramebuffer activateFramebuffer]; - - [self setUniformsForProgramAtIndex:0]; - - glClearColor(backgroundColorRed, backgroundColorGreen, backgroundColorBlue, backgroundColorAlpha); - glClear(GL_COLOR_BUFFER_BIT); - - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, [firstInputFramebuffer texture]); - - glUniform1i(filterInputTextureUniform, 2); - - glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, vertices); - glVertexAttribPointer(filterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - [firstInputFramebuffer unlock]; - firstInputFramebuffer = nil; - - // This assumes that any two-pass filter that says it desires monochrome input is using the first pass for a luminance conversion, which can be dropped -// if (!currentlyReceivingMonochromeInput) -// { - // Run the first stage of the two-pass filter -// [super renderToTextureWithVertices:vertices textureCoordinates:textureCoordinates]; -// } - - // Run the second stage of the two-pass filter - secondOutputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:[self sizeOfFBO] textureOptions:self.outputTextureOptions onlyTexture:NO]; - [secondOutputFramebuffer activateFramebuffer]; - [GPUImageContext setActiveShaderProgram:secondFilterProgram]; - if (usingNextFrameForImageCapture) - { - [secondOutputFramebuffer lock]; - } - - [self setUniformsForProgramAtIndex:1]; - - glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D, [outputFramebuffer texture]); - glVertexAttribPointer(secondFilterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, [[self class] textureCoordinatesForRotation:kGPUImageNoRotation]); - - // TODO: Re-enable this monochrome optimization -// if (!currentlyReceivingMonochromeInput) -// { -// glActiveTexture(GL_TEXTURE3); -// glBindTexture(GL_TEXTURE_2D, outputTexture); -// glVertexAttribPointer(secondFilterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, [[self class] textureCoordinatesForRotation:kGPUImageNoRotation]); -// } -// else -// { -// glActiveTexture(GL_TEXTURE3); -// glBindTexture(GL_TEXTURE_2D, sourceTexture); -// glVertexAttribPointer(secondFilterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates); -// } - - glUniform1i(secondFilterInputTextureUniform, 3); - - glVertexAttribPointer(secondFilterPositionAttribute, 2, GL_FLOAT, 0, 0, vertices); - - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - [outputFramebuffer unlock]; - outputFramebuffer = nil; - - if (usingNextFrameForImageCapture) - { - dispatch_semaphore_signal(imageCaptureSemaphore); - } -} - -- (void)setAndExecuteUniformStateCallbackAtIndex:(GLint)uniform forProgram:(GLProgram *)shaderProgram toBlock:(dispatch_block_t)uniformStateBlock; -{ -// TODO: Deal with the fact that two-pass filters may have the same shader program identifier - if (shaderProgram == filterProgram) - { - [uniformStateRestorationBlocks setObject:[uniformStateBlock copy] forKey:[NSNumber numberWithInt:uniform]]; - } - else - { - [secondProgramUniformStateRestorationBlocks setObject:[uniformStateBlock copy] forKey:[NSNumber numberWithInt:uniform]]; - } - uniformStateBlock(); -} - -- (void)setUniformsForProgramAtIndex:(NSUInteger)programIndex; -{ - if (programIndex == 0) - { - [uniformStateRestorationBlocks enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop){ - dispatch_block_t currentBlock = obj; - currentBlock(); - }]; - } - else - { - [secondProgramUniformStateRestorationBlocks enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop){ - dispatch_block_t currentBlock = obj; - currentBlock(); - }]; - } -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoPassTextureSamplingFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoPassTextureSamplingFilter.h deleted file mode 100644 index 73ab79d3..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoPassTextureSamplingFilter.h +++ /dev/null @@ -1,13 +0,0 @@ -#import "GPUImageTwoPassFilter.h" - -@interface GPUImageTwoPassTextureSamplingFilter : GPUImageTwoPassFilter -{ - GLint verticalPassTexelWidthOffsetUniform, verticalPassTexelHeightOffsetUniform, horizontalPassTexelWidthOffsetUniform, horizontalPassTexelHeightOffsetUniform; - GLfloat verticalPassTexelWidthOffset, verticalPassTexelHeightOffset, horizontalPassTexelWidthOffset, horizontalPassTexelHeightOffset; - CGFloat _verticalTexelSpacing, _horizontalTexelSpacing; -} - -// This sets the spacing between texels (in pixels) when sampling for the first. By default, this is 1.0 -@property(readwrite, nonatomic) CGFloat verticalTexelSpacing, horizontalTexelSpacing; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoPassTextureSamplingFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoPassTextureSamplingFilter.m deleted file mode 100644 index b6a2ec58..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageTwoPassTextureSamplingFilter.m +++ /dev/null @@ -1,85 +0,0 @@ -#import "GPUImageTwoPassTextureSamplingFilter.h" - -@implementation GPUImageTwoPassTextureSamplingFilter - -@synthesize verticalTexelSpacing = _verticalTexelSpacing; -@synthesize horizontalTexelSpacing = _horizontalTexelSpacing; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithFirstStageVertexShaderFromString:(NSString *)firstStageVertexShaderString firstStageFragmentShaderFromString:(NSString *)firstStageFragmentShaderString secondStageVertexShaderFromString:(NSString *)secondStageVertexShaderString secondStageFragmentShaderFromString:(NSString *)secondStageFragmentShaderString -{ - if (!(self = [super initWithFirstStageVertexShaderFromString:firstStageVertexShaderString firstStageFragmentShaderFromString:firstStageFragmentShaderString secondStageVertexShaderFromString:secondStageVertexShaderString secondStageFragmentShaderFromString:secondStageFragmentShaderString])) - { - return nil; - } - - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext useImageProcessingContext]; - - verticalPassTexelWidthOffsetUniform = [filterProgram uniformIndex:@"texelWidthOffset"]; - verticalPassTexelHeightOffsetUniform = [filterProgram uniformIndex:@"texelHeightOffset"]; - - horizontalPassTexelWidthOffsetUniform = [secondFilterProgram uniformIndex:@"texelWidthOffset"]; - horizontalPassTexelHeightOffsetUniform = [secondFilterProgram uniformIndex:@"texelHeightOffset"]; - }); - - self.verticalTexelSpacing = 1.0; - self.horizontalTexelSpacing = 1.0; - - return self; -} - -- (void)setUniformsForProgramAtIndex:(NSUInteger)programIndex; -{ - [super setUniformsForProgramAtIndex:programIndex]; - - if (programIndex == 0) - { - glUniform1f(verticalPassTexelWidthOffsetUniform, verticalPassTexelWidthOffset); - glUniform1f(verticalPassTexelHeightOffsetUniform, verticalPassTexelHeightOffset); - } - else - { - glUniform1f(horizontalPassTexelWidthOffsetUniform, horizontalPassTexelWidthOffset); - glUniform1f(horizontalPassTexelHeightOffsetUniform, horizontalPassTexelHeightOffset); - } -} - -- (void)setupFilterForSize:(CGSize)filterFrameSize; -{ - runSynchronouslyOnVideoProcessingQueue(^{ - // The first pass through the framebuffer may rotate the inbound image, so need to account for that by changing up the kernel ordering for that pass - if (GPUImageRotationSwapsWidthAndHeight(inputRotation)) - { - verticalPassTexelWidthOffset = _verticalTexelSpacing / filterFrameSize.height; - verticalPassTexelHeightOffset = 0.0; - } - else - { - verticalPassTexelWidthOffset = 0.0; - verticalPassTexelHeightOffset = _verticalTexelSpacing / filterFrameSize.height; - } - - horizontalPassTexelWidthOffset = _horizontalTexelSpacing / filterFrameSize.width; - horizontalPassTexelHeightOffset = 0.0; - }); -} - -#pragma mark - -#pragma mark Accessors - -- (void)setVerticalTexelSpacing:(CGFloat)newValue; -{ - _verticalTexelSpacing = newValue; - [self setupFilterForSize:[self sizeOfFBO]]; -} - -- (void)setHorizontalTexelSpacing:(CGFloat)newValue; -{ - _horizontalTexelSpacing = newValue; - [self setupFilterForSize:[self sizeOfFBO]]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageUIElement.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageUIElement.h deleted file mode 100644 index 984ff2ad..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageUIElement.h +++ /dev/null @@ -1,15 +0,0 @@ -#import "GPUImageOutput.h" - -@interface GPUImageUIElement : GPUImageOutput - -// Initialization and teardown -- (id)initWithView:(UIView *)inputView; -- (id)initWithLayer:(CALayer *)inputLayer; - -// Layer management -- (CGSize)layerSizeInPixels; -- (void)update; -- (void)updateUsingCurrentTime; -- (void)updateWithTimestamp:(CMTime)frameTime; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageUIElement.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageUIElement.m deleted file mode 100644 index 33208924..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageUIElement.m +++ /dev/null @@ -1,123 +0,0 @@ -#import "GPUImageUIElement.h" - -@interface GPUImageUIElement () -{ - UIView *view; - CALayer *layer; - - CGSize previousLayerSizeInPixels; - CMTime time; - NSTimeInterval actualTimeOfLastUpdate; -} - -@end - -@implementation GPUImageUIElement - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithView:(UIView *)inputView; -{ - if (!(self = [super init])) - { - return nil; - } - - view = inputView; - layer = inputView.layer; - - previousLayerSizeInPixels = CGSizeZero; - [self update]; - - return self; -} - -- (id)initWithLayer:(CALayer *)inputLayer; -{ - if (!(self = [super init])) - { - return nil; - } - - view = nil; - layer = inputLayer; - - previousLayerSizeInPixels = CGSizeZero; - [self update]; - - return self; -} - -#pragma mark - -#pragma mark Layer management - -- (CGSize)layerSizeInPixels; -{ - CGSize pointSize = layer.bounds.size; - return CGSizeMake(layer.contentsScale * pointSize.width, layer.contentsScale * pointSize.height); -} - -- (void)update; -{ - [self updateWithTimestamp:kCMTimeIndefinite]; -} - -- (void)updateUsingCurrentTime; -{ - if(CMTIME_IS_INVALID(time)) { - time = CMTimeMakeWithSeconds(0, 600); - actualTimeOfLastUpdate = [NSDate timeIntervalSinceReferenceDate]; - } else { - NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate]; - NSTimeInterval diff = now - actualTimeOfLastUpdate; - time = CMTimeAdd(time, CMTimeMakeWithSeconds(diff, 600)); - actualTimeOfLastUpdate = now; - } - - [self updateWithTimestamp:time]; -} - -- (void)updateWithTimestamp:(CMTime)frameTime; -{ - [GPUImageContext useImageProcessingContext]; - - CGSize layerPixelSize = [self layerSizeInPixels]; - - GLubyte *imageData = (GLubyte *) calloc(1, (int)layerPixelSize.width * (int)layerPixelSize.height * 4); - - CGColorSpaceRef genericRGBColorspace = CGColorSpaceCreateDeviceRGB(); - CGContextRef imageContext = CGBitmapContextCreate(imageData, (int)layerPixelSize.width, (int)layerPixelSize.height, 8, (int)layerPixelSize.width * 4, genericRGBColorspace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); -// CGContextRotateCTM(imageContext, M_PI_2); - CGContextTranslateCTM(imageContext, 0.0f, layerPixelSize.height); - CGContextScaleCTM(imageContext, layer.contentsScale, -layer.contentsScale); - // CGContextSetBlendMode(imageContext, kCGBlendModeCopy); // From Technical Q&A QA1708: http://developer.apple.com/library/ios/#qa/qa1708/_index.html - - [layer renderInContext:imageContext]; - - CGContextRelease(imageContext); - CGColorSpaceRelease(genericRGBColorspace); - - // TODO: This may not work - outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:layerPixelSize textureOptions:self.outputTextureOptions onlyTexture:YES]; - - glBindTexture(GL_TEXTURE_2D, [outputFramebuffer texture]); - // no need to use self.outputTextureOptions here, we always need these texture options - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)layerPixelSize.width, (int)layerPixelSize.height, 0, GL_BGRA, GL_UNSIGNED_BYTE, imageData); - - free(imageData); - - for (id currentTarget in targets) - { - if (currentTarget != self.targetToIgnoreForUpdates) - { - NSInteger indexOfObject = [targets indexOfObject:currentTarget]; - NSInteger textureIndexOfTarget = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; - - [currentTarget setInputSize:layerPixelSize atIndex:textureIndexOfTarget]; - [currentTarget newFrameReadyAtTime:frameTime atIndex:textureIndexOfTarget]; - } - } -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageUnsharpMaskFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageUnsharpMaskFilter.h deleted file mode 100755 index 9d8aff01..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageUnsharpMaskFilter.h +++ /dev/null @@ -1,16 +0,0 @@ -#import "GPUImageFilterGroup.h" - -@class GPUImageGaussianBlurFilter; - -@interface GPUImageUnsharpMaskFilter : GPUImageFilterGroup -{ - GPUImageGaussianBlurFilter *blurFilter; - GPUImageFilter *unsharpMaskFilter; -} -// The blur radius of the underlying Gaussian blur. The default is 4.0. -@property (readwrite, nonatomic) CGFloat blurRadiusInPixels; - -// The strength of the sharpening, from 0.0 on up, with a default of 1.0 -@property(readwrite, nonatomic) CGFloat intensity; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageUnsharpMaskFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageUnsharpMaskFilter.m deleted file mode 100755 index 542c5ea3..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageUnsharpMaskFilter.m +++ /dev/null @@ -1,101 +0,0 @@ -#import "GPUImageUnsharpMaskFilter.h" -#import "GPUImageFilter.h" -#import "GPUImageTwoInputFilter.h" -#import "GPUImageGaussianBlurFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageUnsharpMaskFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - varying highp vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - uniform highp float intensity; - - void main() - { - lowp vec4 sharpImageColor = texture2D(inputImageTexture, textureCoordinate); - lowp vec3 blurredImageColor = texture2D(inputImageTexture2, textureCoordinate2).rgb; - - gl_FragColor = vec4(sharpImageColor.rgb * intensity + blurredImageColor * (1.0 - intensity), sharpImageColor.a); -// gl_FragColor = mix(blurredImageColor, sharpImageColor, intensity); -// gl_FragColor = vec4(sharpImageColor.rgb - (blurredImageColor.rgb * intensity), 1.0); - } -); -#else -NSString *const kGPUImageUnsharpMaskFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 textureCoordinate2; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - - uniform float intensity; - - void main() - { - vec4 sharpImageColor = texture2D(inputImageTexture, textureCoordinate); - vec3 blurredImageColor = texture2D(inputImageTexture2, textureCoordinate2).rgb; - - gl_FragColor = vec4(sharpImageColor.rgb * intensity + blurredImageColor * (1.0 - intensity), sharpImageColor.a); - // gl_FragColor = mix(blurredImageColor, sharpImageColor, intensity); - // gl_FragColor = vec4(sharpImageColor.rgb - (blurredImageColor.rgb * intensity), 1.0); - } -); -#endif - -@implementation GPUImageUnsharpMaskFilter - -@synthesize blurRadiusInPixels; -@synthesize intensity = _intensity; - -- (id)init; -{ - if (!(self = [super init])) - { - return nil; - } - - // First pass: apply a variable Gaussian blur - blurFilter = [[GPUImageGaussianBlurFilter alloc] init]; - [self addFilter:blurFilter]; - - // Second pass: combine the blurred image with the original sharp one - unsharpMaskFilter = [[GPUImageTwoInputFilter alloc] initWithFragmentShaderFromString:kGPUImageUnsharpMaskFragmentShaderString]; - [self addFilter:unsharpMaskFilter]; - - // Texture location 0 needs to be the sharp image for both the blur and the second stage processing - [blurFilter addTarget:unsharpMaskFilter atTextureLocation:1]; - - self.initialFilters = [NSArray arrayWithObjects:blurFilter, unsharpMaskFilter, nil]; - self.terminalFilter = unsharpMaskFilter; - - self.intensity = 1.0; - self.blurRadiusInPixels = 4.0; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setBlurRadiusInPixels:(CGFloat)newValue; -{ - blurFilter.blurRadiusInPixels = newValue; -} - -- (CGFloat)blurRadiusInPixels; -{ - return blurFilter.blurRadiusInPixels; -} - -- (void)setIntensity:(CGFloat)newValue; -{ - _intensity = newValue; - [unsharpMaskFilter setFloat:newValue forUniformName:@"intensity"]; -} - -@end \ No newline at end of file diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVideoCamera.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVideoCamera.h deleted file mode 100755 index 22ccb942..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVideoCamera.h +++ /dev/null @@ -1,154 +0,0 @@ -#import -#import -#import -#import "GPUImageContext.h" -#import "GPUImageOutput.h" - -extern const GLfloat kColorConversion601[]; -extern const GLfloat kColorConversion601FullRange[]; -extern const GLfloat kColorConversion709[]; -extern NSString *const kGPUImageYUVVideoRangeConversionForRGFragmentShaderString; -extern NSString *const kGPUImageYUVFullRangeConversionForLAFragmentShaderString; -extern NSString *const kGPUImageYUVVideoRangeConversionForLAFragmentShaderString; - - -//Delegate Protocal for Face Detection. -@protocol GPUImageVideoCameraDelegate - -@optional -- (void)willOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer; -@end - - -/** - A GPUImageOutput that provides frames from either camera -*/ -@interface GPUImageVideoCamera : GPUImageOutput -{ - NSUInteger numberOfFramesCaptured; - CGFloat totalFrameTimeDuringCapture; - - AVCaptureSession *_captureSession; - AVCaptureDevice *_inputCamera; - AVCaptureDevice *_microphone; - AVCaptureDeviceInput *videoInput; - AVCaptureVideoDataOutput *videoOutput; - - BOOL capturePaused; - GPUImageRotationMode outputRotation, internalRotation; - dispatch_semaphore_t frameRenderingSemaphore; - - BOOL captureAsYUV; - GLuint luminanceTexture, chrominanceTexture; - - __unsafe_unretained id _delegate; -} - -/// The AVCaptureSession used to capture from the camera -@property(readonly, retain, nonatomic) AVCaptureSession *captureSession; - -/// This enables the capture session preset to be changed on the fly -@property (readwrite, nonatomic, copy) NSString *captureSessionPreset; - -/// This sets the frame rate of the camera (iOS 5 and above only) -/** - Setting this to 0 or below will set the frame rate back to the default setting for a particular preset. - */ -@property (readwrite) int32_t frameRate; - -/// Easy way to tell which cameras are present on device -@property (readonly, getter = isFrontFacingCameraPresent) BOOL frontFacingCameraPresent; -@property (readonly, getter = isBackFacingCameraPresent) BOOL backFacingCameraPresent; - -/// This enables the benchmarking mode, which logs out instantaneous and average frame times to the console -@property(readwrite, nonatomic) BOOL runBenchmark; - -/// Use this property to manage camera settings. Focus point, exposure point, etc. -@property(readonly) AVCaptureDevice *inputCamera; - -/// This determines the rotation applied to the output image, based on the source material -@property(readwrite, nonatomic) UIInterfaceOrientation outputImageOrientation; - -/// These properties determine whether or not the two camera orientations should be mirrored. By default, both are NO. -@property(readwrite, nonatomic) BOOL horizontallyMirrorFrontFacingCamera, horizontallyMirrorRearFacingCamera; - -@property(nonatomic, assign) id delegate; - -/// @name Initialization and teardown - -/** Begin a capture session - - See AVCaptureSession for acceptable values - - @param sessionPreset Session preset to use - @param cameraPosition Camera to capture from - */ -- (id)initWithSessionPreset:(NSString *)sessionPreset cameraPosition:(AVCaptureDevicePosition)cameraPosition; - -/** Add audio capture to the session. Adding inputs and outputs freezes the capture session momentarily, so you - can use this method to add the audio inputs and outputs early, if you're going to set the audioEncodingTarget - later. Returns YES is the audio inputs and outputs were added, or NO if they had already been added. - */ -- (BOOL)addAudioInputsAndOutputs; - -/** Remove the audio capture inputs and outputs from this session. Returns YES if the audio inputs and outputs - were removed, or NO is they hadn't already been added. - */ -- (BOOL)removeAudioInputsAndOutputs; - -/** Tear down the capture session - */ -- (void)removeInputsAndOutputs; - -/// @name Manage the camera video stream - -/** Start camera capturing - */ -- (void)startCameraCapture; - -/** Stop camera capturing - */ -- (void)stopCameraCapture; - -/** Pause camera capturing - */ -- (void)pauseCameraCapture; - -/** Resume camera capturing - */ -- (void)resumeCameraCapture; - -/** Process a video sample - @param sampleBuffer Buffer to process - */ -- (void)processVideoSampleBuffer:(CMSampleBufferRef)sampleBuffer; - -/** Process an audio sample - @param sampleBuffer Buffer to process - */ -- (void)processAudioSampleBuffer:(CMSampleBufferRef)sampleBuffer; - -/** Get the position (front, rear) of the source camera - */ -- (AVCaptureDevicePosition)cameraPosition; - -/** Get the AVCaptureConnection of the source camera - */ -- (AVCaptureConnection *)videoCaptureConnection; - -/** This flips between the front and rear cameras - */ -- (void)rotateCamera; - -/// @name Benchmarking - -/** When benchmarking is enabled, this will keep a running average of the time from uploading, processing, and final recording or display - */ -- (CGFloat)averageFrameDurationDuringCapture; - -- (void)resetBenchmarkAverage; - -+ (BOOL)isBackFacingCameraPresent; -+ (BOOL)isFrontFacingCameraPresent; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVideoCamera.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVideoCamera.m deleted file mode 100644 index b84f88aa..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVideoCamera.m +++ /dev/null @@ -1,1129 +0,0 @@ -#import "GPUImageVideoCamera.h" -#import "GPUImageMovieWriter.h" -#import "GPUImageFilter.h" - -// Color Conversion Constants (YUV to RGB) including adjustment from 16-235/16-240 (video range) - -// BT.601, which is the standard for SDTV. -const GLfloat kColorConversion601[] = { - 1.164, 1.164, 1.164, - 0.0, -0.392, 2.017, - 1.596, -0.813, 0.0, -}; - -// BT.709, which is the standard for HDTV. -const GLfloat kColorConversion709[] = { - 1.164, 1.164, 1.164, - 0.0, -0.213, 2.112, - 1.793, -0.533, 0.0, -}; - -// BT.601 full range (ref: http://www.equasys.de/colorconversion.html) -const GLfloat kColorConversion601FullRange[] = { - 1.0, 1.0, 1.0, - 0.0, -0.343, 1.765, - 1.4, -0.711, 0.0, -}; - -NSString *const kGPUImageYUVVideoRangeConversionForRGFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D luminanceTexture; - uniform sampler2D chrominanceTexture; - uniform mediump mat3 colorConversionMatrix; - - void main() - { - mediump vec3 yuv; - lowp vec3 rgb; - - yuv.x = texture2D(luminanceTexture, textureCoordinate).r; - yuv.yz = texture2D(chrominanceTexture, textureCoordinate).rg - vec2(0.5, 0.5); - rgb = colorConversionMatrix * yuv; - - gl_FragColor = vec4(rgb, 1); - } - ); - -NSString *const kGPUImageYUVFullRangeConversionForLAFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D luminanceTexture; - uniform sampler2D chrominanceTexture; - uniform mediump mat3 colorConversionMatrix; - - void main() - { - mediump vec3 yuv; - lowp vec3 rgb; - - yuv.x = texture2D(luminanceTexture, textureCoordinate).r; - yuv.yz = texture2D(chrominanceTexture, textureCoordinate).ra - vec2(0.5, 0.5); - rgb = colorConversionMatrix * yuv; - - gl_FragColor = vec4(rgb, 1); - } - ); - -NSString *const kGPUImageYUVVideoRangeConversionForLAFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D luminanceTexture; - uniform sampler2D chrominanceTexture; - uniform mediump mat3 colorConversionMatrix; - - void main() - { - mediump vec3 yuv; - lowp vec3 rgb; - - yuv.x = texture2D(luminanceTexture, textureCoordinate).r - (16.0/255.0); - yuv.yz = texture2D(chrominanceTexture, textureCoordinate).ra - vec2(0.5, 0.5); - rgb = colorConversionMatrix * yuv; - - gl_FragColor = vec4(rgb, 1); - } - ); - - -#pragma mark - -#pragma mark Private methods and instance variables - -@interface GPUImageVideoCamera () -{ - AVCaptureDeviceInput *audioInput; - AVCaptureAudioDataOutput *audioOutput; - NSDate *startingCaptureTime; - - dispatch_queue_t cameraProcessingQueue, audioProcessingQueue; - - GLProgram *yuvConversionProgram; - GLint yuvConversionPositionAttribute, yuvConversionTextureCoordinateAttribute; - GLint yuvConversionLuminanceTextureUniform, yuvConversionChrominanceTextureUniform; - GLint yuvConversionMatrixUniform; - const GLfloat *_preferredConversion; - - BOOL isFullYUVRange; - - int imageBufferWidth, imageBufferHeight; - - BOOL addedAudioInputsDueToEncodingTarget; -} - -- (void)updateOrientationSendToTargets; -- (void)convertYUVToRGBOutput; - -@end - -@implementation GPUImageVideoCamera - -@synthesize captureSessionPreset = _captureSessionPreset; -@synthesize captureSession = _captureSession; -@synthesize inputCamera = _inputCamera; -@synthesize runBenchmark = _runBenchmark; -@synthesize outputImageOrientation = _outputImageOrientation; -@synthesize delegate = _delegate; -@synthesize horizontallyMirrorFrontFacingCamera = _horizontallyMirrorFrontFacingCamera, horizontallyMirrorRearFacingCamera = _horizontallyMirrorRearFacingCamera; -@synthesize frameRate = _frameRate; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [self initWithSessionPreset:AVCaptureSessionPreset640x480 cameraPosition:AVCaptureDevicePositionBack])) - { - return nil; - } - - return self; -} - -- (id)initWithSessionPreset:(NSString *)sessionPreset cameraPosition:(AVCaptureDevicePosition)cameraPosition; -{ - if (!(self = [super init])) - { - return nil; - } - - cameraProcessingQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0); - audioProcessingQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0); - - frameRenderingSemaphore = dispatch_semaphore_create(1); - - _frameRate = 0; // This will not set frame rate unless this value gets set to 1 or above - _runBenchmark = NO; - capturePaused = NO; - outputRotation = kGPUImageNoRotation; - internalRotation = kGPUImageNoRotation; - captureAsYUV = YES; - _preferredConversion = kColorConversion709; - - // Grab the back-facing or front-facing camera - _inputCamera = nil; - NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; - for (AVCaptureDevice *device in devices) - { - if ([device position] == cameraPosition) - { - _inputCamera = device; - } - } - - if (!_inputCamera) { - return nil; - } - - // Create the capture session - _captureSession = [[AVCaptureSession alloc] init]; - - [_captureSession beginConfiguration]; - - // Add the video input - NSError *error = nil; - videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:_inputCamera error:&error]; - if ([_captureSession canAddInput:videoInput]) - { - [_captureSession addInput:videoInput]; - } - - // Add the video frame output - videoOutput = [[AVCaptureVideoDataOutput alloc] init]; - [videoOutput setAlwaysDiscardsLateVideoFrames:NO]; - -// if (captureAsYUV && [GPUImageContext deviceSupportsRedTextures]) - if (captureAsYUV && [GPUImageContext supportsFastTextureUpload]) - { - BOOL supportsFullYUVRange = NO; - NSArray *supportedPixelFormats = videoOutput.availableVideoCVPixelFormatTypes; - for (NSNumber *currentPixelFormat in supportedPixelFormats) - { - if ([currentPixelFormat intValue] == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) - { - supportsFullYUVRange = YES; - } - } - - if (supportsFullYUVRange) - { - [videoOutput setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange] forKey:(id)kCVPixelBufferPixelFormatTypeKey]]; - isFullYUVRange = YES; - } - else - { - [videoOutput setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange] forKey:(id)kCVPixelBufferPixelFormatTypeKey]]; - isFullYUVRange = NO; - } - } - else - { - [videoOutput setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]]; - } - - runSynchronouslyOnVideoProcessingQueue(^{ - - if (captureAsYUV) - { - [GPUImageContext useImageProcessingContext]; - // if ([GPUImageContext deviceSupportsRedTextures]) - // { - // yuvConversionProgram = [[GPUImageContext sharedImageProcessingContext] programForVertexShaderString:kGPUImageVertexShaderString fragmentShaderString:kGPUImageYUVVideoRangeConversionForRGFragmentShaderString]; - // } - // else - // { - if (isFullYUVRange) - { - yuvConversionProgram = [[GPUImageContext sharedImageProcessingContext] programForVertexShaderString:kGPUImageVertexShaderString fragmentShaderString:kGPUImageYUVFullRangeConversionForLAFragmentShaderString]; - } - else - { - yuvConversionProgram = [[GPUImageContext sharedImageProcessingContext] programForVertexShaderString:kGPUImageVertexShaderString fragmentShaderString:kGPUImageYUVVideoRangeConversionForLAFragmentShaderString]; - } - - // } - - if (!yuvConversionProgram.initialized) - { - [yuvConversionProgram addAttribute:@"position"]; - [yuvConversionProgram addAttribute:@"inputTextureCoordinate"]; - - if (![yuvConversionProgram link]) - { - NSString *progLog = [yuvConversionProgram programLog]; - NSLog(@"Program link log: %@", progLog); - NSString *fragLog = [yuvConversionProgram fragmentShaderLog]; - NSLog(@"Fragment shader compile log: %@", fragLog); - NSString *vertLog = [yuvConversionProgram vertexShaderLog]; - NSLog(@"Vertex shader compile log: %@", vertLog); - yuvConversionProgram = nil; - NSAssert(NO, @"Filter shader link failed"); - } - } - - yuvConversionPositionAttribute = [yuvConversionProgram attributeIndex:@"position"]; - yuvConversionTextureCoordinateAttribute = [yuvConversionProgram attributeIndex:@"inputTextureCoordinate"]; - yuvConversionLuminanceTextureUniform = [yuvConversionProgram uniformIndex:@"luminanceTexture"]; - yuvConversionChrominanceTextureUniform = [yuvConversionProgram uniformIndex:@"chrominanceTexture"]; - yuvConversionMatrixUniform = [yuvConversionProgram uniformIndex:@"colorConversionMatrix"]; - - [GPUImageContext setActiveShaderProgram:yuvConversionProgram]; - - glEnableVertexAttribArray(yuvConversionPositionAttribute); - glEnableVertexAttribArray(yuvConversionTextureCoordinateAttribute); - } - }); - - [videoOutput setSampleBufferDelegate:self queue:cameraProcessingQueue]; - if ([_captureSession canAddOutput:videoOutput]) - { - [_captureSession addOutput:videoOutput]; - } - else - { - NSLog(@"Couldn't add video output"); - return nil; - } - - _captureSessionPreset = sessionPreset; - [_captureSession setSessionPreset:_captureSessionPreset]; - -// This will let you get 60 FPS video from the 720p preset on an iPhone 4S, but only that device and that preset -// AVCaptureConnection *conn = [videoOutput connectionWithMediaType:AVMediaTypeVideo]; -// -// if (conn.supportsVideoMinFrameDuration) -// conn.videoMinFrameDuration = CMTimeMake(1,60); -// if (conn.supportsVideoMaxFrameDuration) -// conn.videoMaxFrameDuration = CMTimeMake(1,60); - - [_captureSession commitConfiguration]; - - return self; -} - -- (GPUImageFramebuffer *)framebufferForOutput; -{ - return outputFramebuffer; -} - -- (void)dealloc -{ - [self stopCameraCapture]; - [videoOutput setSampleBufferDelegate:nil queue:dispatch_get_main_queue()]; - [audioOutput setSampleBufferDelegate:nil queue:dispatch_get_main_queue()]; - - [self removeInputsAndOutputs]; - -// ARC forbids explicit message send of 'release'; since iOS 6 even for dispatch_release() calls: stripping it out in that case is required. -#if !OS_OBJECT_USE_OBJC - if (frameRenderingSemaphore != NULL) - { - dispatch_release(frameRenderingSemaphore); - } -#endif -} - -- (BOOL)addAudioInputsAndOutputs -{ - if (audioOutput) - return NO; - - [_captureSession beginConfiguration]; - - _microphone = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio]; - audioInput = [AVCaptureDeviceInput deviceInputWithDevice:_microphone error:nil]; - if ([_captureSession canAddInput:audioInput]) - { - [_captureSession addInput:audioInput]; - } - audioOutput = [[AVCaptureAudioDataOutput alloc] init]; - - if ([_captureSession canAddOutput:audioOutput]) - { - [_captureSession addOutput:audioOutput]; - } - else - { - NSLog(@"Couldn't add audio output"); - } - [audioOutput setSampleBufferDelegate:self queue:audioProcessingQueue]; - - [_captureSession commitConfiguration]; - return YES; -} - -- (BOOL)removeAudioInputsAndOutputs -{ - if (!audioOutput) - return NO; - - [_captureSession beginConfiguration]; - [_captureSession removeInput:audioInput]; - [_captureSession removeOutput:audioOutput]; - audioInput = nil; - audioOutput = nil; - _microphone = nil; - [_captureSession commitConfiguration]; - return YES; -} - -- (void)removeInputsAndOutputs; -{ - [_captureSession beginConfiguration]; - if (videoInput) { - [_captureSession removeInput:videoInput]; - [_captureSession removeOutput:videoOutput]; - videoInput = nil; - videoOutput = nil; - } - if (_microphone != nil) - { - [_captureSession removeInput:audioInput]; - [_captureSession removeOutput:audioOutput]; - audioInput = nil; - audioOutput = nil; - _microphone = nil; - } - [_captureSession commitConfiguration]; -} - -#pragma mark - -#pragma mark Managing targets - -- (void)addTarget:(id)newTarget atTextureLocation:(NSInteger)textureLocation; -{ - [super addTarget:newTarget atTextureLocation:textureLocation]; - - [newTarget setInputRotation:outputRotation atIndex:textureLocation]; -} - -#pragma mark - -#pragma mark Manage the camera video stream - -- (void)startCameraCapture; -{ - if (![_captureSession isRunning]) - { - startingCaptureTime = [NSDate date]; - [_captureSession startRunning]; - }; -} - -- (void)stopCameraCapture; -{ - if ([_captureSession isRunning]) - { - [_captureSession stopRunning]; - } -} - -- (void)pauseCameraCapture; -{ - capturePaused = YES; -} - -- (void)resumeCameraCapture; -{ - capturePaused = NO; -} - -- (void)rotateCamera -{ - if (self.frontFacingCameraPresent == NO) - return; - - NSError *error; - AVCaptureDeviceInput *newVideoInput; - AVCaptureDevicePosition currentCameraPosition = [[videoInput device] position]; - - if (currentCameraPosition == AVCaptureDevicePositionBack) - { - currentCameraPosition = AVCaptureDevicePositionFront; - } - else - { - currentCameraPosition = AVCaptureDevicePositionBack; - } - - AVCaptureDevice *backFacingCamera = nil; - NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; - for (AVCaptureDevice *device in devices) - { - if ([device position] == currentCameraPosition) - { - backFacingCamera = device; - } - } - newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:backFacingCamera error:&error]; - - if (newVideoInput != nil) - { - [_captureSession beginConfiguration]; - - [_captureSession removeInput:videoInput]; - if ([_captureSession canAddInput:newVideoInput]) - { - [_captureSession addInput:newVideoInput]; - videoInput = newVideoInput; - } - else - { - [_captureSession addInput:videoInput]; - } - //captureSession.sessionPreset = oriPreset; - [_captureSession commitConfiguration]; - } - - _inputCamera = backFacingCamera; - [self setOutputImageOrientation:_outputImageOrientation]; -} - -- (AVCaptureDevicePosition)cameraPosition -{ - return [[videoInput device] position]; -} - -+ (BOOL)isBackFacingCameraPresent; -{ - NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; - - for (AVCaptureDevice *device in devices) - { - if ([device position] == AVCaptureDevicePositionBack) - return YES; - } - - return NO; -} - -- (BOOL)isBackFacingCameraPresent -{ - return [GPUImageVideoCamera isBackFacingCameraPresent]; -} - -+ (BOOL)isFrontFacingCameraPresent; -{ - NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; - - for (AVCaptureDevice *device in devices) - { - if ([device position] == AVCaptureDevicePositionFront) - return YES; - } - - return NO; -} - -- (BOOL)isFrontFacingCameraPresent -{ - return [GPUImageVideoCamera isFrontFacingCameraPresent]; -} - -- (void)setCaptureSessionPreset:(NSString *)captureSessionPreset; -{ - [_captureSession beginConfiguration]; - - _captureSessionPreset = captureSessionPreset; - [_captureSession setSessionPreset:_captureSessionPreset]; - - [_captureSession commitConfiguration]; -} - -- (void)setFrameRate:(int32_t)frameRate; -{ - _frameRate = frameRate; - - if (_frameRate > 0) - { - if ([_inputCamera respondsToSelector:@selector(setActiveVideoMinFrameDuration:)] && - [_inputCamera respondsToSelector:@selector(setActiveVideoMaxFrameDuration:)]) { - - NSError *error; - [_inputCamera lockForConfiguration:&error]; - if (error == nil) { -#if defined(__IPHONE_7_0) - [_inputCamera setActiveVideoMinFrameDuration:CMTimeMake(1, _frameRate)]; - [_inputCamera setActiveVideoMaxFrameDuration:CMTimeMake(1, _frameRate)]; -#endif - } - [_inputCamera unlockForConfiguration]; - - } else { - - for (AVCaptureConnection *connection in videoOutput.connections) - { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - if ([connection respondsToSelector:@selector(setVideoMinFrameDuration:)]) - connection.videoMinFrameDuration = CMTimeMake(1, _frameRate); - - if ([connection respondsToSelector:@selector(setVideoMaxFrameDuration:)]) - connection.videoMaxFrameDuration = CMTimeMake(1, _frameRate); -#pragma clang diagnostic pop - } - } - - } - else - { - if ([_inputCamera respondsToSelector:@selector(setActiveVideoMinFrameDuration:)] && - [_inputCamera respondsToSelector:@selector(setActiveVideoMaxFrameDuration:)]) { - - NSError *error; - [_inputCamera lockForConfiguration:&error]; - if (error == nil) { -#if defined(__IPHONE_7_0) - [_inputCamera setActiveVideoMinFrameDuration:kCMTimeInvalid]; - [_inputCamera setActiveVideoMaxFrameDuration:kCMTimeInvalid]; -#endif - } - [_inputCamera unlockForConfiguration]; - - } else { - - for (AVCaptureConnection *connection in videoOutput.connections) - { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - if ([connection respondsToSelector:@selector(setVideoMinFrameDuration:)]) - connection.videoMinFrameDuration = kCMTimeInvalid; // This sets videoMinFrameDuration back to default - - if ([connection respondsToSelector:@selector(setVideoMaxFrameDuration:)]) - connection.videoMaxFrameDuration = kCMTimeInvalid; // This sets videoMaxFrameDuration back to default -#pragma clang diagnostic pop - } - } - - } -} - -- (int32_t)frameRate; -{ - return _frameRate; -} - -- (AVCaptureConnection *)videoCaptureConnection { - for (AVCaptureConnection *connection in [videoOutput connections] ) { - for ( AVCaptureInputPort *port in [connection inputPorts] ) { - if ( [[port mediaType] isEqual:AVMediaTypeVideo] ) { - return connection; - } - } - } - - return nil; -} - -#define INITIALFRAMESTOIGNOREFORBENCHMARK 5 - -- (void)updateTargetsForVideoCameraUsingCacheTextureAtWidth:(int)bufferWidth height:(int)bufferHeight time:(CMTime)currentTime; -{ - // First, update all the framebuffers in the targets - for (id currentTarget in targets) - { - if ([currentTarget enabled]) - { - NSInteger indexOfObject = [targets indexOfObject:currentTarget]; - NSInteger textureIndexOfTarget = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; - - if (currentTarget != self.targetToIgnoreForUpdates) - { - [currentTarget setInputRotation:outputRotation atIndex:textureIndexOfTarget]; - [currentTarget setInputSize:CGSizeMake(bufferWidth, bufferHeight) atIndex:textureIndexOfTarget]; - - if ([currentTarget wantsMonochromeInput] && captureAsYUV) - { - [currentTarget setCurrentlyReceivingMonochromeInput:YES]; - // TODO: Replace optimization for monochrome output - [currentTarget setInputFramebuffer:outputFramebuffer atIndex:textureIndexOfTarget]; - } - else - { - [currentTarget setCurrentlyReceivingMonochromeInput:NO]; - [currentTarget setInputFramebuffer:outputFramebuffer atIndex:textureIndexOfTarget]; - } - } - else - { - [currentTarget setInputRotation:outputRotation atIndex:textureIndexOfTarget]; - [currentTarget setInputFramebuffer:outputFramebuffer atIndex:textureIndexOfTarget]; - } - } - } - - // Then release our hold on the local framebuffer to send it back to the cache as soon as it's no longer needed - [outputFramebuffer unlock]; - outputFramebuffer = nil; - - // Finally, trigger rendering as needed - for (id currentTarget in targets) - { - if ([currentTarget enabled]) - { - NSInteger indexOfObject = [targets indexOfObject:currentTarget]; - NSInteger textureIndexOfTarget = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; - - if (currentTarget != self.targetToIgnoreForUpdates) - { - [currentTarget newFrameReadyAtTime:currentTime atIndex:textureIndexOfTarget]; - } - } - } -} - -- (void)processVideoSampleBuffer:(CMSampleBufferRef)sampleBuffer; -{ - if (capturePaused) - { - return; - } - - CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); - CVImageBufferRef cameraFrame = CMSampleBufferGetImageBuffer(sampleBuffer); - int bufferWidth = (int) CVPixelBufferGetWidth(cameraFrame); - int bufferHeight = (int) CVPixelBufferGetHeight(cameraFrame); - CFTypeRef colorAttachments = CVBufferGetAttachment(cameraFrame, kCVImageBufferYCbCrMatrixKey, NULL); - if (colorAttachments != NULL) - { - if(CFStringCompare(colorAttachments, kCVImageBufferYCbCrMatrix_ITU_R_601_4, 0) == kCFCompareEqualTo) - { - if (isFullYUVRange) - { - _preferredConversion = kColorConversion601FullRange; - } - else - { - _preferredConversion = kColorConversion601; - } - } - else - { - _preferredConversion = kColorConversion709; - } - } - else - { - if (isFullYUVRange) - { - _preferredConversion = kColorConversion601FullRange; - } - else - { - _preferredConversion = kColorConversion601; - } - } - - CMTime currentTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer); - - [GPUImageContext useImageProcessingContext]; - - if ([GPUImageContext supportsFastTextureUpload] && captureAsYUV) - { - CVOpenGLESTextureRef luminanceTextureRef = NULL; - CVOpenGLESTextureRef chrominanceTextureRef = NULL; - -// if (captureAsYUV && [GPUImageContext deviceSupportsRedTextures]) - if (CVPixelBufferGetPlaneCount(cameraFrame) > 0) // Check for YUV planar inputs to do RGB conversion - { - CVPixelBufferLockBaseAddress(cameraFrame, 0); - - if ( (imageBufferWidth != bufferWidth) && (imageBufferHeight != bufferHeight) ) - { - imageBufferWidth = bufferWidth; - imageBufferHeight = bufferHeight; - } - - CVReturn err; - // Y-plane - glActiveTexture(GL_TEXTURE4); - if ([GPUImageContext deviceSupportsRedTextures]) - { -// err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, coreVideoTextureCache, cameraFrame, NULL, GL_TEXTURE_2D, GL_RED_EXT, bufferWidth, bufferHeight, GL_RED_EXT, GL_UNSIGNED_BYTE, 0, &luminanceTextureRef); - err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, [[GPUImageContext sharedImageProcessingContext] coreVideoTextureCache], cameraFrame, NULL, GL_TEXTURE_2D, GL_LUMINANCE, bufferWidth, bufferHeight, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, &luminanceTextureRef); - } - else - { - err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, [[GPUImageContext sharedImageProcessingContext] coreVideoTextureCache], cameraFrame, NULL, GL_TEXTURE_2D, GL_LUMINANCE, bufferWidth, bufferHeight, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, &luminanceTextureRef); - } - if (err) - { - NSLog(@"Error at CVOpenGLESTextureCacheCreateTextureFromImage %d", err); - } - - luminanceTexture = CVOpenGLESTextureGetName(luminanceTextureRef); - glBindTexture(GL_TEXTURE_2D, luminanceTexture); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - // UV-plane - glActiveTexture(GL_TEXTURE5); - if ([GPUImageContext deviceSupportsRedTextures]) - { -// err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, coreVideoTextureCache, cameraFrame, NULL, GL_TEXTURE_2D, GL_RG_EXT, bufferWidth/2, bufferHeight/2, GL_RG_EXT, GL_UNSIGNED_BYTE, 1, &chrominanceTextureRef); - err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, [[GPUImageContext sharedImageProcessingContext] coreVideoTextureCache], cameraFrame, NULL, GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, bufferWidth/2, bufferHeight/2, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 1, &chrominanceTextureRef); - } - else - { - err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, [[GPUImageContext sharedImageProcessingContext] coreVideoTextureCache], cameraFrame, NULL, GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, bufferWidth/2, bufferHeight/2, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 1, &chrominanceTextureRef); - } - if (err) - { - NSLog(@"Error at CVOpenGLESTextureCacheCreateTextureFromImage %d", err); - } - - chrominanceTexture = CVOpenGLESTextureGetName(chrominanceTextureRef); - glBindTexture(GL_TEXTURE_2D, chrominanceTexture); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - -// if (!allTargetsWantMonochromeData) -// { - [self convertYUVToRGBOutput]; -// } - - int rotatedImageBufferWidth = bufferWidth, rotatedImageBufferHeight = bufferHeight; - - if (GPUImageRotationSwapsWidthAndHeight(internalRotation)) - { - rotatedImageBufferWidth = bufferHeight; - rotatedImageBufferHeight = bufferWidth; - } - - [self updateTargetsForVideoCameraUsingCacheTextureAtWidth:rotatedImageBufferWidth height:rotatedImageBufferHeight time:currentTime]; - - CVPixelBufferUnlockBaseAddress(cameraFrame, 0); - CFRelease(luminanceTextureRef); - CFRelease(chrominanceTextureRef); - } - else - { - // TODO: Mesh this with the output framebuffer structure - -// CVPixelBufferLockBaseAddress(cameraFrame, 0); -// -// CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, [[GPUImageContext sharedImageProcessingContext] coreVideoTextureCache], cameraFrame, NULL, GL_TEXTURE_2D, GL_RGBA, bufferWidth, bufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0, &texture); -// -// if (!texture || err) { -// NSLog(@"Camera CVOpenGLESTextureCacheCreateTextureFromImage failed (error: %d)", err); -// NSAssert(NO, @"Camera failure"); -// return; -// } -// -// outputTexture = CVOpenGLESTextureGetName(texture); -// // glBindTexture(CVOpenGLESTextureGetTarget(texture), outputTexture); -// glBindTexture(GL_TEXTURE_2D, outputTexture); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); -// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); -// -// [self updateTargetsForVideoCameraUsingCacheTextureAtWidth:bufferWidth height:bufferHeight time:currentTime]; -// -// CVPixelBufferUnlockBaseAddress(cameraFrame, 0); -// CFRelease(texture); -// -// outputTexture = 0; - } - - - if (_runBenchmark) - { - numberOfFramesCaptured++; - if (numberOfFramesCaptured > INITIALFRAMESTOIGNOREFORBENCHMARK) - { - CFAbsoluteTime currentFrameTime = (CFAbsoluteTimeGetCurrent() - startTime); - totalFrameTimeDuringCapture += currentFrameTime; - NSLog(@"Average frame time : %f ms", [self averageFrameDurationDuringCapture]); - NSLog(@"Current frame time : %f ms", 1000.0 * currentFrameTime); - } - } - } - else - { - CVPixelBufferLockBaseAddress(cameraFrame, 0); - - int bytesPerRow = (int) CVPixelBufferGetBytesPerRow(cameraFrame); - outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:CGSizeMake(bytesPerRow / 4, bufferHeight) onlyTexture:YES]; - [outputFramebuffer activateFramebuffer]; - - glBindTexture(GL_TEXTURE_2D, [outputFramebuffer texture]); - - // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bufferWidth, bufferHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, CVPixelBufferGetBaseAddress(cameraFrame)); - - // Using BGRA extension to pull in video frame data directly - // The use of bytesPerRow / 4 accounts for a display glitch present in preview video frames when using the photo preset on the camera - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bytesPerRow / 4, bufferHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, CVPixelBufferGetBaseAddress(cameraFrame)); - - [self updateTargetsForVideoCameraUsingCacheTextureAtWidth:bytesPerRow / 4 height:bufferHeight time:currentTime]; - - CVPixelBufferUnlockBaseAddress(cameraFrame, 0); - - if (_runBenchmark) - { - numberOfFramesCaptured++; - if (numberOfFramesCaptured > INITIALFRAMESTOIGNOREFORBENCHMARK) - { - CFAbsoluteTime currentFrameTime = (CFAbsoluteTimeGetCurrent() - startTime); - totalFrameTimeDuringCapture += currentFrameTime; - } - } - } -} - -- (void)processAudioSampleBuffer:(CMSampleBufferRef)sampleBuffer; -{ - [self.audioEncodingTarget processAudioBuffer:sampleBuffer]; -} - -- (void)convertYUVToRGBOutput; -{ - [GPUImageContext setActiveShaderProgram:yuvConversionProgram]; - - int rotatedImageBufferWidth = imageBufferWidth, rotatedImageBufferHeight = imageBufferHeight; - - if (GPUImageRotationSwapsWidthAndHeight(internalRotation)) - { - rotatedImageBufferWidth = imageBufferHeight; - rotatedImageBufferHeight = imageBufferWidth; - } - - outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:CGSizeMake(rotatedImageBufferWidth, rotatedImageBufferHeight) textureOptions:self.outputTextureOptions onlyTexture:NO]; - [outputFramebuffer activateFramebuffer]; - - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - static const GLfloat squareVertices[] = { - -1.0f, -1.0f, - 1.0f, -1.0f, - -1.0f, 1.0f, - 1.0f, 1.0f, - }; - - glActiveTexture(GL_TEXTURE4); - glBindTexture(GL_TEXTURE_2D, luminanceTexture); - glUniform1i(yuvConversionLuminanceTextureUniform, 4); - - glActiveTexture(GL_TEXTURE5); - glBindTexture(GL_TEXTURE_2D, chrominanceTexture); - glUniform1i(yuvConversionChrominanceTextureUniform, 5); - - glUniformMatrix3fv(yuvConversionMatrixUniform, 1, GL_FALSE, _preferredConversion); - - glVertexAttribPointer(yuvConversionPositionAttribute, 2, GL_FLOAT, 0, 0, squareVertices); - glVertexAttribPointer(yuvConversionTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, [GPUImageFilter textureCoordinatesForRotation:internalRotation]); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); -} - -#pragma mark - -#pragma mark Benchmarking - -- (CGFloat)averageFrameDurationDuringCapture; -{ - return (totalFrameTimeDuringCapture / (CGFloat)(numberOfFramesCaptured - INITIALFRAMESTOIGNOREFORBENCHMARK)) * 1000.0; -} - -- (void)resetBenchmarkAverage; -{ - numberOfFramesCaptured = 0; - totalFrameTimeDuringCapture = 0.0; -} - -#pragma mark - -#pragma mark AVCaptureVideoDataOutputSampleBufferDelegate - -- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection -{ - if (!self.captureSession.isRunning) - { - return; - } - else if (captureOutput == audioOutput) - { - [self processAudioSampleBuffer:sampleBuffer]; - } - else - { - if (dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_NOW) != 0) - { - return; - } - - CFRetain(sampleBuffer); - runAsynchronouslyOnVideoProcessingQueue(^{ - //Feature Detection Hook. - if (self.delegate) - { - [self.delegate willOutputSampleBuffer:sampleBuffer]; - } - - [self processVideoSampleBuffer:sampleBuffer]; - - CFRelease(sampleBuffer); - dispatch_semaphore_signal(frameRenderingSemaphore); - }); - } -} - -#pragma mark - -#pragma mark Accessors - -- (void)setAudioEncodingTarget:(GPUImageMovieWriter *)newValue; -{ - if (newValue) { - /* Add audio inputs and outputs, if necessary */ - addedAudioInputsDueToEncodingTarget |= [self addAudioInputsAndOutputs]; - } else if (addedAudioInputsDueToEncodingTarget) { - /* Remove audio inputs and outputs, if they were added by previously setting the audio encoding target */ - [self removeAudioInputsAndOutputs]; - addedAudioInputsDueToEncodingTarget = NO; - } - - [super setAudioEncodingTarget:newValue]; -} - -- (void)updateOrientationSendToTargets; -{ - runSynchronouslyOnVideoProcessingQueue(^{ - - // From the iOS 5.0 release notes: - // In previous iOS versions, the front-facing camera would always deliver buffers in AVCaptureVideoOrientationLandscapeLeft and the back-facing camera would always deliver buffers in AVCaptureVideoOrientationLandscapeRight. - - if (captureAsYUV && [GPUImageContext supportsFastTextureUpload]) - { - outputRotation = kGPUImageNoRotation; - if ([self cameraPosition] == AVCaptureDevicePositionBack) - { - if (_horizontallyMirrorRearFacingCamera) - { - switch(_outputImageOrientation) - { - case UIInterfaceOrientationPortrait:internalRotation = kGPUImageRotateRightFlipVertical; break; - case UIInterfaceOrientationPortraitUpsideDown:internalRotation = kGPUImageRotate180; break; - case UIInterfaceOrientationLandscapeLeft:internalRotation = kGPUImageFlipHorizonal; break; - case UIInterfaceOrientationLandscapeRight:internalRotation = kGPUImageFlipVertical; break; - default:internalRotation = kGPUImageNoRotation; - } - } - else - { - switch(_outputImageOrientation) - { - case UIInterfaceOrientationPortrait:internalRotation = kGPUImageRotateRight; break; - case UIInterfaceOrientationPortraitUpsideDown:internalRotation = kGPUImageRotateLeft; break; - case UIInterfaceOrientationLandscapeLeft:internalRotation = kGPUImageRotate180; break; - case UIInterfaceOrientationLandscapeRight:internalRotation = kGPUImageNoRotation; break; - default:internalRotation = kGPUImageNoRotation; - } - } - } - else - { - if (_horizontallyMirrorFrontFacingCamera) - { - switch(_outputImageOrientation) - { - case UIInterfaceOrientationPortrait:internalRotation = kGPUImageRotateRightFlipVertical; break; - case UIInterfaceOrientationPortraitUpsideDown:internalRotation = kGPUImageRotateRightFlipHorizontal; break; - case UIInterfaceOrientationLandscapeLeft:internalRotation = kGPUImageFlipHorizonal; break; - case UIInterfaceOrientationLandscapeRight:internalRotation = kGPUImageFlipVertical; break; - default:internalRotation = kGPUImageNoRotation; - } - } - else - { - switch(_outputImageOrientation) - { - case UIInterfaceOrientationPortrait:internalRotation = kGPUImageRotateRight; break; - case UIInterfaceOrientationPortraitUpsideDown:internalRotation = kGPUImageRotateLeft; break; - case UIInterfaceOrientationLandscapeLeft:internalRotation = kGPUImageNoRotation; break; - case UIInterfaceOrientationLandscapeRight:internalRotation = kGPUImageRotate180; break; - default:internalRotation = kGPUImageNoRotation; - } - } - } - } - else - { - if ([self cameraPosition] == AVCaptureDevicePositionBack) - { - if (_horizontallyMirrorRearFacingCamera) - { - switch(_outputImageOrientation) - { - case UIInterfaceOrientationPortrait:outputRotation = kGPUImageRotateRightFlipVertical; break; - case UIInterfaceOrientationPortraitUpsideDown:outputRotation = kGPUImageRotate180; break; - case UIInterfaceOrientationLandscapeLeft:outputRotation = kGPUImageFlipHorizonal; break; - case UIInterfaceOrientationLandscapeRight:outputRotation = kGPUImageFlipVertical; break; - default:outputRotation = kGPUImageNoRotation; - } - } - else - { - switch(_outputImageOrientation) - { - case UIInterfaceOrientationPortrait:outputRotation = kGPUImageRotateRight; break; - case UIInterfaceOrientationPortraitUpsideDown:outputRotation = kGPUImageRotateLeft; break; - case UIInterfaceOrientationLandscapeLeft:outputRotation = kGPUImageRotate180; break; - case UIInterfaceOrientationLandscapeRight:outputRotation = kGPUImageNoRotation; break; - default:outputRotation = kGPUImageNoRotation; - } - } - } - else - { - if (_horizontallyMirrorFrontFacingCamera) - { - switch(_outputImageOrientation) - { - case UIInterfaceOrientationPortrait:outputRotation = kGPUImageRotateRightFlipVertical; break; - case UIInterfaceOrientationPortraitUpsideDown:outputRotation = kGPUImageRotateRightFlipHorizontal; break; - case UIInterfaceOrientationLandscapeLeft:outputRotation = kGPUImageFlipHorizonal; break; - case UIInterfaceOrientationLandscapeRight:outputRotation = kGPUImageFlipVertical; break; - default:outputRotation = kGPUImageNoRotation; - } - } - else - { - switch(_outputImageOrientation) - { - case UIInterfaceOrientationPortrait:outputRotation = kGPUImageRotateRight; break; - case UIInterfaceOrientationPortraitUpsideDown:outputRotation = kGPUImageRotateLeft; break; - case UIInterfaceOrientationLandscapeLeft:outputRotation = kGPUImageNoRotation; break; - case UIInterfaceOrientationLandscapeRight:outputRotation = kGPUImageRotate180; break; - default:outputRotation = kGPUImageNoRotation; - } - } - } - } - - for (id currentTarget in targets) - { - NSInteger indexOfObject = [targets indexOfObject:currentTarget]; - [currentTarget setInputRotation:outputRotation atIndex:[[targetTextureIndices objectAtIndex:indexOfObject] integerValue]]; - } - }); -} - -- (void)setOutputImageOrientation:(UIInterfaceOrientation)newValue; -{ - _outputImageOrientation = newValue; - [self updateOrientationSendToTargets]; -} - -- (void)setHorizontallyMirrorFrontFacingCamera:(BOOL)newValue -{ - _horizontallyMirrorFrontFacingCamera = newValue; - [self updateOrientationSendToTargets]; -} - -- (void)setHorizontallyMirrorRearFacingCamera:(BOOL)newValue -{ - _horizontallyMirrorRearFacingCamera = newValue; - [self updateOrientationSendToTargets]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVignetteFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVignetteFilter.h deleted file mode 100755 index 37be9449..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVignetteFilter.h +++ /dev/null @@ -1,22 +0,0 @@ -#import "GPUImageFilter.h" - -/** Performs a vignetting effect, fading out the image at the edges - */ -@interface GPUImageVignetteFilter : GPUImageFilter -{ - GLint vignetteCenterUniform, vignetteColorUniform, vignetteStartUniform, vignetteEndUniform; -} - -// the center for the vignette in tex coords (defaults to 0.5, 0.5) -@property (nonatomic, readwrite) CGPoint vignetteCenter; - -// The color to use for the Vignette (defaults to black) -@property (nonatomic, readwrite) GPUVector3 vignetteColor; - -// The normalized distance from the center where the vignette effect starts. Default of 0.5. -@property (nonatomic, readwrite) CGFloat vignetteStart; - -// The normalized distance from the center where the vignette effect ends. Default of 0.75. -@property (nonatomic, readwrite) CGFloat vignetteEnd; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVignetteFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVignetteFilter.m deleted file mode 100755 index 6e1eadb2..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVignetteFilter.m +++ /dev/null @@ -1,104 +0,0 @@ -#import "GPUImageVignetteFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageVignetteFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - varying highp vec2 textureCoordinate; - - uniform lowp vec2 vignetteCenter; - uniform lowp vec3 vignetteColor; - uniform highp float vignetteStart; - uniform highp float vignetteEnd; - - void main() - { - lowp vec4 sourceImageColor = texture2D(inputImageTexture, textureCoordinate); - lowp float d = distance(textureCoordinate, vec2(vignetteCenter.x, vignetteCenter.y)); - lowp float percent = smoothstep(vignetteStart, vignetteEnd, d); - gl_FragColor = vec4(mix(sourceImageColor.rgb, vignetteColor, percent), sourceImageColor.a); - } -); -#else -NSString *const kGPUImageVignetteFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - varying vec2 textureCoordinate; - - uniform vec2 vignetteCenter; - uniform vec3 vignetteColor; - uniform float vignetteStart; - uniform float vignetteEnd; - - void main() - { - vec4 sourceImageColor = texture2D(inputImageTexture, textureCoordinate); - float d = distance(textureCoordinate, vec2(vignetteCenter.x, vignetteCenter.y)); - float percent = smoothstep(vignetteStart, vignetteEnd, d); - gl_FragColor = vec4(mix(sourceImageColor.rgb, vignetteColor, percent), sourceImageColor.a); - } -); -#endif - -@implementation GPUImageVignetteFilter - -@synthesize vignetteCenter = _vignetteCenter; -@synthesize vignetteColor = _vignetteColor; -@synthesize vignetteStart =_vignetteStart; -@synthesize vignetteEnd = _vignetteEnd; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageVignetteFragmentShaderString])) - { - return nil; - } - - vignetteCenterUniform = [filterProgram uniformIndex:@"vignetteCenter"]; - vignetteColorUniform = [filterProgram uniformIndex:@"vignetteColor"]; - vignetteStartUniform = [filterProgram uniformIndex:@"vignetteStart"]; - vignetteEndUniform = [filterProgram uniformIndex:@"vignetteEnd"]; - - self.vignetteCenter = (CGPoint){ 0.5f, 0.5f }; - self.vignetteColor = (GPUVector3){ 0.0f, 0.0f, 0.0f }; - self.vignetteStart = 0.3; - self.vignetteEnd = 0.75; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setVignetteCenter:(CGPoint)newValue -{ - _vignetteCenter = newValue; - - [self setPoint:newValue forUniform:vignetteCenterUniform program:filterProgram]; -} - -- (void)setVignetteColor:(GPUVector3)newValue -{ - _vignetteColor = newValue; - - [self setVec3:newValue forUniform:vignetteColorUniform program:filterProgram]; -} - -- (void)setVignetteStart:(CGFloat)newValue; -{ - _vignetteStart = newValue; - - [self setFloat:_vignetteStart forUniform:vignetteStartUniform program:filterProgram]; -} - -- (void)setVignetteEnd:(CGFloat)newValue; -{ - _vignetteEnd = newValue; - - [self setFloat:_vignetteEnd forUniform:vignetteEndUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVoronoiConsumerFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVoronoiConsumerFilter.h deleted file mode 100644 index 659e39d5..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVoronoiConsumerFilter.h +++ /dev/null @@ -1,10 +0,0 @@ -#import "GPUImageTwoInputFilter.h" - -@interface GPUImageVoronoiConsumerFilter : GPUImageTwoInputFilter -{ - GLint sizeUniform; -} - -@property (nonatomic, readwrite) CGSize sizeInPixels; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVoronoiConsumerFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVoronoiConsumerFilter.m deleted file mode 100644 index c12c34f4..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageVoronoiConsumerFilter.m +++ /dev/null @@ -1,94 +0,0 @@ -#import "GPUImageVoronoiConsumerFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageVoronoiConsumerFragmentShaderString = SHADER_STRING -( - - precision highp float; - - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - uniform vec2 size; - varying vec2 textureCoordinate; - - vec2 getCoordFromColor(vec4 color) -{ - float z = color.z * 256.0; - float yoff = floor(z / 8.0); - float xoff = mod(z, 8.0); - float x = color.x*256.0 + xoff*256.0; - float y = color.y*256.0 + yoff*256.0; - return vec2(x,y) / size; -} - - void main(void) { - vec4 colorLoc = texture2D(inputImageTexture2, textureCoordinate); - vec4 color = texture2D(inputImageTexture, getCoordFromColor(colorLoc)); - - gl_FragColor = color; - } -); -#else -NSString *const kGPUImageVoronoiConsumerFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - uniform sampler2D inputImageTexture2; - uniform vec2 size; - varying vec2 textureCoordinate; - - vec2 getCoordFromColor(vec4 color) - { - float z = color.z * 256.0; - float yoff = floor(z / 8.0); - float xoff = mod(z, 8.0); - float x = color.x*256.0 + xoff*256.0; - float y = color.y*256.0 + yoff*256.0; - return vec2(x,y) / size; - } - - void main(void) - { - vec4 colorLoc = texture2D(inputImageTexture2, textureCoordinate); - vec4 color = texture2D(inputImageTexture, getCoordFromColor(colorLoc)); - - gl_FragColor = color; - } -); -#endif - -@implementation GPUImageVoronoiConsumerFilter - -@synthesize sizeInPixels = _sizeInPixels; - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageVoronoiConsumerFragmentShaderString])) - { - return nil; - } - - sizeUniform = [filterProgram uniformIndex:@"size"]; - - return self; -} - --(void)setSizeInPixels:(CGSize)sizeInPixels { - _sizeInPixels = sizeInPixels; - - //validate that it's a power of 2 and square - - float width = log2(sizeInPixels.width); - float height = log2(sizeInPixels.height); - - if (width != height) { - NSLog(@"Voronoi point texture must be square"); - return; - } - if (width != floor(width) || height != floor(height)) { - NSLog(@"Voronoi point texture must be a power of 2. Texture size %f, %f", sizeInPixels.width, sizeInPixels.height); - return; - } - glUniform2f(sizeUniform, _sizeInPixels.width, _sizeInPixels.height); -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageWeakPixelInclusionFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageWeakPixelInclusionFilter.h deleted file mode 100644 index 44b76c6a..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageWeakPixelInclusionFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImage3x3TextureSamplingFilter.h" - -@interface GPUImageWeakPixelInclusionFilter : GPUImage3x3TextureSamplingFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageWeakPixelInclusionFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageWeakPixelInclusionFilter.m deleted file mode 100644 index 4e95ad5d..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageWeakPixelInclusionFilter.m +++ /dev/null @@ -1,94 +0,0 @@ -#import "GPUImageWeakPixelInclusionFilter.h" - -@implementation GPUImageWeakPixelInclusionFilter - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageWeakPixelInclusionFragmentShaderString = SHADER_STRING -( - precision lowp float; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r; - float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r; - float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r; - float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r; - float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r; - float centerIntensity = texture2D(inputImageTexture, textureCoordinate).r; - - float pixelIntensitySum = bottomLeftIntensity + topRightIntensity + topLeftIntensity + bottomRightIntensity + leftIntensity + rightIntensity + bottomIntensity + topIntensity + centerIntensity; - float sumTest = step(1.5, pixelIntensitySum); - float pixelTest = step(0.01, centerIntensity); - - gl_FragColor = vec4(vec3(sumTest * pixelTest), 1.0); - } -); -#else -NSString *const kGPUImageWeakPixelInclusionFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r; - float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r; - float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r; - float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r; - float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r; - float centerIntensity = texture2D(inputImageTexture, textureCoordinate).r; - - float pixelIntensitySum = bottomLeftIntensity + topRightIntensity + topLeftIntensity + bottomRightIntensity + leftIntensity + rightIntensity + bottomIntensity + topIntensity + centerIntensity; - float sumTest = step(1.5, pixelIntensitySum); - float pixelTest = step(0.01, centerIntensity); - - gl_FragColor = vec4(vec3(sumTest * pixelTest), 1.0); - } -); -#endif - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [self initWithFragmentShaderFromString:kGPUImageWeakPixelInclusionFragmentShaderString])) - { - return nil; - } - - return self; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageWhiteBalanceFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageWhiteBalanceFilter.h deleted file mode 100644 index 6b09c33d..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageWhiteBalanceFilter.h +++ /dev/null @@ -1,17 +0,0 @@ -#import "GPUImageFilter.h" -/** - * Created by Alaric Cole - * Allows adjustment of color temperature in terms of what an image was effectively shot in. This means higher Kelvin values will warm the image, while lower values will cool it. - - */ -@interface GPUImageWhiteBalanceFilter : GPUImageFilter -{ - GLint temperatureUniform, tintUniform; -} -//choose color temperature, in degrees Kelvin -@property(readwrite, nonatomic) CGFloat temperature; - -//adjust tint to compensate -@property(readwrite, nonatomic) CGFloat tint; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageWhiteBalanceFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageWhiteBalanceFilter.m deleted file mode 100644 index 17c9bce9..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageWhiteBalanceFilter.m +++ /dev/null @@ -1,107 +0,0 @@ -#import "GPUImageWhiteBalanceFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageWhiteBalanceFragmentShaderString = SHADER_STRING -( -uniform sampler2D inputImageTexture; -varying highp vec2 textureCoordinate; - -uniform lowp float temperature; -uniform lowp float tint; - -const lowp vec3 warmFilter = vec3(0.93, 0.54, 0.0); - -const mediump mat3 RGBtoYIQ = mat3(0.299, 0.587, 0.114, 0.596, -0.274, -0.322, 0.212, -0.523, 0.311); -const mediump mat3 YIQtoRGB = mat3(1.0, 0.956, 0.621, 1.0, -0.272, -0.647, 1.0, -1.105, 1.702); - -void main() -{ - lowp vec4 source = texture2D(inputImageTexture, textureCoordinate); - - mediump vec3 yiq = RGBtoYIQ * source.rgb; //adjusting tint - yiq.b = clamp(yiq.b + tint*0.5226*0.1, -0.5226, 0.5226); - lowp vec3 rgb = YIQtoRGB * yiq; - - lowp vec3 processed = vec3( - (rgb.r < 0.5 ? (2.0 * rgb.r * warmFilter.r) : (1.0 - 2.0 * (1.0 - rgb.r) * (1.0 - warmFilter.r))), //adjusting temperature - (rgb.g < 0.5 ? (2.0 * rgb.g * warmFilter.g) : (1.0 - 2.0 * (1.0 - rgb.g) * (1.0 - warmFilter.g))), - (rgb.b < 0.5 ? (2.0 * rgb.b * warmFilter.b) : (1.0 - 2.0 * (1.0 - rgb.b) * (1.0 - warmFilter.b)))); - - gl_FragColor = vec4(mix(rgb, processed, temperature), source.a); -} -); -#else -NSString *const kGPUImageWhiteBalanceFragmentShaderString = SHADER_STRING -( - uniform sampler2D inputImageTexture; - varying vec2 textureCoordinate; - - uniform float temperature; - uniform float tint; - - const vec3 warmFilter = vec3(0.93, 0.54, 0.0); - - const mat3 RGBtoYIQ = mat3(0.299, 0.587, 0.114, 0.596, -0.274, -0.322, 0.212, -0.523, 0.311); - const mat3 YIQtoRGB = mat3(1.0, 0.956, 0.621, 1.0, -0.272, -0.647, 1.0, -1.105, 1.702); - - void main() -{ - vec4 source = texture2D(inputImageTexture, textureCoordinate); - - vec3 yiq = RGBtoYIQ * source.rgb; //adjusting tint - yiq.b = clamp(yiq.b + tint*0.5226*0.1, -0.5226, 0.5226); - vec3 rgb = YIQtoRGB * yiq; - - vec3 processed = vec3( - (rgb.r < 0.5 ? (2.0 * rgb.r * warmFilter.r) : (1.0 - 2.0 * (1.0 - rgb.r) * (1.0 - warmFilter.r))), //adjusting temperature - (rgb.g < 0.5 ? (2.0 * rgb.g * warmFilter.g) : (1.0 - 2.0 * (1.0 - rgb.g) * (1.0 - warmFilter.g))), - (rgb.b < 0.5 ? (2.0 * rgb.b * warmFilter.b) : (1.0 - 2.0 * (1.0 - rgb.b) * (1.0 - warmFilter.b)))); - - gl_FragColor = vec4(mix(rgb, processed, temperature), source.a); -} -); -#endif - -@implementation GPUImageWhiteBalanceFilter - -@synthesize temperature = _temperature; -@synthesize tint = _tint; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageWhiteBalanceFragmentShaderString])) - { - return nil; - } - - temperatureUniform = [filterProgram uniformIndex:@"temperature"]; - tintUniform = [filterProgram uniformIndex:@"tint"]; - - self.temperature = 5000.0; - self.tint = 0.0; - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setTemperature:(CGFloat)newValue; -{ - _temperature = newValue; - - [self setFloat:_temperature < 5000 ? 0.0004 * (_temperature-5000.0) : 0.00006 * (_temperature-5000.0) forUniform:temperatureUniform program:filterProgram]; -} - -- (void)setTint:(CGFloat)newValue; -{ - _tint = newValue; - - [self setFloat:_tint / 100.0 forUniform:tintUniform program:filterProgram]; -} - -@end - diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageXYDerivativeFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageXYDerivativeFilter.h deleted file mode 100755 index 8db57457..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageXYDerivativeFilter.h +++ /dev/null @@ -1,5 +0,0 @@ -#import "GPUImageSobelEdgeDetectionFilter.h" - -@interface GPUImageXYDerivativeFilter : GPUImageSobelEdgeDetectionFilter - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageXYDerivativeFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageXYDerivativeFilter.m deleted file mode 100755 index 7e19e9d4..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageXYDerivativeFilter.m +++ /dev/null @@ -1,106 +0,0 @@ -#import "GPUImageXYDerivativeFilter.h" - -// I'm using the Prewitt operator to obtain the derivative, then squaring the X and Y components and placing the product of the two in Z. -// In tests, Prewitt seemed to be tied with Sobel for the best, and it's just a little cheaper to compute. -// This is primarily intended to be used with corner detection filters. - -@implementation GPUImageXYDerivativeFilter - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageGradientFragmentShaderString = SHADER_STRING -( - precision highp float; - - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform float edgeStrength; - - void main() - { - float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r; - float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r; - float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r; - float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r; - float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r; - - float verticalDerivative = -topLeftIntensity - topIntensity - topRightIntensity + bottomLeftIntensity + bottomIntensity + bottomRightIntensity; - float horizontalDerivative = -bottomLeftIntensity - leftIntensity - topLeftIntensity + bottomRightIntensity + rightIntensity + topRightIntensity; - verticalDerivative = verticalDerivative * edgeStrength; - horizontalDerivative = horizontalDerivative * edgeStrength; - - // Scaling the X * Y operation so that negative numbers are not clipped in the 0..1 range. This will be expanded in the corner detection filter - gl_FragColor = vec4(horizontalDerivative * horizontalDerivative, verticalDerivative * verticalDerivative, ((verticalDerivative * horizontalDerivative) + 1.0) / 2.0, 1.0); - } -); -#else -NSString *const kGPUImageGradientFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - varying vec2 leftTextureCoordinate; - varying vec2 rightTextureCoordinate; - - varying vec2 topTextureCoordinate; - varying vec2 topLeftTextureCoordinate; - varying vec2 topRightTextureCoordinate; - - varying vec2 bottomTextureCoordinate; - varying vec2 bottomLeftTextureCoordinate; - varying vec2 bottomRightTextureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform float edgeStrength; - - void main() - { - float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r; - float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r; - float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r; - float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r; - float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r; - float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r; - float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r; - float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r; - - float verticalDerivative = -topLeftIntensity - topIntensity - topRightIntensity + bottomLeftIntensity + bottomIntensity + bottomRightIntensity; - float horizontalDerivative = -bottomLeftIntensity - leftIntensity - topLeftIntensity + bottomRightIntensity + rightIntensity + topRightIntensity; - verticalDerivative = verticalDerivative * edgeStrength; - horizontalDerivative = horizontalDerivative * edgeStrength; - - // Scaling the X * Y operation so that negative numbers are not clipped in the 0..1 range. This will be expanded in the corner detection filter - gl_FragColor = vec4(horizontalDerivative * horizontalDerivative, verticalDerivative * verticalDerivative, ((verticalDerivative * horizontalDerivative) + 1.0) / 2.0, 1.0); - } -); -#endif - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [self initWithFragmentShaderFromString:kGPUImageGradientFragmentShaderString])) - { - return nil; - } - - self.edgeStrength = 1.0; - - return self; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageZoomBlurFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageZoomBlurFilter.h deleted file mode 100644 index 744a72cb..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageZoomBlurFilter.h +++ /dev/null @@ -1,13 +0,0 @@ -#import "GPUImageFilter.h" - -@interface GPUImageZoomBlurFilter : GPUImageFilter - -/** A multiplier for the blur size, ranging from 0.0 on up, with a default of 1.0 - */ -@property (readwrite, nonatomic) CGFloat blurSize; - -/** The normalized center of the blur. (0.5, 0.5) by default - */ -@property (readwrite, nonatomic) CGPoint blurCenter; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageZoomBlurFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageZoomBlurFilter.m deleted file mode 100644 index 2ae84934..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageZoomBlurFilter.m +++ /dev/null @@ -1,115 +0,0 @@ -#import "GPUImageZoomBlurFilter.h" - -#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE -NSString *const kGPUImageZoomBlurFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform highp vec2 blurCenter; - uniform highp float blurSize; - - void main() - { - // TODO: Do a more intelligent scaling based on resolution here - highp vec2 samplingOffset = 1.0/100.0 * (blurCenter - textureCoordinate) * blurSize; - - lowp vec4 fragmentColor = texture2D(inputImageTexture, textureCoordinate) * 0.18; - fragmentColor += texture2D(inputImageTexture, textureCoordinate + samplingOffset) * 0.15; - fragmentColor += texture2D(inputImageTexture, textureCoordinate + (2.0 * samplingOffset)) * 0.12; - fragmentColor += texture2D(inputImageTexture, textureCoordinate + (3.0 * samplingOffset)) * 0.09; - fragmentColor += texture2D(inputImageTexture, textureCoordinate + (4.0 * samplingOffset)) * 0.05; - fragmentColor += texture2D(inputImageTexture, textureCoordinate - samplingOffset) * 0.15; - fragmentColor += texture2D(inputImageTexture, textureCoordinate - (2.0 * samplingOffset)) * 0.12; - fragmentColor += texture2D(inputImageTexture, textureCoordinate - (3.0 * samplingOffset)) * 0.09; - fragmentColor += texture2D(inputImageTexture, textureCoordinate - (4.0 * samplingOffset)) * 0.05; - - gl_FragColor = fragmentColor; - } -); -#else -NSString *const kGPUImageZoomBlurFragmentShaderString = SHADER_STRING -( - varying vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - uniform vec2 blurCenter; - uniform float blurSize; - - void main() - { - // TODO: Do a more intelligent scaling based on resolution here - vec2 samplingOffset = 1.0/100.0 * (blurCenter - textureCoordinate) * blurSize; - - vec4 fragmentColor = texture2D(inputImageTexture, textureCoordinate) * 0.18; - fragmentColor += texture2D(inputImageTexture, textureCoordinate + samplingOffset) * 0.15; - fragmentColor += texture2D(inputImageTexture, textureCoordinate + (2.0 * samplingOffset)) * 0.12; - fragmentColor += texture2D(inputImageTexture, textureCoordinate + (3.0 * samplingOffset)) * 0.09; - fragmentColor += texture2D(inputImageTexture, textureCoordinate + (4.0 * samplingOffset)) * 0.05; - fragmentColor += texture2D(inputImageTexture, textureCoordinate - samplingOffset) * 0.15; - fragmentColor += texture2D(inputImageTexture, textureCoordinate - (2.0 * samplingOffset)) * 0.12; - fragmentColor += texture2D(inputImageTexture, textureCoordinate - (3.0 * samplingOffset)) * 0.09; - fragmentColor += texture2D(inputImageTexture, textureCoordinate - (4.0 * samplingOffset)) * 0.05; - - gl_FragColor = fragmentColor; - } -); -#endif - -@interface GPUImageZoomBlurFilter() -{ - GLint blurSizeUniform, blurCenterUniform; -} -@end - -@implementation GPUImageZoomBlurFilter - -@synthesize blurSize = _blurSize; -@synthesize blurCenter = _blurCenter; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super initWithFragmentShaderFromString:kGPUImageZoomBlurFragmentShaderString])) - { - return nil; - } - - blurSizeUniform = [filterProgram uniformIndex:@"blurSize"]; - blurCenterUniform = [filterProgram uniformIndex:@"blurCenter"]; - - self.blurSize = 1.0; - self.blurCenter = CGPointMake(0.5, 0.5); - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -{ - [super setInputRotation:newInputRotation atIndex:textureIndex]; - [self setBlurCenter:self.blurCenter]; -} - -- (void)setBlurSize:(CGFloat)newValue; -{ - _blurSize = newValue; - - [self setFloat:_blurSize forUniform:blurSizeUniform program:filterProgram]; -} - -- (void)setBlurCenter:(CGPoint)newValue; -{ - _blurCenter = newValue; - - CGPoint rotatedPoint = [self rotatedPoint:_blurCenter forRotation:inputRotation]; - [self setPoint:rotatedPoint forUniform:blurCenterUniform program:filterProgram]; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageiOSBlurFilter.h b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageiOSBlurFilter.h deleted file mode 100644 index 261d0d7c..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageiOSBlurFilter.h +++ /dev/null @@ -1,31 +0,0 @@ -#import "GPUImageFilterGroup.h" - -@class GPUImageSaturationFilter; -@class GPUImageGaussianBlurFilter; -@class GPUImageLuminanceRangeFilter; - -@interface GPUImageiOSBlurFilter : GPUImageFilterGroup -{ - GPUImageSaturationFilter *saturationFilter; - GPUImageGaussianBlurFilter *blurFilter; - GPUImageLuminanceRangeFilter *luminanceRangeFilter; -} - -/** A radius in pixels to use for the blur, with a default of 12.0. This adjusts the sigma variable in the Gaussian distribution function. - */ -@property (readwrite, nonatomic) CGFloat blurRadiusInPixels; - -/** Saturation ranges from 0.0 (fully desaturated) to 2.0 (max saturation), with 0.8 as the normal level - */ -@property (readwrite, nonatomic) CGFloat saturation; - -/** The degree to which to downsample, then upsample the incoming image to minimize computations within the Gaussian blur, default of 4.0 - */ -@property (readwrite, nonatomic) CGFloat downsampling; - - -/** The degree to reduce the luminance range, from 0.0 to 1.0. Default is 0.6. - */ -@property (readwrite, nonatomic) CGFloat rangeReductionFactor; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageiOSBlurFilter.m b/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageiOSBlurFilter.m deleted file mode 100644 index 18533213..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/GPUImageiOSBlurFilter.m +++ /dev/null @@ -1,114 +0,0 @@ -#import "GPUImageiOSBlurFilter.h" -#import "GPUImageSaturationFilter.h" -#import "GPUImageGaussianBlurFilter.h" -#import "GPUImageLuminanceRangeFilter.h" - -@implementation GPUImageiOSBlurFilter - -@synthesize blurRadiusInPixels; -@synthesize saturation; -@synthesize downsampling = _downsampling; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)init; -{ - if (!(self = [super init])) - { - return nil; - } - - // First pass: downsample and desaturate - saturationFilter = [[GPUImageSaturationFilter alloc] init]; - [self addFilter:saturationFilter]; - - // Second pass: apply a strong Gaussian blur - blurFilter = [[GPUImageGaussianBlurFilter alloc] init]; - [self addFilter:blurFilter]; - - // Third pass: upsample and adjust luminance range - luminanceRangeFilter = [[GPUImageLuminanceRangeFilter alloc] init]; - [self addFilter:luminanceRangeFilter]; - - [saturationFilter addTarget:blurFilter]; - [blurFilter addTarget:luminanceRangeFilter]; - - self.initialFilters = [NSArray arrayWithObject:saturationFilter]; - self.terminalFilter = luminanceRangeFilter; - - self.blurRadiusInPixels = 12.0; - self.saturation = 0.8; - self.downsampling = 4.0; - self.rangeReductionFactor = 0.6; - - return self; -} - -- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex; -{ - if (_downsampling > 1.0) - { - CGSize rotatedSize = [saturationFilter rotatedSize:newSize forIndex:textureIndex]; - - [saturationFilter forceProcessingAtSize:CGSizeMake(rotatedSize.width / _downsampling, rotatedSize.height / _downsampling)]; - [luminanceRangeFilter forceProcessingAtSize:rotatedSize]; - } - - [super setInputSize:newSize atIndex:textureIndex]; -} - -#pragma mark - -#pragma mark Accessors - -// From Apple's UIImage+ImageEffects category: - -// A description of how to compute the box kernel width from the Gaussian -// radius (aka standard deviation) appears in the SVG spec: -// http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement -// -// For larger values of 's' (s >= 2.0), an approximation can be used: Three -// successive box-blurs build a piece-wise quadratic convolution kernel, which -// approximates the Gaussian kernel to within roughly 3%. -// -// let d = floor(s * 3*sqrt(2*pi)/4 + 0.5) -// -// ... if d is odd, use three box-blurs of size 'd', centered on the output pixel. - - -- (void)setBlurRadiusInPixels:(CGFloat)newValue; -{ - blurFilter.blurRadiusInPixels = newValue; -} - -- (CGFloat)blurRadiusInPixels; -{ - return blurFilter.blurRadiusInPixels; -} - -- (void)setSaturation:(CGFloat)newValue; -{ - saturationFilter.saturation = newValue; -} - -- (CGFloat)saturation; -{ - return saturationFilter.saturation; -} - -- (void)setDownsampling:(CGFloat)newValue; -{ - _downsampling = newValue; -} - -- (void)setRangeReductionFactor:(CGFloat)rangeReductionFactor -{ - luminanceRangeFilter.rangeReductionFactor = rangeReductionFactor; -} - -- (CGFloat)rangeReductionFactor -{ - return luminanceRangeFilter.rangeReductionFactor; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/iOS/Framework/GPUImageFramework.h b/iOS_Tips/Pods/GPUImage/framework/Source/iOS/Framework/GPUImageFramework.h deleted file mode 100644 index ea12ac09..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/iOS/Framework/GPUImageFramework.h +++ /dev/null @@ -1,172 +0,0 @@ -#import - -//! Project version number for GPUImageFramework. -FOUNDATION_EXPORT double GPUImageFrameworkVersionNumber; - -//! Project version string for GPUImageFramework. -FOUNDATION_EXPORT const unsigned char GPUImageFrameworkVersionString[]; - -#import - -// Base classes -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -// Filters -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageContext.h b/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageContext.h deleted file mode 100755 index 7e4fa035..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageContext.h +++ /dev/null @@ -1,55 +0,0 @@ -#import "GLProgram.h" -#import "GPUImageFramebuffer.h" -#import "GPUImageFramebufferCache.h" - -#define GPUImageRotationSwapsWidthAndHeight(rotation) ((rotation) == kGPUImageRotateLeft || (rotation) == kGPUImageRotateRight || (rotation) == kGPUImageRotateRightFlipVertical || (rotation) == kGPUImageRotateRightFlipHorizontal) - -typedef enum { kGPUImageNoRotation, kGPUImageRotateLeft, kGPUImageRotateRight, kGPUImageFlipVertical, kGPUImageFlipHorizonal, kGPUImageRotateRightFlipVertical, kGPUImageRotateRightFlipHorizontal, kGPUImageRotate180 } GPUImageRotationMode; - -@interface GPUImageContext : NSObject - -@property(readonly, nonatomic) dispatch_queue_t contextQueue; -@property(readwrite, retain, nonatomic) GLProgram *currentShaderProgram; -@property(readonly, retain, nonatomic) EAGLContext *context; -@property(readonly) CVOpenGLESTextureCacheRef coreVideoTextureCache; -@property(readonly) GPUImageFramebufferCache *framebufferCache; - -+ (void *)contextKey; -+ (GPUImageContext *)sharedImageProcessingContext; -+ (dispatch_queue_t)sharedContextQueue; -+ (GPUImageFramebufferCache *)sharedFramebufferCache; -+ (void)useImageProcessingContext; -- (void)useAsCurrentContext; -+ (void)setActiveShaderProgram:(GLProgram *)shaderProgram; -- (void)setContextShaderProgram:(GLProgram *)shaderProgram; -+ (GLint)maximumTextureSizeForThisDevice; -+ (GLint)maximumTextureUnitsForThisDevice; -+ (GLint)maximumVaryingVectorsForThisDevice; -+ (BOOL)deviceSupportsOpenGLESExtension:(NSString *)extension; -+ (BOOL)deviceSupportsRedTextures; -+ (BOOL)deviceSupportsFramebufferReads; -+ (CGSize)sizeThatFitsWithinATextureForSize:(CGSize)inputSize; - -- (void)presentBufferForDisplay; -- (GLProgram *)programForVertexShaderString:(NSString *)vertexShaderString fragmentShaderString:(NSString *)fragmentShaderString; - -- (void)useSharegroup:(EAGLSharegroup *)sharegroup; - -// Manage fast texture upload -+ (BOOL)supportsFastTextureUpload; - -@end - -@protocol GPUImageInput -- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex; -- (void)setInputFramebuffer:(GPUImageFramebuffer *)newInputFramebuffer atIndex:(NSInteger)textureIndex; -- (NSInteger)nextAvailableTextureIndex; -- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex; -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -- (CGSize)maximumOutputSize; -- (void)endProcessing; -- (BOOL)shouldIgnoreUpdatesToThisTarget; -- (BOOL)enabled; -- (BOOL)wantsMonochromeInput; -- (void)setCurrentlyReceivingMonochromeInput:(BOOL)newValue; -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageContext.m b/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageContext.m deleted file mode 100755 index 19546ba9..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageContext.m +++ /dev/null @@ -1,318 +0,0 @@ -#import "GPUImageContext.h" -#import -#import - -#define MAXSHADERPROGRAMSALLOWEDINCACHE 40 - -@interface GPUImageContext() -{ - NSMutableDictionary *shaderProgramCache; - NSMutableArray *shaderProgramUsageHistory; - EAGLSharegroup *_sharegroup; -} - -@end - -@implementation GPUImageContext - -@synthesize context = _context; -@synthesize currentShaderProgram = _currentShaderProgram; -@synthesize contextQueue = _contextQueue; -@synthesize coreVideoTextureCache = _coreVideoTextureCache; -@synthesize framebufferCache = _framebufferCache; - -static void *openGLESContextQueueKey; - -- (id)init; -{ - if (!(self = [super init])) - { - return nil; - } - - openGLESContextQueueKey = &openGLESContextQueueKey; - _contextQueue = dispatch_queue_create("com.sunsetlakesoftware.GPUImage.openGLESContextQueue", NULL); - -#if OS_OBJECT_USE_OBJC - dispatch_queue_set_specific(_contextQueue, openGLESContextQueueKey, (__bridge void *)self, NULL); -#endif - shaderProgramCache = [[NSMutableDictionary alloc] init]; - shaderProgramUsageHistory = [[NSMutableArray alloc] init]; - - return self; -} - -+ (void *)contextKey { - return openGLESContextQueueKey; -} - -// Based on Colin Wheeler's example here: http://cocoasamurai.blogspot.com/2011/04/singletons-your-doing-them-wrong.html -+ (GPUImageContext *)sharedImageProcessingContext; -{ - static dispatch_once_t pred; - static GPUImageContext *sharedImageProcessingContext = nil; - - dispatch_once(&pred, ^{ - sharedImageProcessingContext = [[[self class] alloc] init]; - }); - return sharedImageProcessingContext; -} - -+ (dispatch_queue_t)sharedContextQueue; -{ - return [[self sharedImageProcessingContext] contextQueue]; -} - -+ (GPUImageFramebufferCache *)sharedFramebufferCache; -{ - return [[self sharedImageProcessingContext] framebufferCache]; -} - -+ (void)useImageProcessingContext; -{ - [[GPUImageContext sharedImageProcessingContext] useAsCurrentContext]; -} - -- (void)useAsCurrentContext; -{ - EAGLContext *imageProcessingContext = [self context]; - if ([EAGLContext currentContext] != imageProcessingContext) - { - [EAGLContext setCurrentContext:imageProcessingContext]; - } -} - -+ (void)setActiveShaderProgram:(GLProgram *)shaderProgram; -{ - GPUImageContext *sharedContext = [GPUImageContext sharedImageProcessingContext]; - [sharedContext setContextShaderProgram:shaderProgram]; -} - -- (void)setContextShaderProgram:(GLProgram *)shaderProgram; -{ - EAGLContext *imageProcessingContext = [self context]; - if ([EAGLContext currentContext] != imageProcessingContext) - { - [EAGLContext setCurrentContext:imageProcessingContext]; - } - - if (self.currentShaderProgram != shaderProgram) - { - self.currentShaderProgram = shaderProgram; - [shaderProgram use]; - } -} - -+ (GLint)maximumTextureSizeForThisDevice; -{ - static dispatch_once_t pred; - static GLint maxTextureSize = 0; - - dispatch_once(&pred, ^{ - [self useImageProcessingContext]; - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); - }); - - return maxTextureSize; -} - -+ (GLint)maximumTextureUnitsForThisDevice; -{ - static dispatch_once_t pred; - static GLint maxTextureUnits = 0; - - dispatch_once(&pred, ^{ - [self useImageProcessingContext]; - glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits); - }); - - return maxTextureUnits; -} - -+ (GLint)maximumVaryingVectorsForThisDevice; -{ - static dispatch_once_t pred; - static GLint maxVaryingVectors = 0; - - dispatch_once(&pred, ^{ - [self useImageProcessingContext]; - glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryingVectors); - }); - - return maxVaryingVectors; -} - -+ (BOOL)deviceSupportsOpenGLESExtension:(NSString *)extension; -{ - static dispatch_once_t pred; - static NSArray *extensionNames = nil; - - // Cache extensions for later quick reference, since this won't change for a given device - dispatch_once(&pred, ^{ - [GPUImageContext useImageProcessingContext]; - NSString *extensionsString = [NSString stringWithCString:(const char *)glGetString(GL_EXTENSIONS) encoding:NSASCIIStringEncoding]; - extensionNames = [extensionsString componentsSeparatedByString:@" "]; - }); - - return [extensionNames containsObject:extension]; -} - - -// http://www.khronos.org/registry/gles/extensions/EXT/EXT_texture_rg.txt - -+ (BOOL)deviceSupportsRedTextures; -{ - static dispatch_once_t pred; - static BOOL supportsRedTextures = NO; - - dispatch_once(&pred, ^{ - supportsRedTextures = [GPUImageContext deviceSupportsOpenGLESExtension:@"GL_EXT_texture_rg"]; - }); - - return supportsRedTextures; -} - -+ (BOOL)deviceSupportsFramebufferReads; -{ - static dispatch_once_t pred; - static BOOL supportsFramebufferReads = NO; - - dispatch_once(&pred, ^{ - supportsFramebufferReads = [GPUImageContext deviceSupportsOpenGLESExtension:@"GL_EXT_shader_framebuffer_fetch"]; - }); - - return supportsFramebufferReads; -} - -+ (CGSize)sizeThatFitsWithinATextureForSize:(CGSize)inputSize; -{ - GLint maxTextureSize = [self maximumTextureSizeForThisDevice]; - if ( (inputSize.width < maxTextureSize) && (inputSize.height < maxTextureSize) ) - { - return inputSize; - } - - CGSize adjustedSize; - if (inputSize.width > inputSize.height) - { - adjustedSize.width = (CGFloat)maxTextureSize; - adjustedSize.height = ((CGFloat)maxTextureSize / inputSize.width) * inputSize.height; - } - else - { - adjustedSize.height = (CGFloat)maxTextureSize; - adjustedSize.width = ((CGFloat)maxTextureSize / inputSize.height) * inputSize.width; - } - - return adjustedSize; -} - -- (void)presentBufferForDisplay; -{ - [self.context presentRenderbuffer:GL_RENDERBUFFER]; -} - -- (GLProgram *)programForVertexShaderString:(NSString *)vertexShaderString fragmentShaderString:(NSString *)fragmentShaderString; -{ - NSString *lookupKeyForShaderProgram = [NSString stringWithFormat:@"V: %@ - F: %@", vertexShaderString, fragmentShaderString]; - GLProgram *programFromCache = [shaderProgramCache objectForKey:lookupKeyForShaderProgram]; - - if (programFromCache == nil) - { - programFromCache = [[GLProgram alloc] initWithVertexShaderString:vertexShaderString fragmentShaderString:fragmentShaderString]; - [shaderProgramCache setObject:programFromCache forKey:lookupKeyForShaderProgram]; -// [shaderProgramUsageHistory addObject:lookupKeyForShaderProgram]; -// if ([shaderProgramUsageHistory count] >= MAXSHADERPROGRAMSALLOWEDINCACHE) -// { -// for (NSUInteger currentShaderProgramRemovedFromCache = 0; currentShaderProgramRemovedFromCache < 10; currentShaderProgramRemovedFromCache++) -// { -// NSString *shaderProgramToRemoveFromCache = [shaderProgramUsageHistory objectAtIndex:0]; -// [shaderProgramUsageHistory removeObjectAtIndex:0]; -// [shaderProgramCache removeObjectForKey:shaderProgramToRemoveFromCache]; -// } -// } - } - - return programFromCache; -} - -- (void)useSharegroup:(EAGLSharegroup *)sharegroup; -{ - NSAssert(_context == nil, @"Unable to use a share group when the context has already been created. Call this method before you use the context for the first time."); - - _sharegroup = sharegroup; -} - -- (EAGLContext *)createContext; -{ - EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup:_sharegroup]; - NSAssert(context != nil, @"Unable to create an OpenGL ES 2.0 context. The GPUImage framework requires OpenGL ES 2.0 support to work."); - return context; -} - - -#pragma mark - -#pragma mark Manage fast texture upload - -+ (BOOL)supportsFastTextureUpload; -{ -#if TARGET_IPHONE_SIMULATOR - return NO; -#else - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wtautological-pointer-compare" - return (CVOpenGLESTextureCacheCreate != NULL); -#pragma clang diagnostic pop - -#endif -} - -#pragma mark - -#pragma mark Accessors - -- (EAGLContext *)context; -{ - if (_context == nil) - { - _context = [self createContext]; - [EAGLContext setCurrentContext:_context]; - - // Set up a few global settings for the image processing pipeline - glDisable(GL_DEPTH_TEST); - } - - return _context; -} - -- (CVOpenGLESTextureCacheRef)coreVideoTextureCache; -{ - if (_coreVideoTextureCache == NULL) - { -#if defined(__IPHONE_6_0) - CVReturn err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, [self context], NULL, &_coreVideoTextureCache); -#else - CVReturn err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, (__bridge void *)[self context], NULL, &_coreVideoTextureCache); -#endif - - if (err) - { - NSAssert(NO, @"Error at CVOpenGLESTextureCacheCreate %d", err); - } - - } - - return _coreVideoTextureCache; -} - -- (GPUImageFramebufferCache *)framebufferCache; -{ - if (_framebufferCache == nil) - { - _framebufferCache = [[GPUImageFramebufferCache alloc] init]; - } - - return _framebufferCache; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageMovieWriter.h b/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageMovieWriter.h deleted file mode 100755 index f0b2c6ad..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageMovieWriter.h +++ /dev/null @@ -1,67 +0,0 @@ -#import -#import -#import "GPUImageContext.h" - -extern NSString *const kGPUImageColorSwizzlingFragmentShaderString; - -@protocol GPUImageMovieWriterDelegate - -@optional -- (void)movieRecordingCompleted; -- (void)movieRecordingFailedWithError:(NSError*)error; - -@end - -@interface GPUImageMovieWriter : NSObject -{ - BOOL alreadyFinishedRecording; - - NSURL *movieURL; - NSString *fileType; - AVAssetWriter *assetWriter; - AVAssetWriterInput *assetWriterAudioInput; - AVAssetWriterInput *assetWriterVideoInput; - AVAssetWriterInputPixelBufferAdaptor *assetWriterPixelBufferInput; - - GPUImageContext *_movieWriterContext; - CVPixelBufferRef renderTarget; - CVOpenGLESTextureRef renderTexture; - - CGSize videoSize; - GPUImageRotationMode inputRotation; -} - -@property(readwrite, nonatomic) BOOL hasAudioTrack; -@property(readwrite, nonatomic) BOOL shouldPassthroughAudio; -@property(readwrite, nonatomic) BOOL shouldInvalidateAudioSampleWhenDone; -@property(nonatomic, copy) void(^completionBlock)(void); -@property(nonatomic, copy) void(^failureBlock)(NSError*); -@property(nonatomic, assign) id delegate; -@property(readwrite, nonatomic) BOOL encodingLiveVideo; -@property(nonatomic, copy) BOOL(^videoInputReadyCallback)(void); -@property(nonatomic, copy) BOOL(^audioInputReadyCallback)(void); -@property(nonatomic, copy) void(^audioProcessingCallback)(SInt16 **samplesRef, CMItemCount numSamplesInBuffer); -@property(nonatomic) BOOL enabled; -@property(nonatomic, readonly) AVAssetWriter *assetWriter; -@property(nonatomic, readonly) CMTime duration; -@property(nonatomic, assign) CGAffineTransform transform; -@property(nonatomic, copy) NSArray *metaData; -@property(nonatomic, assign, getter = isPaused) BOOL paused; -@property(nonatomic, retain) GPUImageContext *movieWriterContext; - -// Initialization and teardown -- (id)initWithMovieURL:(NSURL *)newMovieURL size:(CGSize)newSize; -- (id)initWithMovieURL:(NSURL *)newMovieURL size:(CGSize)newSize fileType:(NSString *)newFileType outputSettings:(NSDictionary *)outputSettings; - -- (void)setHasAudioTrack:(BOOL)hasAudioTrack audioSettings:(NSDictionary *)audioOutputSettings; - -// Movie recording -- (void)startRecording; -- (void)startRecordingInOrientation:(CGAffineTransform)orientationTransform; -- (void)finishRecording; -- (void)finishRecordingWithCompletionHandler:(void (^)(void))handler; -- (void)cancelRecording; -- (void)processAudioBuffer:(CMSampleBufferRef)audioBuffer; -- (void)enableSynchronizationCallbacks; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageMovieWriter.m b/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageMovieWriter.m deleted file mode 100755 index 8ced0dfe..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageMovieWriter.m +++ /dev/null @@ -1,934 +0,0 @@ -#import "GPUImageMovieWriter.h" - -#import "GPUImageContext.h" -#import "GLProgram.h" -#import "GPUImageFilter.h" - -NSString *const kGPUImageColorSwizzlingFragmentShaderString = SHADER_STRING -( - varying highp vec2 textureCoordinate; - - uniform sampler2D inputImageTexture; - - void main() - { - gl_FragColor = texture2D(inputImageTexture, textureCoordinate).bgra; - } -); - - -@interface GPUImageMovieWriter () -{ - GLuint movieFramebuffer, movieRenderbuffer; - - GLProgram *colorSwizzlingProgram; - GLint colorSwizzlingPositionAttribute, colorSwizzlingTextureCoordinateAttribute; - GLint colorSwizzlingInputTextureUniform; - - GPUImageFramebuffer *firstInputFramebuffer; - - CMTime startTime, previousFrameTime, previousAudioTime; - - dispatch_queue_t audioQueue, videoQueue; - BOOL audioEncodingIsFinished, videoEncodingIsFinished; - - BOOL isRecording; -} - -// Movie recording -- (void)initializeMovieWithOutputSettings:(NSMutableDictionary *)outputSettings; - -// Frame rendering -- (void)createDataFBO; -- (void)destroyDataFBO; -- (void)setFilterFBO; - -- (void)renderAtInternalSizeUsingFramebuffer:(GPUImageFramebuffer *)inputFramebufferToUse; - -@end - -@implementation GPUImageMovieWriter - -@synthesize hasAudioTrack = _hasAudioTrack; -@synthesize encodingLiveVideo = _encodingLiveVideo; -@synthesize shouldPassthroughAudio = _shouldPassthroughAudio; -@synthesize completionBlock; -@synthesize failureBlock; -@synthesize videoInputReadyCallback; -@synthesize audioInputReadyCallback; -@synthesize enabled; -@synthesize shouldInvalidateAudioSampleWhenDone = _shouldInvalidateAudioSampleWhenDone; -@synthesize paused = _paused; -@synthesize movieWriterContext = _movieWriterContext; - -@synthesize delegate = _delegate; - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithMovieURL:(NSURL *)newMovieURL size:(CGSize)newSize; -{ - return [self initWithMovieURL:newMovieURL size:newSize fileType:AVFileTypeQuickTimeMovie outputSettings:nil]; -} - -- (id)initWithMovieURL:(NSURL *)newMovieURL size:(CGSize)newSize fileType:(NSString *)newFileType outputSettings:(NSMutableDictionary *)outputSettings; -{ - if (!(self = [super init])) - { - return nil; - } - - _shouldInvalidateAudioSampleWhenDone = NO; - - self.enabled = YES; - alreadyFinishedRecording = NO; - videoEncodingIsFinished = NO; - audioEncodingIsFinished = NO; - - videoSize = newSize; - movieURL = newMovieURL; - fileType = newFileType; - startTime = kCMTimeInvalid; - _encodingLiveVideo = [[outputSettings objectForKey:@"EncodingLiveVideo"] isKindOfClass:[NSNumber class]] ? [[outputSettings objectForKey:@"EncodingLiveVideo"] boolValue] : YES; - previousFrameTime = kCMTimeNegativeInfinity; - previousAudioTime = kCMTimeNegativeInfinity; - inputRotation = kGPUImageNoRotation; - - _movieWriterContext = [[GPUImageContext alloc] init]; - [_movieWriterContext useSharegroup:[[[GPUImageContext sharedImageProcessingContext] context] sharegroup]]; - - runSynchronouslyOnContextQueue(_movieWriterContext, ^{ - [_movieWriterContext useAsCurrentContext]; - - if ([GPUImageContext supportsFastTextureUpload]) - { - colorSwizzlingProgram = [_movieWriterContext programForVertexShaderString:kGPUImageVertexShaderString fragmentShaderString:kGPUImagePassthroughFragmentShaderString]; - } - else - { - colorSwizzlingProgram = [_movieWriterContext programForVertexShaderString:kGPUImageVertexShaderString fragmentShaderString:kGPUImageColorSwizzlingFragmentShaderString]; - } - - if (!colorSwizzlingProgram.initialized) - { - [colorSwizzlingProgram addAttribute:@"position"]; - [colorSwizzlingProgram addAttribute:@"inputTextureCoordinate"]; - - if (![colorSwizzlingProgram link]) - { - NSString *progLog = [colorSwizzlingProgram programLog]; - NSLog(@"Program link log: %@", progLog); - NSString *fragLog = [colorSwizzlingProgram fragmentShaderLog]; - NSLog(@"Fragment shader compile log: %@", fragLog); - NSString *vertLog = [colorSwizzlingProgram vertexShaderLog]; - NSLog(@"Vertex shader compile log: %@", vertLog); - colorSwizzlingProgram = nil; - NSAssert(NO, @"Filter shader link failed"); - } - } - - colorSwizzlingPositionAttribute = [colorSwizzlingProgram attributeIndex:@"position"]; - colorSwizzlingTextureCoordinateAttribute = [colorSwizzlingProgram attributeIndex:@"inputTextureCoordinate"]; - colorSwizzlingInputTextureUniform = [colorSwizzlingProgram uniformIndex:@"inputImageTexture"]; - - [_movieWriterContext setContextShaderProgram:colorSwizzlingProgram]; - - glEnableVertexAttribArray(colorSwizzlingPositionAttribute); - glEnableVertexAttribArray(colorSwizzlingTextureCoordinateAttribute); - }); - - [self initializeMovieWithOutputSettings:outputSettings]; - - return self; -} - -- (void)dealloc; -{ - [self destroyDataFBO]; - -#if !OS_OBJECT_USE_OBJC - if( audioQueue != NULL ) - { - dispatch_release(audioQueue); - } - if( videoQueue != NULL ) - { - dispatch_release(videoQueue); - } -#endif -} - -#pragma mark - -#pragma mark Movie recording - -- (void)initializeMovieWithOutputSettings:(NSDictionary *)outputSettings; -{ - isRecording = NO; - - self.enabled = YES; - NSError *error = nil; - assetWriter = [[AVAssetWriter alloc] initWithURL:movieURL fileType:fileType error:&error]; - if (error != nil) - { - NSLog(@"Error: %@", error); - if (failureBlock) - { - failureBlock(error); - } - else - { - if(self.delegate && [self.delegate respondsToSelector:@selector(movieRecordingFailedWithError:)]) - { - [self.delegate movieRecordingFailedWithError:error]; - } - } - } - - // Set this to make sure that a functional movie is produced, even if the recording is cut off mid-stream. Only the last second should be lost in that case. - assetWriter.movieFragmentInterval = CMTimeMakeWithSeconds(1.0, 1000); - - // use default output settings if none specified - if (outputSettings == nil) - { - NSMutableDictionary *settings = [[NSMutableDictionary alloc] init]; - [settings setObject:AVVideoCodecH264 forKey:AVVideoCodecKey]; - [settings setObject:[NSNumber numberWithInt:videoSize.width] forKey:AVVideoWidthKey]; - [settings setObject:[NSNumber numberWithInt:videoSize.height] forKey:AVVideoHeightKey]; - outputSettings = settings; - } - // custom output settings specified - else - { - NSString *videoCodec = [outputSettings objectForKey:AVVideoCodecKey]; - NSNumber *width = [outputSettings objectForKey:AVVideoWidthKey]; - NSNumber *height = [outputSettings objectForKey:AVVideoHeightKey]; - - NSAssert(videoCodec && width && height, @"OutputSettings is missing required parameters."); - - if( [outputSettings objectForKey:@"EncodingLiveVideo"] ) { - NSMutableDictionary *tmp = [outputSettings mutableCopy]; - [tmp removeObjectForKey:@"EncodingLiveVideo"]; - outputSettings = tmp; - } - } - - /* - NSDictionary *videoCleanApertureSettings = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithInt:videoSize.width], AVVideoCleanApertureWidthKey, - [NSNumber numberWithInt:videoSize.height], AVVideoCleanApertureHeightKey, - [NSNumber numberWithInt:0], AVVideoCleanApertureHorizontalOffsetKey, - [NSNumber numberWithInt:0], AVVideoCleanApertureVerticalOffsetKey, - nil]; - - NSDictionary *videoAspectRatioSettings = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithInt:3], AVVideoPixelAspectRatioHorizontalSpacingKey, - [NSNumber numberWithInt:3], AVVideoPixelAspectRatioVerticalSpacingKey, - nil]; - - NSMutableDictionary * compressionProperties = [[NSMutableDictionary alloc] init]; - [compressionProperties setObject:videoCleanApertureSettings forKey:AVVideoCleanApertureKey]; - [compressionProperties setObject:videoAspectRatioSettings forKey:AVVideoPixelAspectRatioKey]; - [compressionProperties setObject:[NSNumber numberWithInt: 2000000] forKey:AVVideoAverageBitRateKey]; - [compressionProperties setObject:[NSNumber numberWithInt: 16] forKey:AVVideoMaxKeyFrameIntervalKey]; - [compressionProperties setObject:AVVideoProfileLevelH264Main31 forKey:AVVideoProfileLevelKey]; - - [outputSettings setObject:compressionProperties forKey:AVVideoCompressionPropertiesKey]; - */ - - assetWriterVideoInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:outputSettings]; - assetWriterVideoInput.expectsMediaDataInRealTime = _encodingLiveVideo; - - // You need to use BGRA for the video in order to get realtime encoding. I use a color-swizzling shader to line up glReadPixels' normal RGBA output with the movie input's BGRA. - NSDictionary *sourcePixelBufferAttributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:kCVPixelFormatType_32BGRA], kCVPixelBufferPixelFormatTypeKey, - [NSNumber numberWithInt:videoSize.width], kCVPixelBufferWidthKey, - [NSNumber numberWithInt:videoSize.height], kCVPixelBufferHeightKey, - nil]; -// NSDictionary *sourcePixelBufferAttributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:kCVPixelFormatType_32ARGB], kCVPixelBufferPixelFormatTypeKey, -// nil]; - - assetWriterPixelBufferInput = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:assetWriterVideoInput sourcePixelBufferAttributes:sourcePixelBufferAttributesDictionary]; - - [assetWriter addInput:assetWriterVideoInput]; -} - -- (void)setEncodingLiveVideo:(BOOL) value -{ - _encodingLiveVideo = value; - if (isRecording) { - NSAssert(NO, @"Can not change Encoding Live Video while recording"); - } - else - { - assetWriterVideoInput.expectsMediaDataInRealTime = _encodingLiveVideo; - assetWriterAudioInput.expectsMediaDataInRealTime = _encodingLiveVideo; - } -} - -- (void)startRecording; -{ - alreadyFinishedRecording = NO; - startTime = kCMTimeInvalid; - runSynchronouslyOnContextQueue(_movieWriterContext, ^{ - if (audioInputReadyCallback == NULL) - { - [assetWriter startWriting]; - } - }); - isRecording = YES; - // [assetWriter startSessionAtSourceTime:kCMTimeZero]; -} - -- (void)startRecordingInOrientation:(CGAffineTransform)orientationTransform; -{ - assetWriterVideoInput.transform = orientationTransform; - - [self startRecording]; -} - -- (void)cancelRecording; -{ - if (assetWriter.status == AVAssetWriterStatusCompleted) - { - return; - } - - isRecording = NO; - runSynchronouslyOnContextQueue(_movieWriterContext, ^{ - alreadyFinishedRecording = YES; - - if( assetWriter.status == AVAssetWriterStatusWriting && ! videoEncodingIsFinished ) - { - videoEncodingIsFinished = YES; - [assetWriterVideoInput markAsFinished]; - } - if( assetWriter.status == AVAssetWriterStatusWriting && ! audioEncodingIsFinished ) - { - audioEncodingIsFinished = YES; - [assetWriterAudioInput markAsFinished]; - } - [assetWriter cancelWriting]; - }); -} - -- (void)finishRecording; -{ - [self finishRecordingWithCompletionHandler:NULL]; -} - -- (void)finishRecordingWithCompletionHandler:(void (^)(void))handler; -{ - runSynchronouslyOnContextQueue(_movieWriterContext, ^{ - isRecording = NO; - - if (assetWriter.status == AVAssetWriterStatusCompleted || assetWriter.status == AVAssetWriterStatusCancelled || assetWriter.status == AVAssetWriterStatusUnknown) - { - if (handler) - runAsynchronouslyOnContextQueue(_movieWriterContext, handler); - return; - } - if( assetWriter.status == AVAssetWriterStatusWriting && ! videoEncodingIsFinished ) - { - videoEncodingIsFinished = YES; - [assetWriterVideoInput markAsFinished]; - } - if( assetWriter.status == AVAssetWriterStatusWriting && ! audioEncodingIsFinished ) - { - audioEncodingIsFinished = YES; - [assetWriterAudioInput markAsFinished]; - } -#if (!defined(__IPHONE_6_0) || (__IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_6_0)) - // Not iOS 6 SDK - [assetWriter finishWriting]; - if (handler) - runAsynchronouslyOnContextQueue(_movieWriterContext,handler); -#else - // iOS 6 SDK - if ([assetWriter respondsToSelector:@selector(finishWritingWithCompletionHandler:)]) { - // Running iOS 6 - [assetWriter finishWritingWithCompletionHandler:(handler ?: ^{ })]; - } - else { - // Not running iOS 6 -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - [assetWriter finishWriting]; -#pragma clang diagnostic pop - if (handler) - runAsynchronouslyOnContextQueue(_movieWriterContext, handler); - } -#endif - }); -} - -- (void)processAudioBuffer:(CMSampleBufferRef)audioBuffer; -{ - if (!isRecording) - { - return; - } - -// if (_hasAudioTrack && CMTIME_IS_VALID(startTime)) - if (_hasAudioTrack) - { - CFRetain(audioBuffer); - - CMTime currentSampleTime = CMSampleBufferGetOutputPresentationTimeStamp(audioBuffer); - - if (CMTIME_IS_INVALID(startTime)) - { - runSynchronouslyOnContextQueue(_movieWriterContext, ^{ - if ((audioInputReadyCallback == NULL) && (assetWriter.status != AVAssetWriterStatusWriting)) - { - [assetWriter startWriting]; - } - [assetWriter startSessionAtSourceTime:currentSampleTime]; - startTime = currentSampleTime; - }); - } - - if (!assetWriterAudioInput.readyForMoreMediaData && _encodingLiveVideo) - { - NSLog(@"1: Had to drop an audio frame: %@", CFBridgingRelease(CMTimeCopyDescription(kCFAllocatorDefault, currentSampleTime))); - if (_shouldInvalidateAudioSampleWhenDone) - { - CMSampleBufferInvalidate(audioBuffer); - } - CFRelease(audioBuffer); - return; - } - - previousAudioTime = currentSampleTime; - - //if the consumer wants to do something with the audio samples before writing, let him. - if (self.audioProcessingCallback) { - //need to introspect into the opaque CMBlockBuffer structure to find its raw sample buffers. - CMBlockBufferRef buffer = CMSampleBufferGetDataBuffer(audioBuffer); - CMItemCount numSamplesInBuffer = CMSampleBufferGetNumSamples(audioBuffer); - AudioBufferList audioBufferList; - - CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(audioBuffer, - NULL, - &audioBufferList, - sizeof(audioBufferList), - NULL, - NULL, - kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment, - &buffer - ); - //passing a live pointer to the audio buffers, try to process them in-place or we might have syncing issues. - for (int bufferCount=0; bufferCount < audioBufferList.mNumberBuffers; bufferCount++) { - SInt16 *samples = (SInt16 *)audioBufferList.mBuffers[bufferCount].mData; - self.audioProcessingCallback(&samples, numSamplesInBuffer); - } - } - -// NSLog(@"Recorded audio sample time: %lld, %d, %lld", currentSampleTime.value, currentSampleTime.timescale, currentSampleTime.epoch); - void(^write)() = ^() { - while( ! assetWriterAudioInput.readyForMoreMediaData && ! _encodingLiveVideo && ! audioEncodingIsFinished ) { - NSDate *maxDate = [NSDate dateWithTimeIntervalSinceNow:0.5]; - //NSLog(@"audio waiting..."); - [[NSRunLoop currentRunLoop] runUntilDate:maxDate]; - } - if (!assetWriterAudioInput.readyForMoreMediaData) - { - NSLog(@"2: Had to drop an audio frame %@", CFBridgingRelease(CMTimeCopyDescription(kCFAllocatorDefault, currentSampleTime))); - } - else if(assetWriter.status == AVAssetWriterStatusWriting) - { - if (![assetWriterAudioInput appendSampleBuffer:audioBuffer]) - NSLog(@"Problem appending audio buffer at time: %@", CFBridgingRelease(CMTimeCopyDescription(kCFAllocatorDefault, currentSampleTime))); - } - else - { - //NSLog(@"Wrote an audio frame %@", CFBridgingRelease(CMTimeCopyDescription(kCFAllocatorDefault, currentSampleTime))); - } - - if (_shouldInvalidateAudioSampleWhenDone) - { - CMSampleBufferInvalidate(audioBuffer); - } - CFRelease(audioBuffer); - }; -// runAsynchronouslyOnContextQueue(_movieWriterContext, write); - if( _encodingLiveVideo ) - - { - runAsynchronouslyOnContextQueue(_movieWriterContext, write); - } - else - { - write(); - } - } -} - -- (void)enableSynchronizationCallbacks; -{ - if (videoInputReadyCallback != NULL) - { - if( assetWriter.status != AVAssetWriterStatusWriting ) - { - [assetWriter startWriting]; - } - videoQueue = dispatch_queue_create("com.sunsetlakesoftware.GPUImage.videoReadingQueue", NULL); - [assetWriterVideoInput requestMediaDataWhenReadyOnQueue:videoQueue usingBlock:^{ - if( _paused ) - { - //NSLog(@"video requestMediaDataWhenReadyOnQueue paused"); - // if we don't sleep, we'll get called back almost immediately, chewing up CPU - usleep(10000); - return; - } - //NSLog(@"video requestMediaDataWhenReadyOnQueue begin"); - while( assetWriterVideoInput.readyForMoreMediaData && ! _paused ) - { - if( videoInputReadyCallback && ! videoInputReadyCallback() && ! videoEncodingIsFinished ) - { - runAsynchronouslyOnContextQueue(_movieWriterContext, ^{ - if( assetWriter.status == AVAssetWriterStatusWriting && ! videoEncodingIsFinished ) - { - videoEncodingIsFinished = YES; - [assetWriterVideoInput markAsFinished]; - } - }); - } - } - //NSLog(@"video requestMediaDataWhenReadyOnQueue end"); - }]; - } - - if (audioInputReadyCallback != NULL) - { - audioQueue = dispatch_queue_create("com.sunsetlakesoftware.GPUImage.audioReadingQueue", NULL); - [assetWriterAudioInput requestMediaDataWhenReadyOnQueue:audioQueue usingBlock:^{ - if( _paused ) - { - //NSLog(@"audio requestMediaDataWhenReadyOnQueue paused"); - // if we don't sleep, we'll get called back almost immediately, chewing up CPU - usleep(10000); - return; - } - //NSLog(@"audio requestMediaDataWhenReadyOnQueue begin"); - while( assetWriterAudioInput.readyForMoreMediaData && ! _paused ) - { - if( audioInputReadyCallback && ! audioInputReadyCallback() && ! audioEncodingIsFinished ) - { - runAsynchronouslyOnContextQueue(_movieWriterContext, ^{ - if( assetWriter.status == AVAssetWriterStatusWriting && ! audioEncodingIsFinished ) - { - audioEncodingIsFinished = YES; - [assetWriterAudioInput markAsFinished]; - } - }); - } - } - //NSLog(@"audio requestMediaDataWhenReadyOnQueue end"); - }]; - } - -} - -#pragma mark - -#pragma mark Frame rendering - -- (void)createDataFBO; -{ - glActiveTexture(GL_TEXTURE1); - glGenFramebuffers(1, &movieFramebuffer); - glBindFramebuffer(GL_FRAMEBUFFER, movieFramebuffer); - - if ([GPUImageContext supportsFastTextureUpload]) - { - // Code originally sourced from http://allmybrain.com/2011/12/08/rendering-to-a-texture-with-ios-5-texture-cache-api/ - - - CVPixelBufferPoolCreatePixelBuffer (NULL, [assetWriterPixelBufferInput pixelBufferPool], &renderTarget); - - /* AVAssetWriter will use BT.601 conversion matrix for RGB to YCbCr conversion - * regardless of the kCVImageBufferYCbCrMatrixKey value. - * Tagging the resulting video file as BT.601, is the best option right now. - * Creating a proper BT.709 video is not possible at the moment. - */ - CVBufferSetAttachment(renderTarget, kCVImageBufferColorPrimariesKey, kCVImageBufferColorPrimaries_ITU_R_709_2, kCVAttachmentMode_ShouldPropagate); - CVBufferSetAttachment(renderTarget, kCVImageBufferYCbCrMatrixKey, kCVImageBufferYCbCrMatrix_ITU_R_601_4, kCVAttachmentMode_ShouldPropagate); - CVBufferSetAttachment(renderTarget, kCVImageBufferTransferFunctionKey, kCVImageBufferTransferFunction_ITU_R_709_2, kCVAttachmentMode_ShouldPropagate); - - CVOpenGLESTextureCacheCreateTextureFromImage (kCFAllocatorDefault, [_movieWriterContext coreVideoTextureCache], renderTarget, - NULL, // texture attributes - GL_TEXTURE_2D, - GL_RGBA, // opengl format - (int)videoSize.width, - (int)videoSize.height, - GL_BGRA, // native iOS format - GL_UNSIGNED_BYTE, - 0, - &renderTexture); - - glBindTexture(CVOpenGLESTextureGetTarget(renderTexture), CVOpenGLESTextureGetName(renderTexture)); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, CVOpenGLESTextureGetName(renderTexture), 0); - } - else - { - glGenRenderbuffers(1, &movieRenderbuffer); - glBindRenderbuffer(GL_RENDERBUFFER, movieRenderbuffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, (int)videoSize.width, (int)videoSize.height); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, movieRenderbuffer); - } - - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - - NSAssert(status == GL_FRAMEBUFFER_COMPLETE, @"Incomplete filter FBO: %d", status); -} - -- (void)destroyDataFBO; -{ - runSynchronouslyOnContextQueue(_movieWriterContext, ^{ - [_movieWriterContext useAsCurrentContext]; - - if (movieFramebuffer) - { - glDeleteFramebuffers(1, &movieFramebuffer); - movieFramebuffer = 0; - } - - if (movieRenderbuffer) - { - glDeleteRenderbuffers(1, &movieRenderbuffer); - movieRenderbuffer = 0; - } - - if ([GPUImageContext supportsFastTextureUpload]) - { - if (renderTexture) - { - CFRelease(renderTexture); - } - if (renderTarget) - { - CVPixelBufferRelease(renderTarget); - } - - } - }); -} - -- (void)setFilterFBO; -{ - if (!movieFramebuffer) - { - [self createDataFBO]; - } - - glBindFramebuffer(GL_FRAMEBUFFER, movieFramebuffer); - - glViewport(0, 0, (int)videoSize.width, (int)videoSize.height); -} - -- (void)renderAtInternalSizeUsingFramebuffer:(GPUImageFramebuffer *)inputFramebufferToUse; -{ - [_movieWriterContext useAsCurrentContext]; - [self setFilterFBO]; - - [_movieWriterContext setContextShaderProgram:colorSwizzlingProgram]; - - glClearColor(1.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // This needs to be flipped to write out to video correctly - static const GLfloat squareVertices[] = { - -1.0f, -1.0f, - 1.0f, -1.0f, - -1.0f, 1.0f, - 1.0f, 1.0f, - }; - - const GLfloat *textureCoordinates = [GPUImageFilter textureCoordinatesForRotation:inputRotation]; - - glActiveTexture(GL_TEXTURE4); - glBindTexture(GL_TEXTURE_2D, [inputFramebufferToUse texture]); - glUniform1i(colorSwizzlingInputTextureUniform, 4); - -// NSLog(@"Movie writer framebuffer: %@", inputFramebufferToUse); - - glVertexAttribPointer(colorSwizzlingPositionAttribute, 2, GL_FLOAT, 0, 0, squareVertices); - glVertexAttribPointer(colorSwizzlingTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glFinish(); -} - -#pragma mark - -#pragma mark GPUImageInput protocol - -- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex; -{ - if (!isRecording) - { - [firstInputFramebuffer unlock]; - return; - } - - // Drop frames forced by images and other things with no time constants - // Also, if two consecutive times with the same value are added to the movie, it aborts recording, so I bail on that case - if ( (CMTIME_IS_INVALID(frameTime)) || (CMTIME_COMPARE_INLINE(frameTime, ==, previousFrameTime)) || (CMTIME_IS_INDEFINITE(frameTime)) ) - { - [firstInputFramebuffer unlock]; - return; - } - - if (CMTIME_IS_INVALID(startTime)) - { - runSynchronouslyOnContextQueue(_movieWriterContext, ^{ - if ((videoInputReadyCallback == NULL) && (assetWriter.status != AVAssetWriterStatusWriting)) - { - [assetWriter startWriting]; - } - - [assetWriter startSessionAtSourceTime:frameTime]; - startTime = frameTime; - }); - } - - GPUImageFramebuffer *inputFramebufferForBlock = firstInputFramebuffer; - glFinish(); - - runAsynchronouslyOnContextQueue(_movieWriterContext, ^{ - if (!assetWriterVideoInput.readyForMoreMediaData && _encodingLiveVideo) - { - [inputFramebufferForBlock unlock]; - NSLog(@"1: Had to drop a video frame: %@", CFBridgingRelease(CMTimeCopyDescription(kCFAllocatorDefault, frameTime))); - return; - } - - // Render the frame with swizzled colors, so that they can be uploaded quickly as BGRA frames - [_movieWriterContext useAsCurrentContext]; - [self renderAtInternalSizeUsingFramebuffer:inputFramebufferForBlock]; - - CVPixelBufferRef pixel_buffer = NULL; - - if ([GPUImageContext supportsFastTextureUpload]) - { - pixel_buffer = renderTarget; - CVPixelBufferLockBaseAddress(pixel_buffer, 0); - } - else - { - CVReturn status = CVPixelBufferPoolCreatePixelBuffer (NULL, [assetWriterPixelBufferInput pixelBufferPool], &pixel_buffer); - if ((pixel_buffer == NULL) || (status != kCVReturnSuccess)) - { - CVPixelBufferRelease(pixel_buffer); - return; - } - else - { - CVPixelBufferLockBaseAddress(pixel_buffer, 0); - - GLubyte *pixelBufferData = (GLubyte *)CVPixelBufferGetBaseAddress(pixel_buffer); - glReadPixels(0, 0, videoSize.width, videoSize.height, GL_RGBA, GL_UNSIGNED_BYTE, pixelBufferData); - } - } - - void(^write)() = ^() { - while( ! assetWriterVideoInput.readyForMoreMediaData && ! _encodingLiveVideo && ! videoEncodingIsFinished ) { - NSDate *maxDate = [NSDate dateWithTimeIntervalSinceNow:0.1]; - // NSLog(@"video waiting..."); - [[NSRunLoop currentRunLoop] runUntilDate:maxDate]; - } - if (!assetWriterVideoInput.readyForMoreMediaData) - { - NSLog(@"2: Had to drop a video frame: %@", CFBridgingRelease(CMTimeCopyDescription(kCFAllocatorDefault, frameTime))); - } - else if(self.assetWriter.status == AVAssetWriterStatusWriting) - { - if (![assetWriterPixelBufferInput appendPixelBuffer:pixel_buffer withPresentationTime:frameTime]) - NSLog(@"Problem appending pixel buffer at time: %@", CFBridgingRelease(CMTimeCopyDescription(kCFAllocatorDefault, frameTime))); - } - else - { - NSLog(@"Couldn't write a frame"); - //NSLog(@"Wrote a video frame: %@", CFBridgingRelease(CMTimeCopyDescription(kCFAllocatorDefault, frameTime))); - } - CVPixelBufferUnlockBaseAddress(pixel_buffer, 0); - - previousFrameTime = frameTime; - - if (![GPUImageContext supportsFastTextureUpload]) - { - CVPixelBufferRelease(pixel_buffer); - } - }; - - write(); - - [inputFramebufferForBlock unlock]; - }); -} - -- (NSInteger)nextAvailableTextureIndex; -{ - return 0; -} - -- (void)setInputFramebuffer:(GPUImageFramebuffer *)newInputFramebuffer atIndex:(NSInteger)textureIndex; -{ - [newInputFramebuffer lock]; -// runSynchronouslyOnContextQueue(_movieWriterContext, ^{ - firstInputFramebuffer = newInputFramebuffer; -// }); -} - -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -{ - inputRotation = newInputRotation; -} - -- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex; -{ -} - -- (CGSize)maximumOutputSize; -{ - return videoSize; -} - -- (void)endProcessing -{ - if (completionBlock) - { - if (!alreadyFinishedRecording) - { - alreadyFinishedRecording = YES; - completionBlock(); - } - } - else - { - if (_delegate && [_delegate respondsToSelector:@selector(movieRecordingCompleted)]) - { - [_delegate movieRecordingCompleted]; - } - } -} - -- (BOOL)shouldIgnoreUpdatesToThisTarget; -{ - return NO; -} - -- (BOOL)wantsMonochromeInput; -{ - return NO; -} - -- (void)setCurrentlyReceivingMonochromeInput:(BOOL)newValue; -{ - -} - -#pragma mark - -#pragma mark Accessors - -- (void)setHasAudioTrack:(BOOL)newValue -{ - [self setHasAudioTrack:newValue audioSettings:nil]; -} - -- (void)setHasAudioTrack:(BOOL)newValue audioSettings:(NSDictionary *)audioOutputSettings; -{ - _hasAudioTrack = newValue; - - if (_hasAudioTrack) - { - if (_shouldPassthroughAudio) - { - // Do not set any settings so audio will be the same as passthrough - audioOutputSettings = nil; - } - else if (audioOutputSettings == nil) - { - AVAudioSession *sharedAudioSession = [AVAudioSession sharedInstance]; - double preferredHardwareSampleRate; - - if ([sharedAudioSession respondsToSelector:@selector(sampleRate)]) - { - preferredHardwareSampleRate = [sharedAudioSession sampleRate]; - } - else - { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - preferredHardwareSampleRate = [[AVAudioSession sharedInstance] currentHardwareSampleRate]; -#pragma clang diagnostic pop - } - - AudioChannelLayout acl; - bzero( &acl, sizeof(acl)); - acl.mChannelLayoutTag = kAudioChannelLayoutTag_Mono; - - audioOutputSettings = [NSDictionary dictionaryWithObjectsAndKeys: - [ NSNumber numberWithInt: kAudioFormatMPEG4AAC], AVFormatIDKey, - [ NSNumber numberWithInt: 1 ], AVNumberOfChannelsKey, - [ NSNumber numberWithFloat: preferredHardwareSampleRate ], AVSampleRateKey, - [ NSData dataWithBytes: &acl length: sizeof( acl ) ], AVChannelLayoutKey, - //[ NSNumber numberWithInt:AVAudioQualityLow], AVEncoderAudioQualityKey, - [ NSNumber numberWithInt: 64000 ], AVEncoderBitRateKey, - nil]; -/* - AudioChannelLayout acl; - bzero( &acl, sizeof(acl)); - acl.mChannelLayoutTag = kAudioChannelLayoutTag_Mono; - - audioOutputSettings = [NSDictionary dictionaryWithObjectsAndKeys: - [ NSNumber numberWithInt: kAudioFormatMPEG4AAC ], AVFormatIDKey, - [ NSNumber numberWithInt: 1 ], AVNumberOfChannelsKey, - [ NSNumber numberWithFloat: 44100.0 ], AVSampleRateKey, - [ NSNumber numberWithInt: 64000 ], AVEncoderBitRateKey, - [ NSData dataWithBytes: &acl length: sizeof( acl ) ], AVChannelLayoutKey, - nil];*/ - } - - assetWriterAudioInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:audioOutputSettings]; - [assetWriter addInput:assetWriterAudioInput]; - assetWriterAudioInput.expectsMediaDataInRealTime = _encodingLiveVideo; - } - else - { - // Remove audio track if it exists - } -} - -- (NSArray*)metaData { - return assetWriter.metadata; -} - -- (void)setMetaData:(NSArray*)metaData { - assetWriter.metadata = metaData; -} - -- (CMTime)duration { - if( ! CMTIME_IS_VALID(startTime) ) - return kCMTimeZero; - if( ! CMTIME_IS_NEGATIVE_INFINITY(previousFrameTime) ) - return CMTimeSubtract(previousFrameTime, startTime); - if( ! CMTIME_IS_NEGATIVE_INFINITY(previousAudioTime) ) - return CMTimeSubtract(previousAudioTime, startTime); - return kCMTimeZero; -} - -- (CGAffineTransform)transform { - return assetWriterVideoInput.transform; -} - -- (void)setTransform:(CGAffineTransform)transform { - assetWriterVideoInput.transform = transform; -} - -- (AVAssetWriter*)assetWriter { - return assetWriter; -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImagePicture+TextureSubimage.h b/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImagePicture+TextureSubimage.h deleted file mode 100644 index 03c631bc..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImagePicture+TextureSubimage.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// GPUImagePicture+TextureSubimage.h -// GPUImage -// -// Created by Jack Wu on 2014-05-28. -// Copyright (c) 2014 Brad Larson. All rights reserved. -// - -#import "GPUImagePicture.h" - -@interface GPUImagePicture (TextureSubimage) - -- (void)replaceTextureWithSubimage:(UIImage*)subimage; -- (void)replaceTextureWithSubCGImage:(CGImageRef)subimageSource; - -- (void)replaceTextureWithSubimage:(UIImage*)subimage inRect:(CGRect)subRect; -- (void)replaceTextureWithSubCGImage:(CGImageRef)subimageSource inRect:(CGRect)subRect; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImagePicture+TextureSubimage.m b/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImagePicture+TextureSubimage.m deleted file mode 100644 index 71ef8f97..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImagePicture+TextureSubimage.m +++ /dev/null @@ -1,103 +0,0 @@ -// -// GPUImagePicture+TextureSubimage.m -// GPUImage -// -// Created by Jack Wu on 2014-05-28. -// Copyright (c) 2014 Brad Larson. All rights reserved. -// - -#import "GPUImagePicture+TextureSubimage.h" - -@implementation GPUImagePicture (TextureSubimage) - -- (void)replaceTextureWithSubimage:(UIImage*)subimage { - return [self replaceTextureWithSubCGImage:[subimage CGImage]]; -} - -- (void)replaceTextureWithSubCGImage:(CGImageRef)subimageSource { - CGRect rect = (CGRect) {.origin = CGPointZero, .size = (CGSize){.width = CGImageGetWidth(subimageSource), .height = CGImageGetHeight(subimageSource)}}; - return [self replaceTextureWithSubCGImage:subimageSource inRect:rect]; -} - -- (void)replaceTextureWithSubimage:(UIImage*)subimage inRect:(CGRect)subRect { - return [self replaceTextureWithSubCGImage:[subimage CGImage] inRect:subRect]; -} - -- (void)replaceTextureWithSubCGImage:(CGImageRef)subimageSource inRect:(CGRect)subRect { - NSAssert(outputFramebuffer, @"Picture must be initialized first before replacing subtexture"); - NSAssert(self.framebufferForOutput.textureOptions.internalFormat == GL_RGBA, @"For replacing subtexture the internal texture format must be GL_RGBA."); - - CGRect subimageRect = (CGRect){.origin = CGPointZero, .size = (CGSize){.width = CGImageGetWidth(subimageSource), .height = CGImageGetHeight(subimageSource)}}; - NSAssert(!CGRectIsEmpty(subimageRect), @"Passed sub image must not be empty - it should be at least 1px tall and wide"); - NSAssert(!CGRectIsEmpty(subRect), @"Passed sub rect must not be empty"); - - NSAssert(CGSizeEqualToSize(subimageRect.size, subRect.size), @"Subimage size must match the size of sub rect"); - - // We don't have to worry about scaling the subimage or finding a power of two size. - // The initialization has taken care of that for us. - - dispatch_semaphore_signal(imageUpdateSemaphore); - - BOOL shouldRedrawUsingCoreGraphics = NO; - - // Since internal format is always RGBA, we need the input data in RGBA as well. - CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(subimageSource); - CGBitmapInfo byteOrderInfo = bitmapInfo & kCGBitmapByteOrderMask; - if (byteOrderInfo != kCGBitmapByteOrderDefault && byteOrderInfo != kCGBitmapByteOrder32Big) { - shouldRedrawUsingCoreGraphics = YES; - } - else { - CGImageAlphaInfo alphaInfo = bitmapInfo & kCGBitmapAlphaInfoMask; - if (alphaInfo != kCGImageAlphaPremultipliedLast && alphaInfo != kCGImageAlphaLast && alphaInfo != kCGImageAlphaNoneSkipLast) { - shouldRedrawUsingCoreGraphics = YES; - } - } - - GLubyte *imageData = NULL; - CFDataRef dataFromImageDataProvider; - if (shouldRedrawUsingCoreGraphics) - { - // For resized or incompatible image: redraw - imageData = (GLubyte *) calloc(1, (int)subimageRect.size.width * (int)subimageRect.size.height * 4); - - CGColorSpaceRef genericRGBColorspace = CGColorSpaceCreateDeviceRGB(); - - CGContextRef imageContext = CGBitmapContextCreate(imageData, (size_t)subimageRect.size.width, (size_t)subimageRect.size.height, 8, (size_t)subimageRect.size.width * 4, genericRGBColorspace, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast); - - CGContextDrawImage(imageContext, CGRectMake(0.0, 0.0, subimageRect.size.width, subimageRect.size.height), subimageSource); - CGContextRelease(imageContext); - CGColorSpaceRelease(genericRGBColorspace); - } - else - { - // Access the raw image bytes directly - dataFromImageDataProvider = CGDataProviderCopyData(CGImageGetDataProvider(subimageSource)); - imageData = (GLubyte *)CFDataGetBytePtr(dataFromImageDataProvider); - } - - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext useImageProcessingContext]; - [outputFramebuffer disableReferenceCounting]; - - glBindTexture(GL_TEXTURE_2D, [outputFramebuffer texture]); - - // no need to use self.outputTextureOptions here since pictures need this texture formats and type - glTexSubImage2D(GL_TEXTURE_2D, 0, subRect.origin.x, subRect.origin.y, (GLint)subRect.size.width, subRect.size.height, GL_RGBA, GL_UNSIGNED_BYTE, imageData); - - if (self.shouldSmoothlyScaleOutput) - { - glGenerateMipmap(GL_TEXTURE_2D); - } - glBindTexture(GL_TEXTURE_2D, 0); - }); - - if (shouldRedrawUsingCoreGraphics) - { - free(imageData); - } - else - { - CFRelease(dataFromImageDataProvider); - } -} -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImagePicture.h b/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImagePicture.h deleted file mode 100755 index 1ae0ef4a..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImagePicture.h +++ /dev/null @@ -1,34 +0,0 @@ -#import -#import "GPUImageOutput.h" - - -@interface GPUImagePicture : GPUImageOutput -{ - CGSize pixelSizeOfImage; - BOOL hasProcessedImage; - - dispatch_semaphore_t imageUpdateSemaphore; -} - -// Initialization and teardown -- (id)initWithURL:(NSURL *)url; -- (id)initWithImage:(UIImage *)newImageSource; -- (id)initWithCGImage:(CGImageRef)newImageSource; -- (id)initWithImage:(UIImage *)newImageSource smoothlyScaleOutput:(BOOL)smoothlyScaleOutput; -- (id)initWithCGImage:(CGImageRef)newImageSource smoothlyScaleOutput:(BOOL)smoothlyScaleOutput; - -// Image rendering -- (void)processImage; -- (CGSize)outputImageSize; - -/** - * Process image with all targets and filters asynchronously - * The completion handler is called after processing finished in the - * GPU's dispatch queue - and only if this method did not return NO. - * - * @returns NO if resource is blocked and processing is discarded, YES otherwise - */ -- (BOOL)processImageWithCompletionHandler:(void (^)(void))completion; -- (void)processImageUpToFilter:(GPUImageOutput *)finalFilterInChain withCompletionHandler:(void (^)(UIImage *processedImage))block; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImagePicture.m b/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImagePicture.m deleted file mode 100755 index 97602cf1..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImagePicture.m +++ /dev/null @@ -1,304 +0,0 @@ -#import "GPUImagePicture.h" - -@implementation GPUImagePicture - -#pragma mark - -#pragma mark Initialization and teardown - -- (id)initWithURL:(NSURL *)url; -{ - NSData *imageData = [[NSData alloc] initWithContentsOfURL:url]; - - if (!(self = [self initWithData:imageData])) - { - return nil; - } - - return self; -} - -- (id)initWithData:(NSData *)imageData; -{ - UIImage *inputImage = [[UIImage alloc] initWithData:imageData]; - - if (!(self = [self initWithImage:inputImage])) - { - return nil; - } - - return self; -} - -- (id)initWithImage:(UIImage *)newImageSource; -{ - if (!(self = [self initWithImage:newImageSource smoothlyScaleOutput:NO])) - { - return nil; - } - - return self; -} - -- (id)initWithCGImage:(CGImageRef)newImageSource; -{ - if (!(self = [self initWithCGImage:newImageSource smoothlyScaleOutput:NO])) - { - return nil; - } - return self; -} - -- (id)initWithImage:(UIImage *)newImageSource smoothlyScaleOutput:(BOOL)smoothlyScaleOutput; -{ - return [self initWithCGImage:[newImageSource CGImage] smoothlyScaleOutput:smoothlyScaleOutput]; -} - -- (id)initWithCGImage:(CGImageRef)newImageSource smoothlyScaleOutput:(BOOL)smoothlyScaleOutput; -{ - if (!(self = [super init])) - { - return nil; - } - - hasProcessedImage = NO; - self.shouldSmoothlyScaleOutput = smoothlyScaleOutput; - imageUpdateSemaphore = dispatch_semaphore_create(0); - dispatch_semaphore_signal(imageUpdateSemaphore); - - - // TODO: Dispatch this whole thing asynchronously to move image loading off main thread - CGFloat widthOfImage = CGImageGetWidth(newImageSource); - CGFloat heightOfImage = CGImageGetHeight(newImageSource); - - // If passed an empty image reference, CGContextDrawImage will fail in future versions of the SDK. - NSAssert( widthOfImage > 0 && heightOfImage > 0, @"Passed image must not be empty - it should be at least 1px tall and wide"); - - pixelSizeOfImage = CGSizeMake(widthOfImage, heightOfImage); - CGSize pixelSizeToUseForTexture = pixelSizeOfImage; - - BOOL shouldRedrawUsingCoreGraphics = NO; - - // For now, deal with images larger than the maximum texture size by resizing to be within that limit - CGSize scaledImageSizeToFitOnGPU = [GPUImageContext sizeThatFitsWithinATextureForSize:pixelSizeOfImage]; - if (!CGSizeEqualToSize(scaledImageSizeToFitOnGPU, pixelSizeOfImage)) - { - pixelSizeOfImage = scaledImageSizeToFitOnGPU; - pixelSizeToUseForTexture = pixelSizeOfImage; - shouldRedrawUsingCoreGraphics = YES; - } - - if (self.shouldSmoothlyScaleOutput) - { - // In order to use mipmaps, you need to provide power-of-two textures, so convert to the next largest power of two and stretch to fill - CGFloat powerClosestToWidth = ceil(log2(pixelSizeOfImage.width)); - CGFloat powerClosestToHeight = ceil(log2(pixelSizeOfImage.height)); - - pixelSizeToUseForTexture = CGSizeMake(pow(2.0, powerClosestToWidth), pow(2.0, powerClosestToHeight)); - - shouldRedrawUsingCoreGraphics = YES; - } - - GLubyte *imageData = NULL; - CFDataRef dataFromImageDataProvider = NULL; - GLenum format = GL_BGRA; - - if (!shouldRedrawUsingCoreGraphics) { - /* Check that the memory layout is compatible with GL, as we cannot use glPixelStore to - * tell GL about the memory layout with GLES. - */ - if (CGImageGetBytesPerRow(newImageSource) != CGImageGetWidth(newImageSource) * 4 || - CGImageGetBitsPerPixel(newImageSource) != 32 || - CGImageGetBitsPerComponent(newImageSource) != 8) - { - shouldRedrawUsingCoreGraphics = YES; - } else { - /* Check that the bitmap pixel format is compatible with GL */ - CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(newImageSource); - if ((bitmapInfo & kCGBitmapFloatComponents) != 0) { - /* We don't support float components for use directly in GL */ - shouldRedrawUsingCoreGraphics = YES; - } else { - CGBitmapInfo byteOrderInfo = bitmapInfo & kCGBitmapByteOrderMask; - if (byteOrderInfo == kCGBitmapByteOrder32Little) { - /* Little endian, for alpha-first we can use this bitmap directly in GL */ - CGImageAlphaInfo alphaInfo = bitmapInfo & kCGBitmapAlphaInfoMask; - if (alphaInfo != kCGImageAlphaPremultipliedFirst && alphaInfo != kCGImageAlphaFirst && - alphaInfo != kCGImageAlphaNoneSkipFirst) { - shouldRedrawUsingCoreGraphics = YES; - } - } else if (byteOrderInfo == kCGBitmapByteOrderDefault || byteOrderInfo == kCGBitmapByteOrder32Big) { - /* Big endian, for alpha-last we can use this bitmap directly in GL */ - CGImageAlphaInfo alphaInfo = bitmapInfo & kCGBitmapAlphaInfoMask; - if (alphaInfo != kCGImageAlphaPremultipliedLast && alphaInfo != kCGImageAlphaLast && - alphaInfo != kCGImageAlphaNoneSkipLast) { - shouldRedrawUsingCoreGraphics = YES; - } else { - /* Can access directly using GL_RGBA pixel format */ - format = GL_RGBA; - } - } - } - } - } - - // CFAbsoluteTime elapsedTime, startTime = CFAbsoluteTimeGetCurrent(); - - if (shouldRedrawUsingCoreGraphics) - { - // For resized or incompatible image: redraw - imageData = (GLubyte *) calloc(1, (int)pixelSizeToUseForTexture.width * (int)pixelSizeToUseForTexture.height * 4); - - CGColorSpaceRef genericRGBColorspace = CGColorSpaceCreateDeviceRGB(); - - CGContextRef imageContext = CGBitmapContextCreate(imageData, (size_t)pixelSizeToUseForTexture.width, (size_t)pixelSizeToUseForTexture.height, 8, (size_t)pixelSizeToUseForTexture.width * 4, genericRGBColorspace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); - // CGContextSetBlendMode(imageContext, kCGBlendModeCopy); // From Technical Q&A QA1708: http://developer.apple.com/library/ios/#qa/qa1708/_index.html - CGContextDrawImage(imageContext, CGRectMake(0.0, 0.0, pixelSizeToUseForTexture.width, pixelSizeToUseForTexture.height), newImageSource); - CGContextRelease(imageContext); - CGColorSpaceRelease(genericRGBColorspace); - } - else - { - // Access the raw image bytes directly - dataFromImageDataProvider = CGDataProviderCopyData(CGImageGetDataProvider(newImageSource)); - imageData = (GLubyte *)CFDataGetBytePtr(dataFromImageDataProvider); - } - - // elapsedTime = (CFAbsoluteTimeGetCurrent() - startTime) * 1000.0; - // NSLog(@"Core Graphics drawing time: %f", elapsedTime); - - // CGFloat currentRedTotal = 0.0f, currentGreenTotal = 0.0f, currentBlueTotal = 0.0f, currentAlphaTotal = 0.0f; - // NSUInteger totalNumberOfPixels = round(pixelSizeToUseForTexture.width * pixelSizeToUseForTexture.height); - // - // for (NSUInteger currentPixel = 0; currentPixel < totalNumberOfPixels; currentPixel++) - // { - // currentBlueTotal += (CGFloat)imageData[(currentPixel * 4)] / 255.0f; - // currentGreenTotal += (CGFloat)imageData[(currentPixel * 4) + 1] / 255.0f; - // currentRedTotal += (CGFloat)imageData[(currentPixel * 4 + 2)] / 255.0f; - // currentAlphaTotal += (CGFloat)imageData[(currentPixel * 4) + 3] / 255.0f; - // } - // - // NSLog(@"Debug, average input image red: %f, green: %f, blue: %f, alpha: %f", currentRedTotal / (CGFloat)totalNumberOfPixels, currentGreenTotal / (CGFloat)totalNumberOfPixels, currentBlueTotal / (CGFloat)totalNumberOfPixels, currentAlphaTotal / (CGFloat)totalNumberOfPixels); - - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext useImageProcessingContext]; - - outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:pixelSizeToUseForTexture onlyTexture:YES]; - [outputFramebuffer disableReferenceCounting]; - - glBindTexture(GL_TEXTURE_2D, [outputFramebuffer texture]); - if (self.shouldSmoothlyScaleOutput) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - } - // no need to use self.outputTextureOptions here since pictures need this texture formats and type - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)pixelSizeToUseForTexture.width, (int)pixelSizeToUseForTexture.height, 0, format, GL_UNSIGNED_BYTE, imageData); - - if (self.shouldSmoothlyScaleOutput) - { - glGenerateMipmap(GL_TEXTURE_2D); - } - glBindTexture(GL_TEXTURE_2D, 0); - }); - - if (shouldRedrawUsingCoreGraphics) - { - free(imageData); - } - else - { - if (dataFromImageDataProvider) - { - CFRelease(dataFromImageDataProvider); - } - } - - return self; -} - -// ARC forbids explicit message send of 'release'; since iOS 6 even for dispatch_release() calls: stripping it out in that case is required. -- (void)dealloc; -{ - [outputFramebuffer enableReferenceCounting]; - [outputFramebuffer unlock]; - -#if !OS_OBJECT_USE_OBJC - if (imageUpdateSemaphore != NULL) - { - dispatch_release(imageUpdateSemaphore); - } -#endif -} - -#pragma mark - -#pragma mark Image rendering - -- (void)removeAllTargets; -{ - [super removeAllTargets]; - hasProcessedImage = NO; -} - -- (void)processImage; -{ - [self processImageWithCompletionHandler:nil]; -} - -- (BOOL)processImageWithCompletionHandler:(void (^)(void))completion; -{ - hasProcessedImage = YES; - - // dispatch_semaphore_wait(imageUpdateSemaphore, DISPATCH_TIME_FOREVER); - - if (dispatch_semaphore_wait(imageUpdateSemaphore, DISPATCH_TIME_NOW) != 0) - { - return NO; - } - - runAsynchronouslyOnVideoProcessingQueue(^{ - for (id currentTarget in targets) - { - NSInteger indexOfObject = [targets indexOfObject:currentTarget]; - NSInteger textureIndexOfTarget = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; - - [currentTarget setCurrentlyReceivingMonochromeInput:NO]; - [currentTarget setInputSize:pixelSizeOfImage atIndex:textureIndexOfTarget]; - [currentTarget setInputFramebuffer:outputFramebuffer atIndex:textureIndexOfTarget]; - [currentTarget newFrameReadyAtTime:kCMTimeIndefinite atIndex:textureIndexOfTarget]; - } - - dispatch_semaphore_signal(imageUpdateSemaphore); - - if (completion != nil) { - completion(); - } - }); - - return YES; -} - -- (void)processImageUpToFilter:(GPUImageOutput *)finalFilterInChain withCompletionHandler:(void (^)(UIImage *processedImage))block; -{ - [finalFilterInChain useNextFrameForImageCapture]; - [self processImageWithCompletionHandler:^{ - UIImage *imageFromFilter = [finalFilterInChain imageFromCurrentFramebuffer]; - block(imageFromFilter); - }]; -} - -- (CGSize)outputImageSize; -{ - return pixelSizeOfImage; -} - -- (void)addTarget:(id)newTarget atTextureLocation:(NSInteger)textureLocation; -{ - [super addTarget:newTarget atTextureLocation:textureLocation]; - - if (hasProcessedImage) - { - [newTarget setInputSize:pixelSizeOfImage atIndex:textureLocation]; - [newTarget newFrameReadyAtTime:kCMTimeIndefinite atIndex:textureLocation]; - } -} - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageView.h b/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageView.h deleted file mode 100755 index 03e12ee5..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageView.h +++ /dev/null @@ -1,39 +0,0 @@ -#import -#import "GPUImageContext.h" - -typedef enum { - kGPUImageFillModeStretch, // Stretch to fill the full view, which may distort the image outside of its normal aspect ratio - kGPUImageFillModePreserveAspectRatio, // Maintains the aspect ratio of the source image, adding bars of the specified background color - kGPUImageFillModePreserveAspectRatioAndFill // Maintains the aspect ratio of the source image, zooming in on its center to fill the view -} GPUImageFillModeType; - -/** - UIView subclass to use as an endpoint for displaying GPUImage outputs - */ -@interface GPUImageView : UIView -{ - GPUImageRotationMode inputRotation; -} - -/** The fill mode dictates how images are fit in the view, with the default being kGPUImageFillModePreserveAspectRatio - */ -@property(readwrite, nonatomic) GPUImageFillModeType fillMode; - -/** This calculates the current display size, in pixels, taking into account Retina scaling factors - */ -@property(readonly, nonatomic) CGSize sizeInPixels; - -@property(nonatomic) BOOL enabled; - -/** Handling fill mode - - @param redComponent Red component for background color - @param greenComponent Green component for background color - @param blueComponent Blue component for background color - @param alphaComponent Alpha component for background color - */ -- (void)setBackgroundColorRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent alpha:(GLfloat)alphaComponent; - -- (void)setCurrentlyReceivingMonochromeInput:(BOOL)newValue; - -@end diff --git a/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageView.m b/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageView.m deleted file mode 100755 index 5def624c..00000000 --- a/iOS_Tips/Pods/GPUImage/framework/Source/iOS/GPUImageView.m +++ /dev/null @@ -1,481 +0,0 @@ -#import "GPUImageView.h" -#import -#import -#import "GPUImageContext.h" -#import "GPUImageFilter.h" -#import - -#pragma mark - -#pragma mark Private methods and instance variables - -@interface GPUImageView () -{ - GPUImageFramebuffer *inputFramebufferForDisplay; - GLuint displayRenderbuffer, displayFramebuffer; - - GLProgram *displayProgram; - GLint displayPositionAttribute, displayTextureCoordinateAttribute; - GLint displayInputTextureUniform; - - CGSize inputImageSize; - GLfloat imageVertices[8]; - GLfloat backgroundColorRed, backgroundColorGreen, backgroundColorBlue, backgroundColorAlpha; - - CGSize boundsSizeAtFrameBufferEpoch; -} - -@property (assign, nonatomic) NSUInteger aspectRatio; - -// Initialization and teardown -- (void)commonInit; - -// Managing the display FBOs -- (void)createDisplayFramebuffer; -- (void)destroyDisplayFramebuffer; - -// Handling fill mode -- (void)recalculateViewGeometry; - -@end - -@implementation GPUImageView - -@synthesize aspectRatio; -@synthesize sizeInPixels = _sizeInPixels; -@synthesize fillMode = _fillMode; -@synthesize enabled; - -#pragma mark - -#pragma mark Initialization and teardown - -+ (Class)layerClass -{ - return [CAEAGLLayer class]; -} - -- (id)initWithFrame:(CGRect)frame -{ - if (!(self = [super initWithFrame:frame])) - { - return nil; - } - - [self commonInit]; - - return self; -} - --(id)initWithCoder:(NSCoder *)coder -{ - if (!(self = [super initWithCoder:coder])) - { - return nil; - } - - [self commonInit]; - - return self; -} - -- (void)commonInit; -{ - // Set scaling to account for Retina display - if ([self respondsToSelector:@selector(setContentScaleFactor:)]) - { - self.contentScaleFactor = [[UIScreen mainScreen] scale]; - } - - inputRotation = kGPUImageNoRotation; - self.opaque = YES; - self.hidden = NO; - CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer; - eaglLayer.opaque = YES; - eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil]; - - self.enabled = YES; - - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext useImageProcessingContext]; - - displayProgram = [[GPUImageContext sharedImageProcessingContext] programForVertexShaderString:kGPUImageVertexShaderString fragmentShaderString:kGPUImagePassthroughFragmentShaderString]; - if (!displayProgram.initialized) - { - [displayProgram addAttribute:@"position"]; - [displayProgram addAttribute:@"inputTextureCoordinate"]; - - if (![displayProgram link]) - { - NSString *progLog = [displayProgram programLog]; - NSLog(@"Program link log: %@", progLog); - NSString *fragLog = [displayProgram fragmentShaderLog]; - NSLog(@"Fragment shader compile log: %@", fragLog); - NSString *vertLog = [displayProgram vertexShaderLog]; - NSLog(@"Vertex shader compile log: %@", vertLog); - displayProgram = nil; - NSAssert(NO, @"Filter shader link failed"); - } - } - - displayPositionAttribute = [displayProgram attributeIndex:@"position"]; - displayTextureCoordinateAttribute = [displayProgram attributeIndex:@"inputTextureCoordinate"]; - displayInputTextureUniform = [displayProgram uniformIndex:@"inputImageTexture"]; // This does assume a name of "inputTexture" for the fragment shader - - [GPUImageContext setActiveShaderProgram:displayProgram]; - glEnableVertexAttribArray(displayPositionAttribute); - glEnableVertexAttribArray(displayTextureCoordinateAttribute); - - [self setBackgroundColorRed:0.0 green:0.0 blue:0.0 alpha:1.0]; - _fillMode = kGPUImageFillModePreserveAspectRatio; - [self createDisplayFramebuffer]; - }); -} - -- (void)layoutSubviews { - [super layoutSubviews]; - - // The frame buffer needs to be trashed and re-created when the view size changes. - if (!CGSizeEqualToSize(self.bounds.size, boundsSizeAtFrameBufferEpoch) && - !CGSizeEqualToSize(self.bounds.size, CGSizeZero)) { - runSynchronouslyOnVideoProcessingQueue(^{ - [self destroyDisplayFramebuffer]; - [self createDisplayFramebuffer]; - [self recalculateViewGeometry]; - }); - } -} - -- (void)dealloc -{ - runSynchronouslyOnVideoProcessingQueue(^{ - [self destroyDisplayFramebuffer]; - }); -} - -#pragma mark - -#pragma mark Managing the display FBOs - -- (void)createDisplayFramebuffer; -{ - [GPUImageContext useImageProcessingContext]; - - glGenFramebuffers(1, &displayFramebuffer); - glBindFramebuffer(GL_FRAMEBUFFER, displayFramebuffer); - - glGenRenderbuffers(1, &displayRenderbuffer); - glBindRenderbuffer(GL_RENDERBUFFER, displayRenderbuffer); - - [[[GPUImageContext sharedImageProcessingContext] context] renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer]; - - GLint backingWidth, backingHeight; - - glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth); - glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight); - - if ( (backingWidth == 0) || (backingHeight == 0) ) - { - [self destroyDisplayFramebuffer]; - return; - } - - _sizeInPixels.width = (CGFloat)backingWidth; - _sizeInPixels.height = (CGFloat)backingHeight; - -// NSLog(@"Backing width: %d, height: %d", backingWidth, backingHeight); - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, displayRenderbuffer); - - GLuint framebufferCreationStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); - NSAssert(framebufferCreationStatus == GL_FRAMEBUFFER_COMPLETE, @"Failure with display framebuffer generation for display of size: %f, %f", self.bounds.size.width, self.bounds.size.height); - boundsSizeAtFrameBufferEpoch = self.bounds.size; -} - -- (void)destroyDisplayFramebuffer; -{ - [GPUImageContext useImageProcessingContext]; - - if (displayFramebuffer) - { - glDeleteFramebuffers(1, &displayFramebuffer); - displayFramebuffer = 0; - } - - if (displayRenderbuffer) - { - glDeleteRenderbuffers(1, &displayRenderbuffer); - displayRenderbuffer = 0; - } -} - -- (void)setDisplayFramebuffer; -{ - if (!displayFramebuffer) - { - [self createDisplayFramebuffer]; - } - - glBindFramebuffer(GL_FRAMEBUFFER, displayFramebuffer); - - glViewport(0, 0, (GLint)_sizeInPixels.width, (GLint)_sizeInPixels.height); -} - -- (void)presentFramebuffer; -{ - glBindRenderbuffer(GL_RENDERBUFFER, displayRenderbuffer); - [[GPUImageContext sharedImageProcessingContext] presentBufferForDisplay]; -} - -#pragma mark - -#pragma mark Handling fill mode - -- (void)recalculateViewGeometry; -{ - runSynchronouslyOnVideoProcessingQueue(^{ - CGFloat heightScaling, widthScaling; - - CGSize currentViewSize = self.bounds.size; - - // CGFloat imageAspectRatio = inputImageSize.width / inputImageSize.height; - // CGFloat viewAspectRatio = currentViewSize.width / currentViewSize.height; - - CGRect insetRect = AVMakeRectWithAspectRatioInsideRect(inputImageSize, self.bounds); - - switch(_fillMode) - { - case kGPUImageFillModeStretch: - { - widthScaling = 1.0; - heightScaling = 1.0; - }; break; - case kGPUImageFillModePreserveAspectRatio: - { - widthScaling = insetRect.size.width / currentViewSize.width; - heightScaling = insetRect.size.height / currentViewSize.height; - }; break; - case kGPUImageFillModePreserveAspectRatioAndFill: - { - // CGFloat widthHolder = insetRect.size.width / currentViewSize.width; - widthScaling = currentViewSize.height / insetRect.size.height; - heightScaling = currentViewSize.width / insetRect.size.width; - }; break; - } - - imageVertices[0] = -widthScaling; - imageVertices[1] = -heightScaling; - imageVertices[2] = widthScaling; - imageVertices[3] = -heightScaling; - imageVertices[4] = -widthScaling; - imageVertices[5] = heightScaling; - imageVertices[6] = widthScaling; - imageVertices[7] = heightScaling; - }); - -// static const GLfloat imageVertices[] = { -// -1.0f, -1.0f, -// 1.0f, -1.0f, -// -1.0f, 1.0f, -// 1.0f, 1.0f, -// }; -} - -- (void)setBackgroundColorRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent alpha:(GLfloat)alphaComponent; -{ - backgroundColorRed = redComponent; - backgroundColorGreen = greenComponent; - backgroundColorBlue = blueComponent; - backgroundColorAlpha = alphaComponent; -} - -+ (const GLfloat *)textureCoordinatesForRotation:(GPUImageRotationMode)rotationMode; -{ -// static const GLfloat noRotationTextureCoordinates[] = { -// 0.0f, 0.0f, -// 1.0f, 0.0f, -// 0.0f, 1.0f, -// 1.0f, 1.0f, -// }; - - static const GLfloat noRotationTextureCoordinates[] = { - 0.0f, 1.0f, - 1.0f, 1.0f, - 0.0f, 0.0f, - 1.0f, 0.0f, - }; - - static const GLfloat rotateRightTextureCoordinates[] = { - 1.0f, 1.0f, - 1.0f, 0.0f, - 0.0f, 1.0f, - 0.0f, 0.0f, - }; - - static const GLfloat rotateLeftTextureCoordinates[] = { - 0.0f, 0.0f, - 0.0f, 1.0f, - 1.0f, 0.0f, - 1.0f, 1.0f, - }; - - static const GLfloat verticalFlipTextureCoordinates[] = { - 0.0f, 0.0f, - 1.0f, 0.0f, - 0.0f, 1.0f, - 1.0f, 1.0f, - }; - - static const GLfloat horizontalFlipTextureCoordinates[] = { - 1.0f, 1.0f, - 0.0f, 1.0f, - 1.0f, 0.0f, - 0.0f, 0.0f, - }; - - static const GLfloat rotateRightVerticalFlipTextureCoordinates[] = { - 1.0f, 0.0f, - 1.0f, 1.0f, - 0.0f, 0.0f, - 0.0f, 1.0f, - }; - - static const GLfloat rotateRightHorizontalFlipTextureCoordinates[] = { - 1.0f, 1.0f, - 1.0f, 0.0f, - 0.0f, 1.0f, - 0.0f, 0.0f, - }; - - static const GLfloat rotate180TextureCoordinates[] = { - 1.0f, 0.0f, - 0.0f, 0.0f, - 1.0f, 1.0f, - 0.0f, 1.0f, - }; - - switch(rotationMode) - { - case kGPUImageNoRotation: return noRotationTextureCoordinates; - case kGPUImageRotateLeft: return rotateLeftTextureCoordinates; - case kGPUImageRotateRight: return rotateRightTextureCoordinates; - case kGPUImageFlipVertical: return verticalFlipTextureCoordinates; - case kGPUImageFlipHorizonal: return horizontalFlipTextureCoordinates; - case kGPUImageRotateRightFlipVertical: return rotateRightVerticalFlipTextureCoordinates; - case kGPUImageRotateRightFlipHorizontal: return rotateRightHorizontalFlipTextureCoordinates; - case kGPUImageRotate180: return rotate180TextureCoordinates; - } -} - -#pragma mark - -#pragma mark GPUInput protocol - -- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex; -{ - runSynchronouslyOnVideoProcessingQueue(^{ - [GPUImageContext setActiveShaderProgram:displayProgram]; - [self setDisplayFramebuffer]; - - glClearColor(backgroundColorRed, backgroundColorGreen, backgroundColorBlue, backgroundColorAlpha); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glActiveTexture(GL_TEXTURE4); - glBindTexture(GL_TEXTURE_2D, [inputFramebufferForDisplay texture]); - glUniform1i(displayInputTextureUniform, 4); - - glVertexAttribPointer(displayPositionAttribute, 2, GL_FLOAT, 0, 0, imageVertices); - glVertexAttribPointer(displayTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, [GPUImageView textureCoordinatesForRotation:inputRotation]); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - [self presentFramebuffer]; - [inputFramebufferForDisplay unlock]; - inputFramebufferForDisplay = nil; - }); -} - -- (NSInteger)nextAvailableTextureIndex; -{ - return 0; -} - -- (void)setInputFramebuffer:(GPUImageFramebuffer *)newInputFramebuffer atIndex:(NSInteger)textureIndex; -{ - inputFramebufferForDisplay = newInputFramebuffer; - [inputFramebufferForDisplay lock]; -} - -- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; -{ - inputRotation = newInputRotation; -} - -- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex; -{ - runSynchronouslyOnVideoProcessingQueue(^{ - CGSize rotatedSize = newSize; - - if (GPUImageRotationSwapsWidthAndHeight(inputRotation)) - { - rotatedSize.width = newSize.height; - rotatedSize.height = newSize.width; - } - - if (!CGSizeEqualToSize(inputImageSize, rotatedSize)) - { - inputImageSize = rotatedSize; - [self recalculateViewGeometry]; - } - }); -} - -- (CGSize)maximumOutputSize; -{ - if ([self respondsToSelector:@selector(setContentScaleFactor:)]) - { - CGSize pointSize = self.bounds.size; - return CGSizeMake(self.contentScaleFactor * pointSize.width, self.contentScaleFactor * pointSize.height); - } - else - { - return self.bounds.size; - } -} - -- (void)endProcessing -{ -} - -- (BOOL)shouldIgnoreUpdatesToThisTarget; -{ - return NO; -} - -- (BOOL)wantsMonochromeInput; -{ - return NO; -} - -- (void)setCurrentlyReceivingMonochromeInput:(BOOL)newValue; -{ - -} - -#pragma mark - -#pragma mark Accessors - -- (CGSize)sizeInPixels; -{ - if (CGSizeEqualToSize(_sizeInPixels, CGSizeZero)) - { - return [self maximumOutputSize]; - } - else - { - return _sizeInPixels; - } -} - -- (void)setFillMode:(GPUImageFillModeType)newValue; -{ - _fillMode = newValue; - [self recalculateViewGeometry]; -} - -@end diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/BaseType.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/BaseType.h deleted file mode 120000 index a4f8a379..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/BaseType.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/BaseType.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBAssociationManager+Internal.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBAssociationManager+Internal.h deleted file mode 120000 index 8747b028..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBAssociationManager+Internal.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Associations/Internal/FBAssociationManager+Internal.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBAssociationManager.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBAssociationManager.h deleted file mode 120000 index 87773ed0..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBAssociationManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Associations/FBAssociationManager.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBBlockInterface.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBBlockInterface.h deleted file mode 120000 index 28b4641e..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBBlockInterface.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockInterface.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBBlockStrongLayout.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBBlockStrongLayout.h deleted file mode 120000 index 831bea23..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBBlockStrongLayout.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockStrongLayout.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBBlockStrongRelationDetector.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBBlockStrongRelationDetector.h deleted file mode 120000 index 0f130bd2..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBBlockStrongRelationDetector.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Layout/Blocks/FBBlockStrongRelationDetector.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBClassStrongLayout.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBClassStrongLayout.h deleted file mode 120000 index b27a4028..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBClassStrongLayout.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayout.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBClassStrongLayoutHelpers.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBClassStrongLayoutHelpers.h deleted file mode 120000 index 0abb7f6d..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBClassStrongLayoutHelpers.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayoutHelpers.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBIvarReference.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBIvarReference.h deleted file mode 120000 index 9d353eef..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBIvarReference.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBIvarReference.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBNodeEnumerator.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBNodeEnumerator.h deleted file mode 120000 index 4c41ee2d..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBNodeEnumerator.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBNodeEnumerator.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectGraphConfiguration.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectGraphConfiguration.h deleted file mode 120000 index 922bcebb..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectGraphConfiguration.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectGraphConfiguration.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectInStructReference.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectInStructReference.h deleted file mode 120000 index 5cf4f43c..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectInStructReference.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBObjectInStructReference.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectReference.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectReference.h deleted file mode 120000 index 57e54c02..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectReference.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Reference/FBObjectReference.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectiveCBlock.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectiveCBlock.h deleted file mode 120000 index 7c42b2da..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectiveCBlock.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCBlock.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectiveCGraphElement+Internal.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectiveCGraphElement+Internal.h deleted file mode 120000 index df1269f4..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectiveCGraphElement+Internal.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Graph/Internal/FBObjectiveCGraphElement+Internal.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectiveCGraphElement.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectiveCGraphElement.h deleted file mode 120000 index 58c6b5b2..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectiveCGraphElement.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCGraphElement.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectiveCNSCFTimer.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectiveCNSCFTimer.h deleted file mode 120000 index 25a71185..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectiveCNSCFTimer.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Graph/Specialization/FBObjectiveCNSCFTimer.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectiveCObject.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectiveCObject.h deleted file mode 120000 index b12969ab..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBObjectiveCObject.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCObject.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBRetainCycleDetector+Internal.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBRetainCycleDetector+Internal.h deleted file mode 120000 index 0c4fa790..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBRetainCycleDetector+Internal.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBRetainCycleDetector+Internal.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBRetainCycleDetector.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBRetainCycleDetector.h deleted file mode 120000 index efd23309..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBRetainCycleDetector.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBRetainCycleDetector.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBRetainCycleUtils.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBRetainCycleUtils.h deleted file mode 120000 index 610a974e..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBRetainCycleUtils.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/FBRetainCycleUtils.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBStandardGraphEdgeFilters.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBStandardGraphEdgeFilters.h deleted file mode 120000 index e040885b..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBStandardGraphEdgeFilters.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Filtering/FBStandardGraphEdgeFilters.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBStructEncodingParser.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBStructEncodingParser.h deleted file mode 120000 index 1884d703..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/FBStructEncodingParser.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/FBStructEncodingParser.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/Struct.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/Struct.h deleted file mode 120000 index 26610318..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/Struct.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/Struct.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/Type.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/Type.h deleted file mode 120000 index f31a3275..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/Type.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/Type.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/fishhook.h b/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/fishhook.h deleted file mode 120000 index 0f149f3d..00000000 --- a/iOS_Tips/Pods/Headers/Private/FBRetainCycleDetector/fishhook.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/fishhook/fishhook.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GLProgram.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GLProgram.h deleted file mode 120000 index 7b517c78..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GLProgram.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GLProgram.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImage.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImage.h deleted file mode 120000 index bca8af3b..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImage.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImage3x3ConvolutionFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImage3x3ConvolutionFilter.h deleted file mode 120000 index 810319ad..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImage3x3ConvolutionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImage3x3ConvolutionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImage3x3TextureSamplingFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImage3x3TextureSamplingFilter.h deleted file mode 120000 index 6e5da5e6..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImage3x3TextureSamplingFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImage3x3TextureSamplingFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAdaptiveThresholdFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAdaptiveThresholdFilter.h deleted file mode 120000 index 547be3d0..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAdaptiveThresholdFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageAdaptiveThresholdFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAddBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAddBlendFilter.h deleted file mode 120000 index c0020c2a..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAddBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageAddBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAlphaBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAlphaBlendFilter.h deleted file mode 120000 index 8d030c71..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAlphaBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageAlphaBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAmatorkaFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAmatorkaFilter.h deleted file mode 120000 index c357f5e3..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAmatorkaFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageAmatorkaFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAverageColor.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAverageColor.h deleted file mode 120000 index 702913cf..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAverageColor.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageAverageColor.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAverageLuminanceThresholdFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAverageLuminanceThresholdFilter.h deleted file mode 120000 index fabcf094..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageAverageLuminanceThresholdFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageAverageLuminanceThresholdFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageBilateralFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageBilateralFilter.h deleted file mode 120000 index 6498b00c..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageBilateralFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageBilateralFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageBoxBlurFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageBoxBlurFilter.h deleted file mode 120000 index 9a4d8f03..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageBoxBlurFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageBoxBlurFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageBrightnessFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageBrightnessFilter.h deleted file mode 120000 index 1b81b6a5..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageBrightnessFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageBrightnessFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageBuffer.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageBuffer.h deleted file mode 120000 index 220ce7f8..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageBuffer.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageBuffer.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageBulgeDistortionFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageBulgeDistortionFilter.h deleted file mode 120000 index ab666324..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageBulgeDistortionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageBulgeDistortionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageCGAColorspaceFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageCGAColorspaceFilter.h deleted file mode 120000 index 3086aeb5..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageCGAColorspaceFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageCGAColorspaceFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageCannyEdgeDetectionFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageCannyEdgeDetectionFilter.h deleted file mode 120000 index 39e89d57..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageCannyEdgeDetectionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageCannyEdgeDetectionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageChromaKeyBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageChromaKeyBlendFilter.h deleted file mode 120000 index cd3ea805..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageChromaKeyBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageChromaKeyBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageChromaKeyFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageChromaKeyFilter.h deleted file mode 120000 index bdecab2f..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageChromaKeyFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageChromaKeyFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageClosingFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageClosingFilter.h deleted file mode 120000 index 5b163840..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageClosingFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageClosingFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorBlendFilter.h deleted file mode 120000 index f72172b7..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageColorBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorBurnBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorBurnBlendFilter.h deleted file mode 120000 index a45ffd4b..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorBurnBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageColorBurnBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorDodgeBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorDodgeBlendFilter.h deleted file mode 120000 index 10e12cb6..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorDodgeBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageColorDodgeBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorInvertFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorInvertFilter.h deleted file mode 120000 index 6961f69a..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorInvertFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageColorInvertFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorMatrixFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorMatrixFilter.h deleted file mode 120000 index 4e8d4d59..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorMatrixFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageColorMatrixFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorPackingFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorPackingFilter.h deleted file mode 120000 index b6ce55c9..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageColorPackingFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageColorPackingFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageContext.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageContext.h deleted file mode 120000 index 40791f1b..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageContext.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/iOS/GPUImageContext.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageContrastFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageContrastFilter.h deleted file mode 120000 index 22057498..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageContrastFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageContrastFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageCropFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageCropFilter.h deleted file mode 120000 index d136ed77..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageCropFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageCropFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageCrosshairGenerator.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageCrosshairGenerator.h deleted file mode 120000 index 2112ba21..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageCrosshairGenerator.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageCrosshairGenerator.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageCrosshatchFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageCrosshatchFilter.h deleted file mode 120000 index 7706d91d..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageCrosshatchFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageCrosshatchFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDarkenBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDarkenBlendFilter.h deleted file mode 120000 index 8fdf8cd5..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDarkenBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageDarkenBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDifferenceBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDifferenceBlendFilter.h deleted file mode 120000 index 6a41b879..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDifferenceBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageDifferenceBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDilationFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDilationFilter.h deleted file mode 120000 index 1b82a7a7..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDilationFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageDilationFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDirectionalNonMaximumSuppressionFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDirectionalNonMaximumSuppressionFilter.h deleted file mode 120000 index c5820fac..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDirectionalNonMaximumSuppressionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageDirectionalNonMaximumSuppressionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDirectionalSobelEdgeDetectionFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDirectionalSobelEdgeDetectionFilter.h deleted file mode 120000 index ebc6b5b8..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDirectionalSobelEdgeDetectionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageDirectionalSobelEdgeDetectionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDissolveBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDissolveBlendFilter.h deleted file mode 120000 index c40a8147..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDissolveBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageDissolveBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDivideBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDivideBlendFilter.h deleted file mode 120000 index e21f3007..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageDivideBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageDivideBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageEmbossFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageEmbossFilter.h deleted file mode 120000 index 93a8ac2d..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageEmbossFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageEmbossFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageErosionFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageErosionFilter.h deleted file mode 120000 index 66c4b920..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageErosionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageErosionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageExclusionBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageExclusionBlendFilter.h deleted file mode 120000 index ee6a437c..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageExclusionBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageExclusionBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageExposureFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageExposureFilter.h deleted file mode 120000 index cb3ec5ed..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageExposureFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageExposureFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFASTCornerDetectionFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFASTCornerDetectionFilter.h deleted file mode 120000 index 6f73c3e1..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFASTCornerDetectionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageFASTCornerDetectionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFalseColorFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFalseColorFilter.h deleted file mode 120000 index 161cc44b..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFalseColorFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageFalseColorFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFilter.h deleted file mode 120000 index c7036945..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFilterGroup.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFilterGroup.h deleted file mode 120000 index c15625a3..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFilterGroup.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageFilterGroup.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFilterPipeline.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFilterPipeline.h deleted file mode 120000 index e3d54cd2..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFilterPipeline.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageFilterPipeline.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFramebuffer.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFramebuffer.h deleted file mode 120000 index 912489a3..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFramebuffer.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageFramebuffer.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFramebufferCache.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFramebufferCache.h deleted file mode 120000 index 14e95530..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFramebufferCache.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageFramebufferCache.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFramework.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFramework.h deleted file mode 120000 index ade56d4a..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageFramework.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/iOS/Framework/GPUImageFramework.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGammaFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGammaFilter.h deleted file mode 120000 index 127ab2c7..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGammaFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageGammaFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGaussianBlurFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGaussianBlurFilter.h deleted file mode 120000 index 2a9ecae7..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGaussianBlurFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageGaussianBlurFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGaussianBlurPositionFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGaussianBlurPositionFilter.h deleted file mode 120000 index 423c806f..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGaussianBlurPositionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageGaussianBlurPositionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGaussianSelectiveBlurFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGaussianSelectiveBlurFilter.h deleted file mode 120000 index 6d410149..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGaussianSelectiveBlurFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageGaussianSelectiveBlurFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGlassSphereFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGlassSphereFilter.h deleted file mode 120000 index e01a6f51..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGlassSphereFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageGlassSphereFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGrayscaleFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGrayscaleFilter.h deleted file mode 120000 index 8332833f..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageGrayscaleFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageGrayscaleFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHSBFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHSBFilter.h deleted file mode 120000 index df50e698..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHSBFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHSBFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHalftoneFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHalftoneFilter.h deleted file mode 120000 index f6151b4d..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHalftoneFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHalftoneFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHardLightBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHardLightBlendFilter.h deleted file mode 120000 index e857cd30..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHardLightBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHardLightBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHarrisCornerDetectionFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHarrisCornerDetectionFilter.h deleted file mode 120000 index cf78593f..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHarrisCornerDetectionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHarrisCornerDetectionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHazeFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHazeFilter.h deleted file mode 120000 index 5b2806e7..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHazeFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHazeFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHighPassFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHighPassFilter.h deleted file mode 120000 index f5063f14..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHighPassFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHighPassFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHighlightShadowFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHighlightShadowFilter.h deleted file mode 120000 index 33329bd5..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHighlightShadowFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHighlightShadowFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHistogramEqualizationFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHistogramEqualizationFilter.h deleted file mode 120000 index 8a2721b7..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHistogramEqualizationFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHistogramEqualizationFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHistogramFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHistogramFilter.h deleted file mode 120000 index b2f97670..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHistogramFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHistogramFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHistogramGenerator.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHistogramGenerator.h deleted file mode 120000 index 03c93a15..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHistogramGenerator.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHistogramGenerator.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHoughTransformLineDetector.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHoughTransformLineDetector.h deleted file mode 120000 index 2d5da6af..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHoughTransformLineDetector.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHoughTransformLineDetector.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHueBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHueBlendFilter.h deleted file mode 120000 index 97d05aaf..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHueBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHueBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHueFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHueFilter.h deleted file mode 120000 index 62c976c1..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageHueFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHueFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageJFAVoronoiFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageJFAVoronoiFilter.h deleted file mode 120000 index f02faeb4..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageJFAVoronoiFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageJFAVoronoiFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageKuwaharaFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageKuwaharaFilter.h deleted file mode 120000 index e64abda0..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageKuwaharaFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageKuwaharaFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageKuwaharaRadius3Filter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageKuwaharaRadius3Filter.h deleted file mode 120000 index 3e2aec8c..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageKuwaharaRadius3Filter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageKuwaharaRadius3Filter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLanczosResamplingFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLanczosResamplingFilter.h deleted file mode 120000 index b036cbba..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLanczosResamplingFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLanczosResamplingFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLaplacianFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLaplacianFilter.h deleted file mode 120000 index d663c479..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLaplacianFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLaplacianFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLevelsFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLevelsFilter.h deleted file mode 120000 index 2d92e6bc..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLevelsFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLevelsFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLightenBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLightenBlendFilter.h deleted file mode 120000 index 425d16c0..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLightenBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLightenBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLineGenerator.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLineGenerator.h deleted file mode 120000 index 5a999110..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLineGenerator.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLineGenerator.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLinearBurnBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLinearBurnBlendFilter.h deleted file mode 120000 index f471fdb9..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLinearBurnBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLinearBurnBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLocalBinaryPatternFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLocalBinaryPatternFilter.h deleted file mode 120000 index 93395da8..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLocalBinaryPatternFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLocalBinaryPatternFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLookupFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLookupFilter.h deleted file mode 120000 index 0ea51d79..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLookupFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLookupFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLowPassFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLowPassFilter.h deleted file mode 120000 index 59aca2a8..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLowPassFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLowPassFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLuminanceRangeFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLuminanceRangeFilter.h deleted file mode 120000 index 9855a2a7..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLuminanceRangeFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLuminanceRangeFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLuminanceThresholdFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLuminanceThresholdFilter.h deleted file mode 120000 index 0b1478af..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLuminanceThresholdFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLuminanceThresholdFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLuminosity.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLuminosity.h deleted file mode 120000 index c20086fa..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLuminosity.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLuminosity.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLuminosityBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLuminosityBlendFilter.h deleted file mode 120000 index 19ef8578..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageLuminosityBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLuminosityBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMaskFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMaskFilter.h deleted file mode 120000 index 29e6989a..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMaskFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageMaskFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMedianFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMedianFilter.h deleted file mode 120000 index 7e68c25d..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMedianFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageMedianFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMissEtikateFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMissEtikateFilter.h deleted file mode 120000 index a0afc5ba..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMissEtikateFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageMissEtikateFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMonochromeFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMonochromeFilter.h deleted file mode 120000 index 8c4201d7..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMonochromeFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageMonochromeFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMosaicFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMosaicFilter.h deleted file mode 120000 index 8f8a3285..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMosaicFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageMosaicFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMotionBlurFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMotionBlurFilter.h deleted file mode 120000 index f2e2b8e0..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMotionBlurFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageMotionBlurFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMotionDetector.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMotionDetector.h deleted file mode 120000 index 8c5b0e10..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMotionDetector.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageMotionDetector.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMovie.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMovie.h deleted file mode 120000 index 4d6e8798..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMovie.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageMovie.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMovieComposition.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMovieComposition.h deleted file mode 120000 index 93598144..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMovieComposition.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageMovieComposition.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMovieWriter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMovieWriter.h deleted file mode 120000 index 0981109d..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMovieWriter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/iOS/GPUImageMovieWriter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMultiplyBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMultiplyBlendFilter.h deleted file mode 120000 index 0b39ea10..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageMultiplyBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageMultiplyBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageNobleCornerDetectionFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageNobleCornerDetectionFilter.h deleted file mode 120000 index e4ea4995..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageNobleCornerDetectionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageNobleCornerDetectionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageNonMaximumSuppressionFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageNonMaximumSuppressionFilter.h deleted file mode 120000 index b5f7957a..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageNonMaximumSuppressionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageNonMaximumSuppressionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageNormalBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageNormalBlendFilter.h deleted file mode 120000 index 5d0b343b..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageNormalBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageNormalBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageOpacityFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageOpacityFilter.h deleted file mode 120000 index 1bcca485..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageOpacityFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageOpacityFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageOpeningFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageOpeningFilter.h deleted file mode 120000 index b68bb068..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageOpeningFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageOpeningFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageOutput.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageOutput.h deleted file mode 120000 index dcb6fab8..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageOutput.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageOutput.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageOverlayBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageOverlayBlendFilter.h deleted file mode 120000 index 34b88fbe..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageOverlayBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageOverlayBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageParallelCoordinateLineTransformFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageParallelCoordinateLineTransformFilter.h deleted file mode 120000 index 8f0d06f6..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageParallelCoordinateLineTransformFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageParallelCoordinateLineTransformFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePerlinNoiseFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePerlinNoiseFilter.h deleted file mode 120000 index 00c2bfe7..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePerlinNoiseFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImagePerlinNoiseFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePicture+TextureSubimage.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePicture+TextureSubimage.h deleted file mode 120000 index 97e13907..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePicture+TextureSubimage.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/iOS/GPUImagePicture+TextureSubimage.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePicture.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePicture.h deleted file mode 120000 index 9999ee88..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePicture.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/iOS/GPUImagePicture.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePinchDistortionFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePinchDistortionFilter.h deleted file mode 120000 index 561065be..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePinchDistortionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImagePinchDistortionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePixellateFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePixellateFilter.h deleted file mode 120000 index 65d5092c..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePixellateFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImagePixellateFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePixellatePositionFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePixellatePositionFilter.h deleted file mode 120000 index 06e3b7e2..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePixellatePositionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImagePixellatePositionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePoissonBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePoissonBlendFilter.h deleted file mode 120000 index c852272e..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePoissonBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImagePoissonBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePolarPixellateFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePolarPixellateFilter.h deleted file mode 120000 index 752176da..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePolarPixellateFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImagePolarPixellateFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePolkaDotFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePolkaDotFilter.h deleted file mode 120000 index dba6db1a..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePolkaDotFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImagePolkaDotFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePosterizeFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePosterizeFilter.h deleted file mode 120000 index 215ea1b0..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePosterizeFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImagePosterizeFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePrewittEdgeDetectionFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePrewittEdgeDetectionFilter.h deleted file mode 120000 index c620cdef..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImagePrewittEdgeDetectionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImagePrewittEdgeDetectionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRGBClosingFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRGBClosingFilter.h deleted file mode 120000 index e958b6df..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRGBClosingFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageRGBClosingFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRGBDilationFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRGBDilationFilter.h deleted file mode 120000 index 406dea33..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRGBDilationFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageRGBDilationFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRGBErosionFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRGBErosionFilter.h deleted file mode 120000 index b0bea951..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRGBErosionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageRGBErosionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRGBFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRGBFilter.h deleted file mode 120000 index 64f0f29e..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRGBFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageRGBFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRGBOpeningFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRGBOpeningFilter.h deleted file mode 120000 index b08322df..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRGBOpeningFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageRGBOpeningFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRawDataInput.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRawDataInput.h deleted file mode 120000 index 3ac18170..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRawDataInput.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageRawDataInput.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRawDataOutput.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRawDataOutput.h deleted file mode 120000 index a08dd75e..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageRawDataOutput.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageRawDataOutput.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSaturationBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSaturationBlendFilter.h deleted file mode 120000 index 128968a3..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSaturationBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSaturationBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSaturationFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSaturationFilter.h deleted file mode 120000 index 9b56c3c2..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSaturationFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSaturationFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageScreenBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageScreenBlendFilter.h deleted file mode 120000 index c09274d9..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageScreenBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageScreenBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSepiaFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSepiaFilter.h deleted file mode 120000 index 6af3120c..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSepiaFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSepiaFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSharpenFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSharpenFilter.h deleted file mode 120000 index a736679d..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSharpenFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSharpenFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageShiTomasiFeatureDetectionFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageShiTomasiFeatureDetectionFilter.h deleted file mode 120000 index 6bfa8c58..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageShiTomasiFeatureDetectionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageShiTomasiFeatureDetectionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSingleComponentGaussianBlurFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSingleComponentGaussianBlurFilter.h deleted file mode 120000 index dd642505..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSingleComponentGaussianBlurFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSingleComponentGaussianBlurFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSketchFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSketchFilter.h deleted file mode 120000 index 9aafd154..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSketchFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSketchFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSmoothToonFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSmoothToonFilter.h deleted file mode 120000 index 8091466f..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSmoothToonFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSmoothToonFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSobelEdgeDetectionFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSobelEdgeDetectionFilter.h deleted file mode 120000 index 019a83d0..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSobelEdgeDetectionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSobelEdgeDetectionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSoftEleganceFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSoftEleganceFilter.h deleted file mode 120000 index ae0fe89b..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSoftEleganceFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSoftEleganceFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSoftLightBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSoftLightBlendFilter.h deleted file mode 120000 index ec5c1881..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSoftLightBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSoftLightBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSolidColorGenerator.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSolidColorGenerator.h deleted file mode 120000 index 4eb09f85..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSolidColorGenerator.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSolidColorGenerator.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSourceOverBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSourceOverBlendFilter.h deleted file mode 120000 index 50dee17d..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSourceOverBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSourceOverBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSphereRefractionFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSphereRefractionFilter.h deleted file mode 120000 index 9ebdd7cb..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSphereRefractionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSphereRefractionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageStillCamera.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageStillCamera.h deleted file mode 120000 index 52fd54f6..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageStillCamera.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageStillCamera.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageStretchDistortionFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageStretchDistortionFilter.h deleted file mode 120000 index 261fca3d..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageStretchDistortionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageStretchDistortionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSubtractBlendFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSubtractBlendFilter.h deleted file mode 120000 index dfc7cb0a..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSubtractBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSubtractBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSwirlFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSwirlFilter.h deleted file mode 120000 index 84091382..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageSwirlFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSwirlFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTextureInput.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTextureInput.h deleted file mode 120000 index da1350a4..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTextureInput.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageTextureInput.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTextureOutput.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTextureOutput.h deleted file mode 120000 index da55e4dc..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTextureOutput.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageTextureOutput.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageThreeInputFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageThreeInputFilter.h deleted file mode 120000 index c3a2659a..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageThreeInputFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageThreeInputFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageThresholdEdgeDetectionFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageThresholdEdgeDetectionFilter.h deleted file mode 120000 index 69d9d2cd..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageThresholdEdgeDetectionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageThresholdEdgeDetectionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageThresholdSketchFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageThresholdSketchFilter.h deleted file mode 120000 index eb97d3b4..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageThresholdSketchFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageThresholdSketchFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageThresholdedNonMaximumSuppressionFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageThresholdedNonMaximumSuppressionFilter.h deleted file mode 120000 index 7ccd2357..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageThresholdedNonMaximumSuppressionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageThresholdedNonMaximumSuppressionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTiltShiftFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTiltShiftFilter.h deleted file mode 120000 index 939825c6..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTiltShiftFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageTiltShiftFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageToneCurveFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageToneCurveFilter.h deleted file mode 120000 index 74c0912c..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageToneCurveFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageToneCurveFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageToonFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageToonFilter.h deleted file mode 120000 index 19aca502..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageToonFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageToonFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTransformFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTransformFilter.h deleted file mode 120000 index 647b8d5c..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTransformFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageTransformFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTwoInputCrossTextureSamplingFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTwoInputCrossTextureSamplingFilter.h deleted file mode 120000 index 37e25218..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTwoInputCrossTextureSamplingFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageTwoInputCrossTextureSamplingFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTwoInputFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTwoInputFilter.h deleted file mode 120000 index c5d5ae16..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTwoInputFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageTwoInputFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTwoPassFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTwoPassFilter.h deleted file mode 120000 index 9ee4bf0b..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTwoPassFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageTwoPassFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTwoPassTextureSamplingFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTwoPassTextureSamplingFilter.h deleted file mode 120000 index 0bd37757..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageTwoPassTextureSamplingFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageTwoPassTextureSamplingFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageUIElement.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageUIElement.h deleted file mode 120000 index cccc6850..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageUIElement.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageUIElement.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageUnsharpMaskFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageUnsharpMaskFilter.h deleted file mode 120000 index 0d612ecd..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageUnsharpMaskFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageUnsharpMaskFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageVideoCamera.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageVideoCamera.h deleted file mode 120000 index e5a2daf8..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageVideoCamera.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageVideoCamera.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageView.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageView.h deleted file mode 120000 index 47efed92..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageView.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/iOS/GPUImageView.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageVignetteFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageVignetteFilter.h deleted file mode 120000 index 82aeec2b..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageVignetteFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageVignetteFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageVoronoiConsumerFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageVoronoiConsumerFilter.h deleted file mode 120000 index 31810f65..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageVoronoiConsumerFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageVoronoiConsumerFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageWeakPixelInclusionFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageWeakPixelInclusionFilter.h deleted file mode 120000 index 851aebf2..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageWeakPixelInclusionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageWeakPixelInclusionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageWhiteBalanceFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageWhiteBalanceFilter.h deleted file mode 120000 index d2318ca5..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageWhiteBalanceFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageWhiteBalanceFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageXYDerivativeFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageXYDerivativeFilter.h deleted file mode 120000 index d6024a32..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageXYDerivativeFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageXYDerivativeFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageZoomBlurFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageZoomBlurFilter.h deleted file mode 120000 index 67da1204..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageZoomBlurFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageZoomBlurFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageiOSBlurFilter.h b/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageiOSBlurFilter.h deleted file mode 120000 index 2bf9dc16..00000000 --- a/iOS_Tips/Pods/Headers/Private/GPUImage/GPUImageiOSBlurFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageiOSBlurFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/MBProgressHUD/MBProgressHUD.h b/iOS_Tips/Pods/Headers/Private/MBProgressHUD/MBProgressHUD.h deleted file mode 120000 index 19ed4db7..00000000 --- a/iOS_Tips/Pods/Headers/Private/MBProgressHUD/MBProgressHUD.h +++ /dev/null @@ -1 +0,0 @@ -../../../MBProgressHUD/MBProgressHUD.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/MLeakedObjectProxy.h b/iOS_Tips/Pods/Headers/Private/MLeaksFinder/MLeakedObjectProxy.h deleted file mode 120000 index 132a394f..00000000 --- a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/MLeakedObjectProxy.h +++ /dev/null @@ -1 +0,0 @@ -../../../MLeaksFinder/MLeaksFinder/MLeakedObjectProxy.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/MLeaksFinder.h b/iOS_Tips/Pods/Headers/Private/MLeaksFinder/MLeaksFinder.h deleted file mode 120000 index 0cf746ab..00000000 --- a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/MLeaksFinder.h +++ /dev/null @@ -1 +0,0 @@ -../../../MLeaksFinder/MLeaksFinder/MLeaksFinder.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/MLeaksMessenger.h b/iOS_Tips/Pods/Headers/Private/MLeaksFinder/MLeaksMessenger.h deleted file mode 120000 index 4615e4f0..00000000 --- a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/MLeaksMessenger.h +++ /dev/null @@ -1 +0,0 @@ -../../../MLeaksFinder/MLeaksFinder/MLeaksMessenger.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/NSObject+MemoryLeak.h b/iOS_Tips/Pods/Headers/Private/MLeaksFinder/NSObject+MemoryLeak.h deleted file mode 120000 index 7343f141..00000000 --- a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/NSObject+MemoryLeak.h +++ /dev/null @@ -1 +0,0 @@ -../../../MLeaksFinder/MLeaksFinder/NSObject+MemoryLeak.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UIApplication+MemoryLeak.h b/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UIApplication+MemoryLeak.h deleted file mode 120000 index ed2b35db..00000000 --- a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UIApplication+MemoryLeak.h +++ /dev/null @@ -1 +0,0 @@ -../../../MLeaksFinder/MLeaksFinder/UIApplication+MemoryLeak.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UINavigationController+MemoryLeak.h b/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UINavigationController+MemoryLeak.h deleted file mode 120000 index 4e0e0aac..00000000 --- a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UINavigationController+MemoryLeak.h +++ /dev/null @@ -1 +0,0 @@ -../../../MLeaksFinder/MLeaksFinder/UINavigationController+MemoryLeak.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UIPageViewController+MemoryLeak.h b/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UIPageViewController+MemoryLeak.h deleted file mode 120000 index fe2af6f3..00000000 --- a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UIPageViewController+MemoryLeak.h +++ /dev/null @@ -1 +0,0 @@ -../../../MLeaksFinder/MLeaksFinder/UIPageViewController+MemoryLeak.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UISplitViewController+MemoryLeak.h b/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UISplitViewController+MemoryLeak.h deleted file mode 120000 index ff0cab9c..00000000 --- a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UISplitViewController+MemoryLeak.h +++ /dev/null @@ -1 +0,0 @@ -../../../MLeaksFinder/MLeaksFinder/UISplitViewController+MemoryLeak.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UITabBarController+MemoryLeak.h b/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UITabBarController+MemoryLeak.h deleted file mode 120000 index 759fea77..00000000 --- a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UITabBarController+MemoryLeak.h +++ /dev/null @@ -1 +0,0 @@ -../../../MLeaksFinder/MLeaksFinder/UITabBarController+MemoryLeak.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UITouch+MemoryLeak.h b/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UITouch+MemoryLeak.h deleted file mode 120000 index f41084a3..00000000 --- a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UITouch+MemoryLeak.h +++ /dev/null @@ -1 +0,0 @@ -../../../MLeaksFinder/MLeaksFinder/UITouch+MemoryLeak.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UIView+MemoryLeak.h b/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UIView+MemoryLeak.h deleted file mode 120000 index 9fc01700..00000000 --- a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UIView+MemoryLeak.h +++ /dev/null @@ -1 +0,0 @@ -../../../MLeaksFinder/MLeaksFinder/UIView+MemoryLeak.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UIViewController+MemoryLeak.h b/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UIViewController+MemoryLeak.h deleted file mode 120000 index cdad092d..00000000 --- a/iOS_Tips/Pods/Headers/Private/MLeaksFinder/UIViewController+MemoryLeak.h +++ /dev/null @@ -1 +0,0 @@ -../../../MLeaksFinder/MLeaksFinder/UIViewController+MemoryLeak.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/Masonry/MASCompositeConstraint.h b/iOS_Tips/Pods/Headers/Private/Masonry/MASCompositeConstraint.h deleted file mode 120000 index b1b34103..00000000 --- a/iOS_Tips/Pods/Headers/Private/Masonry/MASCompositeConstraint.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/MASCompositeConstraint.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/Masonry/MASConstraint+Private.h b/iOS_Tips/Pods/Headers/Private/Masonry/MASConstraint+Private.h deleted file mode 120000 index ed9aa9f3..00000000 --- a/iOS_Tips/Pods/Headers/Private/Masonry/MASConstraint+Private.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/MASConstraint+Private.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/Masonry/MASConstraint.h b/iOS_Tips/Pods/Headers/Private/Masonry/MASConstraint.h deleted file mode 120000 index 76e9e73d..00000000 --- a/iOS_Tips/Pods/Headers/Private/Masonry/MASConstraint.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/MASConstraint.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/Masonry/MASConstraintMaker.h b/iOS_Tips/Pods/Headers/Private/Masonry/MASConstraintMaker.h deleted file mode 120000 index b6d6027b..00000000 --- a/iOS_Tips/Pods/Headers/Private/Masonry/MASConstraintMaker.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/MASConstraintMaker.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/Masonry/MASLayoutConstraint.h b/iOS_Tips/Pods/Headers/Private/Masonry/MASLayoutConstraint.h deleted file mode 120000 index 73e87968..00000000 --- a/iOS_Tips/Pods/Headers/Private/Masonry/MASLayoutConstraint.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/MASLayoutConstraint.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/Masonry/MASUtilities.h b/iOS_Tips/Pods/Headers/Private/Masonry/MASUtilities.h deleted file mode 120000 index aae5e32b..00000000 --- a/iOS_Tips/Pods/Headers/Private/Masonry/MASUtilities.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/MASUtilities.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/Masonry/MASViewAttribute.h b/iOS_Tips/Pods/Headers/Private/Masonry/MASViewAttribute.h deleted file mode 120000 index 5399f642..00000000 --- a/iOS_Tips/Pods/Headers/Private/Masonry/MASViewAttribute.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/MASViewAttribute.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/Masonry/MASViewConstraint.h b/iOS_Tips/Pods/Headers/Private/Masonry/MASViewConstraint.h deleted file mode 120000 index 382c4194..00000000 --- a/iOS_Tips/Pods/Headers/Private/Masonry/MASViewConstraint.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/MASViewConstraint.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/Masonry/Masonry.h b/iOS_Tips/Pods/Headers/Private/Masonry/Masonry.h deleted file mode 120000 index f5093032..00000000 --- a/iOS_Tips/Pods/Headers/Private/Masonry/Masonry.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/Masonry.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/Masonry/NSArray+MASAdditions.h b/iOS_Tips/Pods/Headers/Private/Masonry/NSArray+MASAdditions.h deleted file mode 120000 index db1d0ea7..00000000 --- a/iOS_Tips/Pods/Headers/Private/Masonry/NSArray+MASAdditions.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/NSArray+MASAdditions.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/Masonry/NSArray+MASShorthandAdditions.h b/iOS_Tips/Pods/Headers/Private/Masonry/NSArray+MASShorthandAdditions.h deleted file mode 120000 index 2169edc5..00000000 --- a/iOS_Tips/Pods/Headers/Private/Masonry/NSArray+MASShorthandAdditions.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/NSArray+MASShorthandAdditions.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/Masonry/NSLayoutConstraint+MASDebugAdditions.h b/iOS_Tips/Pods/Headers/Private/Masonry/NSLayoutConstraint+MASDebugAdditions.h deleted file mode 120000 index 72f59430..00000000 --- a/iOS_Tips/Pods/Headers/Private/Masonry/NSLayoutConstraint+MASDebugAdditions.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/NSLayoutConstraint+MASDebugAdditions.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/Masonry/View+MASAdditions.h b/iOS_Tips/Pods/Headers/Private/Masonry/View+MASAdditions.h deleted file mode 120000 index 9060451a..00000000 --- a/iOS_Tips/Pods/Headers/Private/Masonry/View+MASAdditions.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/View+MASAdditions.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/Masonry/View+MASShorthandAdditions.h b/iOS_Tips/Pods/Headers/Private/Masonry/View+MASShorthandAdditions.h deleted file mode 120000 index 91ef93fa..00000000 --- a/iOS_Tips/Pods/Headers/Private/Masonry/View+MASShorthandAdditions.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/View+MASShorthandAdditions.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Private/Masonry/ViewController+MASAdditions.h b/iOS_Tips/Pods/Headers/Private/Masonry/ViewController+MASAdditions.h deleted file mode 120000 index 12320e3f..00000000 --- a/iOS_Tips/Pods/Headers/Private/Masonry/ViewController+MASAdditions.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/ViewController+MASAdditions.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBAssociationManager.h b/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBAssociationManager.h deleted file mode 120000 index 87773ed0..00000000 --- a/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBAssociationManager.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Associations/FBAssociationManager.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBObjectGraphConfiguration.h b/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBObjectGraphConfiguration.h deleted file mode 120000 index 922bcebb..00000000 --- a/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBObjectGraphConfiguration.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectGraphConfiguration.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBObjectiveCBlock.h b/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBObjectiveCBlock.h deleted file mode 120000 index 7c42b2da..00000000 --- a/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBObjectiveCBlock.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCBlock.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBObjectiveCGraphElement.h b/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBObjectiveCGraphElement.h deleted file mode 120000 index 58c6b5b2..00000000 --- a/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBObjectiveCGraphElement.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCGraphElement.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBObjectiveCNSCFTimer.h b/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBObjectiveCNSCFTimer.h deleted file mode 120000 index 25a71185..00000000 --- a/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBObjectiveCNSCFTimer.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Graph/Specialization/FBObjectiveCNSCFTimer.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBObjectiveCObject.h b/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBObjectiveCObject.h deleted file mode 120000 index b12969ab..00000000 --- a/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBObjectiveCObject.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCObject.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBRetainCycleDetector.h b/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBRetainCycleDetector.h deleted file mode 120000 index efd23309..00000000 --- a/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBRetainCycleDetector.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Detector/FBRetainCycleDetector.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBStandardGraphEdgeFilters.h b/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBStandardGraphEdgeFilters.h deleted file mode 120000 index e040885b..00000000 --- a/iOS_Tips/Pods/Headers/Public/FBRetainCycleDetector/FBStandardGraphEdgeFilters.h +++ /dev/null @@ -1 +0,0 @@ -../../../FBRetainCycleDetector/FBRetainCycleDetector/Filtering/FBStandardGraphEdgeFilters.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GLProgram.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GLProgram.h deleted file mode 120000 index 7b517c78..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GLProgram.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GLProgram.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImage.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImage.h deleted file mode 120000 index bca8af3b..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImage.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImage.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImage3x3ConvolutionFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImage3x3ConvolutionFilter.h deleted file mode 120000 index 810319ad..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImage3x3ConvolutionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImage3x3ConvolutionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImage3x3TextureSamplingFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImage3x3TextureSamplingFilter.h deleted file mode 120000 index 6e5da5e6..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImage3x3TextureSamplingFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImage3x3TextureSamplingFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAdaptiveThresholdFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAdaptiveThresholdFilter.h deleted file mode 120000 index 547be3d0..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAdaptiveThresholdFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageAdaptiveThresholdFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAddBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAddBlendFilter.h deleted file mode 120000 index c0020c2a..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAddBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageAddBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAlphaBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAlphaBlendFilter.h deleted file mode 120000 index 8d030c71..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAlphaBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageAlphaBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAmatorkaFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAmatorkaFilter.h deleted file mode 120000 index c357f5e3..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAmatorkaFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageAmatorkaFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAverageColor.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAverageColor.h deleted file mode 120000 index 702913cf..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAverageColor.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageAverageColor.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAverageLuminanceThresholdFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAverageLuminanceThresholdFilter.h deleted file mode 120000 index fabcf094..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageAverageLuminanceThresholdFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageAverageLuminanceThresholdFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageBilateralFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageBilateralFilter.h deleted file mode 120000 index 6498b00c..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageBilateralFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageBilateralFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageBoxBlurFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageBoxBlurFilter.h deleted file mode 120000 index 9a4d8f03..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageBoxBlurFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageBoxBlurFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageBrightnessFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageBrightnessFilter.h deleted file mode 120000 index 1b81b6a5..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageBrightnessFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageBrightnessFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageBuffer.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageBuffer.h deleted file mode 120000 index 220ce7f8..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageBuffer.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageBuffer.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageBulgeDistortionFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageBulgeDistortionFilter.h deleted file mode 120000 index ab666324..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageBulgeDistortionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageBulgeDistortionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageCGAColorspaceFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageCGAColorspaceFilter.h deleted file mode 120000 index 3086aeb5..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageCGAColorspaceFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageCGAColorspaceFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageCannyEdgeDetectionFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageCannyEdgeDetectionFilter.h deleted file mode 120000 index 39e89d57..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageCannyEdgeDetectionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageCannyEdgeDetectionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageChromaKeyBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageChromaKeyBlendFilter.h deleted file mode 120000 index cd3ea805..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageChromaKeyBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageChromaKeyBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageChromaKeyFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageChromaKeyFilter.h deleted file mode 120000 index bdecab2f..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageChromaKeyFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageChromaKeyFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageClosingFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageClosingFilter.h deleted file mode 120000 index 5b163840..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageClosingFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageClosingFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorBlendFilter.h deleted file mode 120000 index f72172b7..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageColorBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorBurnBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorBurnBlendFilter.h deleted file mode 120000 index a45ffd4b..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorBurnBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageColorBurnBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorDodgeBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorDodgeBlendFilter.h deleted file mode 120000 index 10e12cb6..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorDodgeBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageColorDodgeBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorInvertFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorInvertFilter.h deleted file mode 120000 index 6961f69a..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorInvertFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageColorInvertFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorMatrixFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorMatrixFilter.h deleted file mode 120000 index 4e8d4d59..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorMatrixFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageColorMatrixFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorPackingFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorPackingFilter.h deleted file mode 120000 index b6ce55c9..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageColorPackingFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageColorPackingFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageContext.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageContext.h deleted file mode 120000 index 40791f1b..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageContext.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/iOS/GPUImageContext.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageContrastFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageContrastFilter.h deleted file mode 120000 index 22057498..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageContrastFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageContrastFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageCropFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageCropFilter.h deleted file mode 120000 index d136ed77..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageCropFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageCropFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageCrosshairGenerator.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageCrosshairGenerator.h deleted file mode 120000 index 2112ba21..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageCrosshairGenerator.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageCrosshairGenerator.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageCrosshatchFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageCrosshatchFilter.h deleted file mode 120000 index 7706d91d..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageCrosshatchFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageCrosshatchFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDarkenBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDarkenBlendFilter.h deleted file mode 120000 index 8fdf8cd5..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDarkenBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageDarkenBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDifferenceBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDifferenceBlendFilter.h deleted file mode 120000 index 6a41b879..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDifferenceBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageDifferenceBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDilationFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDilationFilter.h deleted file mode 120000 index 1b82a7a7..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDilationFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageDilationFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDirectionalNonMaximumSuppressionFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDirectionalNonMaximumSuppressionFilter.h deleted file mode 120000 index c5820fac..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDirectionalNonMaximumSuppressionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageDirectionalNonMaximumSuppressionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDirectionalSobelEdgeDetectionFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDirectionalSobelEdgeDetectionFilter.h deleted file mode 120000 index ebc6b5b8..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDirectionalSobelEdgeDetectionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageDirectionalSobelEdgeDetectionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDissolveBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDissolveBlendFilter.h deleted file mode 120000 index c40a8147..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDissolveBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageDissolveBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDivideBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDivideBlendFilter.h deleted file mode 120000 index e21f3007..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageDivideBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageDivideBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageEmbossFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageEmbossFilter.h deleted file mode 120000 index 93a8ac2d..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageEmbossFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageEmbossFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageErosionFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageErosionFilter.h deleted file mode 120000 index 66c4b920..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageErosionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageErosionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageExclusionBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageExclusionBlendFilter.h deleted file mode 120000 index ee6a437c..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageExclusionBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageExclusionBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageExposureFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageExposureFilter.h deleted file mode 120000 index cb3ec5ed..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageExposureFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageExposureFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFASTCornerDetectionFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFASTCornerDetectionFilter.h deleted file mode 120000 index 6f73c3e1..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFASTCornerDetectionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageFASTCornerDetectionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFalseColorFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFalseColorFilter.h deleted file mode 120000 index 161cc44b..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFalseColorFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageFalseColorFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFilter.h deleted file mode 120000 index c7036945..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFilterGroup.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFilterGroup.h deleted file mode 120000 index c15625a3..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFilterGroup.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageFilterGroup.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFilterPipeline.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFilterPipeline.h deleted file mode 120000 index e3d54cd2..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFilterPipeline.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageFilterPipeline.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFramebuffer.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFramebuffer.h deleted file mode 120000 index 912489a3..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFramebuffer.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageFramebuffer.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFramebufferCache.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFramebufferCache.h deleted file mode 120000 index 14e95530..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFramebufferCache.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageFramebufferCache.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFramework.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFramework.h deleted file mode 120000 index ade56d4a..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageFramework.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/iOS/Framework/GPUImageFramework.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGammaFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGammaFilter.h deleted file mode 120000 index 127ab2c7..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGammaFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageGammaFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGaussianBlurFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGaussianBlurFilter.h deleted file mode 120000 index 2a9ecae7..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGaussianBlurFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageGaussianBlurFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGaussianBlurPositionFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGaussianBlurPositionFilter.h deleted file mode 120000 index 423c806f..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGaussianBlurPositionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageGaussianBlurPositionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGaussianSelectiveBlurFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGaussianSelectiveBlurFilter.h deleted file mode 120000 index 6d410149..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGaussianSelectiveBlurFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageGaussianSelectiveBlurFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGlassSphereFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGlassSphereFilter.h deleted file mode 120000 index e01a6f51..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGlassSphereFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageGlassSphereFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGrayscaleFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGrayscaleFilter.h deleted file mode 120000 index 8332833f..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageGrayscaleFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageGrayscaleFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHSBFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHSBFilter.h deleted file mode 120000 index df50e698..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHSBFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHSBFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHalftoneFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHalftoneFilter.h deleted file mode 120000 index f6151b4d..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHalftoneFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHalftoneFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHardLightBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHardLightBlendFilter.h deleted file mode 120000 index e857cd30..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHardLightBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHardLightBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHarrisCornerDetectionFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHarrisCornerDetectionFilter.h deleted file mode 120000 index cf78593f..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHarrisCornerDetectionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHarrisCornerDetectionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHazeFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHazeFilter.h deleted file mode 120000 index 5b2806e7..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHazeFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHazeFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHighPassFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHighPassFilter.h deleted file mode 120000 index f5063f14..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHighPassFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHighPassFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHighlightShadowFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHighlightShadowFilter.h deleted file mode 120000 index 33329bd5..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHighlightShadowFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHighlightShadowFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHistogramEqualizationFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHistogramEqualizationFilter.h deleted file mode 120000 index 8a2721b7..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHistogramEqualizationFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHistogramEqualizationFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHistogramFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHistogramFilter.h deleted file mode 120000 index b2f97670..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHistogramFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHistogramFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHistogramGenerator.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHistogramGenerator.h deleted file mode 120000 index 03c93a15..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHistogramGenerator.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHistogramGenerator.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHoughTransformLineDetector.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHoughTransformLineDetector.h deleted file mode 120000 index 2d5da6af..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHoughTransformLineDetector.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHoughTransformLineDetector.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHueBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHueBlendFilter.h deleted file mode 120000 index 97d05aaf..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHueBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHueBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHueFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHueFilter.h deleted file mode 120000 index 62c976c1..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageHueFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageHueFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageJFAVoronoiFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageJFAVoronoiFilter.h deleted file mode 120000 index f02faeb4..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageJFAVoronoiFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageJFAVoronoiFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageKuwaharaFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageKuwaharaFilter.h deleted file mode 120000 index e64abda0..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageKuwaharaFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageKuwaharaFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageKuwaharaRadius3Filter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageKuwaharaRadius3Filter.h deleted file mode 120000 index 3e2aec8c..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageKuwaharaRadius3Filter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageKuwaharaRadius3Filter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLanczosResamplingFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLanczosResamplingFilter.h deleted file mode 120000 index b036cbba..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLanczosResamplingFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLanczosResamplingFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLaplacianFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLaplacianFilter.h deleted file mode 120000 index d663c479..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLaplacianFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLaplacianFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLevelsFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLevelsFilter.h deleted file mode 120000 index 2d92e6bc..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLevelsFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLevelsFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLightenBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLightenBlendFilter.h deleted file mode 120000 index 425d16c0..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLightenBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLightenBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLineGenerator.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLineGenerator.h deleted file mode 120000 index 5a999110..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLineGenerator.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLineGenerator.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLinearBurnBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLinearBurnBlendFilter.h deleted file mode 120000 index f471fdb9..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLinearBurnBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLinearBurnBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLocalBinaryPatternFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLocalBinaryPatternFilter.h deleted file mode 120000 index 93395da8..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLocalBinaryPatternFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLocalBinaryPatternFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLookupFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLookupFilter.h deleted file mode 120000 index 0ea51d79..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLookupFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLookupFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLowPassFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLowPassFilter.h deleted file mode 120000 index 59aca2a8..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLowPassFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLowPassFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLuminanceRangeFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLuminanceRangeFilter.h deleted file mode 120000 index 9855a2a7..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLuminanceRangeFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLuminanceRangeFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLuminanceThresholdFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLuminanceThresholdFilter.h deleted file mode 120000 index 0b1478af..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLuminanceThresholdFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLuminanceThresholdFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLuminosity.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLuminosity.h deleted file mode 120000 index c20086fa..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLuminosity.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLuminosity.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLuminosityBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLuminosityBlendFilter.h deleted file mode 120000 index 19ef8578..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageLuminosityBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageLuminosityBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMaskFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMaskFilter.h deleted file mode 120000 index 29e6989a..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMaskFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageMaskFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMedianFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMedianFilter.h deleted file mode 120000 index 7e68c25d..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMedianFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageMedianFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMissEtikateFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMissEtikateFilter.h deleted file mode 120000 index a0afc5ba..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMissEtikateFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageMissEtikateFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMonochromeFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMonochromeFilter.h deleted file mode 120000 index 8c4201d7..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMonochromeFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageMonochromeFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMosaicFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMosaicFilter.h deleted file mode 120000 index 8f8a3285..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMosaicFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageMosaicFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMotionBlurFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMotionBlurFilter.h deleted file mode 120000 index f2e2b8e0..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMotionBlurFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageMotionBlurFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMotionDetector.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMotionDetector.h deleted file mode 120000 index 8c5b0e10..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMotionDetector.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageMotionDetector.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMovie.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMovie.h deleted file mode 120000 index 4d6e8798..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMovie.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageMovie.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMovieComposition.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMovieComposition.h deleted file mode 120000 index 93598144..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMovieComposition.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageMovieComposition.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMovieWriter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMovieWriter.h deleted file mode 120000 index 0981109d..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMovieWriter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/iOS/GPUImageMovieWriter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMultiplyBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMultiplyBlendFilter.h deleted file mode 120000 index 0b39ea10..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageMultiplyBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageMultiplyBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageNobleCornerDetectionFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageNobleCornerDetectionFilter.h deleted file mode 120000 index e4ea4995..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageNobleCornerDetectionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageNobleCornerDetectionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageNonMaximumSuppressionFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageNonMaximumSuppressionFilter.h deleted file mode 120000 index b5f7957a..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageNonMaximumSuppressionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageNonMaximumSuppressionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageNormalBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageNormalBlendFilter.h deleted file mode 120000 index 5d0b343b..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageNormalBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageNormalBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageOpacityFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageOpacityFilter.h deleted file mode 120000 index 1bcca485..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageOpacityFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageOpacityFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageOpeningFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageOpeningFilter.h deleted file mode 120000 index b68bb068..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageOpeningFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageOpeningFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageOutput.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageOutput.h deleted file mode 120000 index dcb6fab8..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageOutput.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageOutput.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageOverlayBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageOverlayBlendFilter.h deleted file mode 120000 index 34b88fbe..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageOverlayBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageOverlayBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageParallelCoordinateLineTransformFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageParallelCoordinateLineTransformFilter.h deleted file mode 120000 index 8f0d06f6..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageParallelCoordinateLineTransformFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageParallelCoordinateLineTransformFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePerlinNoiseFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePerlinNoiseFilter.h deleted file mode 120000 index 00c2bfe7..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePerlinNoiseFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImagePerlinNoiseFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePicture+TextureSubimage.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePicture+TextureSubimage.h deleted file mode 120000 index 97e13907..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePicture+TextureSubimage.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/iOS/GPUImagePicture+TextureSubimage.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePicture.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePicture.h deleted file mode 120000 index 9999ee88..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePicture.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/iOS/GPUImagePicture.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePinchDistortionFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePinchDistortionFilter.h deleted file mode 120000 index 561065be..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePinchDistortionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImagePinchDistortionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePixellateFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePixellateFilter.h deleted file mode 120000 index 65d5092c..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePixellateFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImagePixellateFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePixellatePositionFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePixellatePositionFilter.h deleted file mode 120000 index 06e3b7e2..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePixellatePositionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImagePixellatePositionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePoissonBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePoissonBlendFilter.h deleted file mode 120000 index c852272e..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePoissonBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImagePoissonBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePolarPixellateFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePolarPixellateFilter.h deleted file mode 120000 index 752176da..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePolarPixellateFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImagePolarPixellateFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePolkaDotFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePolkaDotFilter.h deleted file mode 120000 index dba6db1a..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePolkaDotFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImagePolkaDotFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePosterizeFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePosterizeFilter.h deleted file mode 120000 index 215ea1b0..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePosterizeFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImagePosterizeFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePrewittEdgeDetectionFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePrewittEdgeDetectionFilter.h deleted file mode 120000 index c620cdef..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImagePrewittEdgeDetectionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImagePrewittEdgeDetectionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRGBClosingFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRGBClosingFilter.h deleted file mode 120000 index e958b6df..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRGBClosingFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageRGBClosingFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRGBDilationFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRGBDilationFilter.h deleted file mode 120000 index 406dea33..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRGBDilationFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageRGBDilationFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRGBErosionFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRGBErosionFilter.h deleted file mode 120000 index b0bea951..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRGBErosionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageRGBErosionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRGBFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRGBFilter.h deleted file mode 120000 index 64f0f29e..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRGBFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageRGBFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRGBOpeningFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRGBOpeningFilter.h deleted file mode 120000 index b08322df..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRGBOpeningFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageRGBOpeningFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRawDataInput.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRawDataInput.h deleted file mode 120000 index 3ac18170..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRawDataInput.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageRawDataInput.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRawDataOutput.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRawDataOutput.h deleted file mode 120000 index a08dd75e..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageRawDataOutput.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageRawDataOutput.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSaturationBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSaturationBlendFilter.h deleted file mode 120000 index 128968a3..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSaturationBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSaturationBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSaturationFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSaturationFilter.h deleted file mode 120000 index 9b56c3c2..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSaturationFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSaturationFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageScreenBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageScreenBlendFilter.h deleted file mode 120000 index c09274d9..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageScreenBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageScreenBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSepiaFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSepiaFilter.h deleted file mode 120000 index 6af3120c..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSepiaFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSepiaFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSharpenFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSharpenFilter.h deleted file mode 120000 index a736679d..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSharpenFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSharpenFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageShiTomasiFeatureDetectionFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageShiTomasiFeatureDetectionFilter.h deleted file mode 120000 index 6bfa8c58..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageShiTomasiFeatureDetectionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageShiTomasiFeatureDetectionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSingleComponentGaussianBlurFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSingleComponentGaussianBlurFilter.h deleted file mode 120000 index dd642505..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSingleComponentGaussianBlurFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSingleComponentGaussianBlurFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSketchFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSketchFilter.h deleted file mode 120000 index 9aafd154..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSketchFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSketchFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSmoothToonFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSmoothToonFilter.h deleted file mode 120000 index 8091466f..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSmoothToonFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSmoothToonFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSobelEdgeDetectionFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSobelEdgeDetectionFilter.h deleted file mode 120000 index 019a83d0..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSobelEdgeDetectionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSobelEdgeDetectionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSoftEleganceFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSoftEleganceFilter.h deleted file mode 120000 index ae0fe89b..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSoftEleganceFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSoftEleganceFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSoftLightBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSoftLightBlendFilter.h deleted file mode 120000 index ec5c1881..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSoftLightBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSoftLightBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSolidColorGenerator.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSolidColorGenerator.h deleted file mode 120000 index 4eb09f85..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSolidColorGenerator.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSolidColorGenerator.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSourceOverBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSourceOverBlendFilter.h deleted file mode 120000 index 50dee17d..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSourceOverBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSourceOverBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSphereRefractionFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSphereRefractionFilter.h deleted file mode 120000 index 9ebdd7cb..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSphereRefractionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSphereRefractionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageStillCamera.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageStillCamera.h deleted file mode 120000 index 52fd54f6..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageStillCamera.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageStillCamera.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageStretchDistortionFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageStretchDistortionFilter.h deleted file mode 120000 index 261fca3d..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageStretchDistortionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageStretchDistortionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSubtractBlendFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSubtractBlendFilter.h deleted file mode 120000 index dfc7cb0a..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSubtractBlendFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSubtractBlendFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSwirlFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSwirlFilter.h deleted file mode 120000 index 84091382..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageSwirlFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageSwirlFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTextureInput.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTextureInput.h deleted file mode 120000 index da1350a4..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTextureInput.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageTextureInput.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTextureOutput.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTextureOutput.h deleted file mode 120000 index da55e4dc..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTextureOutput.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageTextureOutput.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageThreeInputFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageThreeInputFilter.h deleted file mode 120000 index c3a2659a..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageThreeInputFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageThreeInputFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageThresholdEdgeDetectionFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageThresholdEdgeDetectionFilter.h deleted file mode 120000 index 69d9d2cd..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageThresholdEdgeDetectionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageThresholdEdgeDetectionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageThresholdSketchFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageThresholdSketchFilter.h deleted file mode 120000 index eb97d3b4..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageThresholdSketchFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageThresholdSketchFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageThresholdedNonMaximumSuppressionFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageThresholdedNonMaximumSuppressionFilter.h deleted file mode 120000 index 7ccd2357..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageThresholdedNonMaximumSuppressionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageThresholdedNonMaximumSuppressionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTiltShiftFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTiltShiftFilter.h deleted file mode 120000 index 939825c6..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTiltShiftFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageTiltShiftFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageToneCurveFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageToneCurveFilter.h deleted file mode 120000 index 74c0912c..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageToneCurveFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageToneCurveFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageToonFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageToonFilter.h deleted file mode 120000 index 19aca502..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageToonFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageToonFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTransformFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTransformFilter.h deleted file mode 120000 index 647b8d5c..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTransformFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageTransformFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTwoInputCrossTextureSamplingFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTwoInputCrossTextureSamplingFilter.h deleted file mode 120000 index 37e25218..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTwoInputCrossTextureSamplingFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageTwoInputCrossTextureSamplingFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTwoInputFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTwoInputFilter.h deleted file mode 120000 index c5d5ae16..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTwoInputFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageTwoInputFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTwoPassFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTwoPassFilter.h deleted file mode 120000 index 9ee4bf0b..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTwoPassFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageTwoPassFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTwoPassTextureSamplingFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTwoPassTextureSamplingFilter.h deleted file mode 120000 index 0bd37757..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageTwoPassTextureSamplingFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageTwoPassTextureSamplingFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageUIElement.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageUIElement.h deleted file mode 120000 index cccc6850..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageUIElement.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageUIElement.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageUnsharpMaskFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageUnsharpMaskFilter.h deleted file mode 120000 index 0d612ecd..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageUnsharpMaskFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageUnsharpMaskFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageVideoCamera.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageVideoCamera.h deleted file mode 120000 index e5a2daf8..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageVideoCamera.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageVideoCamera.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageView.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageView.h deleted file mode 120000 index 47efed92..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageView.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/iOS/GPUImageView.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageVignetteFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageVignetteFilter.h deleted file mode 120000 index 82aeec2b..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageVignetteFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageVignetteFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageVoronoiConsumerFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageVoronoiConsumerFilter.h deleted file mode 120000 index 31810f65..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageVoronoiConsumerFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageVoronoiConsumerFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageWeakPixelInclusionFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageWeakPixelInclusionFilter.h deleted file mode 120000 index 851aebf2..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageWeakPixelInclusionFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageWeakPixelInclusionFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageWhiteBalanceFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageWhiteBalanceFilter.h deleted file mode 120000 index d2318ca5..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageWhiteBalanceFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageWhiteBalanceFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageXYDerivativeFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageXYDerivativeFilter.h deleted file mode 120000 index d6024a32..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageXYDerivativeFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageXYDerivativeFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageZoomBlurFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageZoomBlurFilter.h deleted file mode 120000 index 67da1204..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageZoomBlurFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageZoomBlurFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageiOSBlurFilter.h b/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageiOSBlurFilter.h deleted file mode 120000 index 2bf9dc16..00000000 --- a/iOS_Tips/Pods/Headers/Public/GPUImage/GPUImageiOSBlurFilter.h +++ /dev/null @@ -1 +0,0 @@ -../../../GPUImage/framework/Source/GPUImageiOSBlurFilter.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/MBProgressHUD/MBProgressHUD.h b/iOS_Tips/Pods/Headers/Public/MBProgressHUD/MBProgressHUD.h deleted file mode 120000 index 19ed4db7..00000000 --- a/iOS_Tips/Pods/Headers/Public/MBProgressHUD/MBProgressHUD.h +++ /dev/null @@ -1 +0,0 @@ -../../../MBProgressHUD/MBProgressHUD.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/MLeaksFinder/MLeaksFinder.h b/iOS_Tips/Pods/Headers/Public/MLeaksFinder/MLeaksFinder.h deleted file mode 120000 index 0cf746ab..00000000 --- a/iOS_Tips/Pods/Headers/Public/MLeaksFinder/MLeaksFinder.h +++ /dev/null @@ -1 +0,0 @@ -../../../MLeaksFinder/MLeaksFinder/MLeaksFinder.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/MLeaksFinder/NSObject+MemoryLeak.h b/iOS_Tips/Pods/Headers/Public/MLeaksFinder/NSObject+MemoryLeak.h deleted file mode 120000 index 7343f141..00000000 --- a/iOS_Tips/Pods/Headers/Public/MLeaksFinder/NSObject+MemoryLeak.h +++ /dev/null @@ -1 +0,0 @@ -../../../MLeaksFinder/MLeaksFinder/NSObject+MemoryLeak.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/Masonry/MASCompositeConstraint.h b/iOS_Tips/Pods/Headers/Public/Masonry/MASCompositeConstraint.h deleted file mode 120000 index b1b34103..00000000 --- a/iOS_Tips/Pods/Headers/Public/Masonry/MASCompositeConstraint.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/MASCompositeConstraint.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/Masonry/MASConstraint+Private.h b/iOS_Tips/Pods/Headers/Public/Masonry/MASConstraint+Private.h deleted file mode 120000 index ed9aa9f3..00000000 --- a/iOS_Tips/Pods/Headers/Public/Masonry/MASConstraint+Private.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/MASConstraint+Private.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/Masonry/MASConstraint.h b/iOS_Tips/Pods/Headers/Public/Masonry/MASConstraint.h deleted file mode 120000 index 76e9e73d..00000000 --- a/iOS_Tips/Pods/Headers/Public/Masonry/MASConstraint.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/MASConstraint.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/Masonry/MASConstraintMaker.h b/iOS_Tips/Pods/Headers/Public/Masonry/MASConstraintMaker.h deleted file mode 120000 index b6d6027b..00000000 --- a/iOS_Tips/Pods/Headers/Public/Masonry/MASConstraintMaker.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/MASConstraintMaker.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/Masonry/MASLayoutConstraint.h b/iOS_Tips/Pods/Headers/Public/Masonry/MASLayoutConstraint.h deleted file mode 120000 index 73e87968..00000000 --- a/iOS_Tips/Pods/Headers/Public/Masonry/MASLayoutConstraint.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/MASLayoutConstraint.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/Masonry/MASUtilities.h b/iOS_Tips/Pods/Headers/Public/Masonry/MASUtilities.h deleted file mode 120000 index aae5e32b..00000000 --- a/iOS_Tips/Pods/Headers/Public/Masonry/MASUtilities.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/MASUtilities.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/Masonry/MASViewAttribute.h b/iOS_Tips/Pods/Headers/Public/Masonry/MASViewAttribute.h deleted file mode 120000 index 5399f642..00000000 --- a/iOS_Tips/Pods/Headers/Public/Masonry/MASViewAttribute.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/MASViewAttribute.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/Masonry/MASViewConstraint.h b/iOS_Tips/Pods/Headers/Public/Masonry/MASViewConstraint.h deleted file mode 120000 index 382c4194..00000000 --- a/iOS_Tips/Pods/Headers/Public/Masonry/MASViewConstraint.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/MASViewConstraint.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/Masonry/Masonry.h b/iOS_Tips/Pods/Headers/Public/Masonry/Masonry.h deleted file mode 120000 index f5093032..00000000 --- a/iOS_Tips/Pods/Headers/Public/Masonry/Masonry.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/Masonry.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/Masonry/NSArray+MASAdditions.h b/iOS_Tips/Pods/Headers/Public/Masonry/NSArray+MASAdditions.h deleted file mode 120000 index db1d0ea7..00000000 --- a/iOS_Tips/Pods/Headers/Public/Masonry/NSArray+MASAdditions.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/NSArray+MASAdditions.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/Masonry/NSArray+MASShorthandAdditions.h b/iOS_Tips/Pods/Headers/Public/Masonry/NSArray+MASShorthandAdditions.h deleted file mode 120000 index 2169edc5..00000000 --- a/iOS_Tips/Pods/Headers/Public/Masonry/NSArray+MASShorthandAdditions.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/NSArray+MASShorthandAdditions.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/Masonry/NSLayoutConstraint+MASDebugAdditions.h b/iOS_Tips/Pods/Headers/Public/Masonry/NSLayoutConstraint+MASDebugAdditions.h deleted file mode 120000 index 72f59430..00000000 --- a/iOS_Tips/Pods/Headers/Public/Masonry/NSLayoutConstraint+MASDebugAdditions.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/NSLayoutConstraint+MASDebugAdditions.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/Masonry/View+MASAdditions.h b/iOS_Tips/Pods/Headers/Public/Masonry/View+MASAdditions.h deleted file mode 120000 index 9060451a..00000000 --- a/iOS_Tips/Pods/Headers/Public/Masonry/View+MASAdditions.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/View+MASAdditions.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/Masonry/View+MASShorthandAdditions.h b/iOS_Tips/Pods/Headers/Public/Masonry/View+MASShorthandAdditions.h deleted file mode 120000 index 91ef93fa..00000000 --- a/iOS_Tips/Pods/Headers/Public/Masonry/View+MASShorthandAdditions.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/View+MASShorthandAdditions.h \ No newline at end of file diff --git a/iOS_Tips/Pods/Headers/Public/Masonry/ViewController+MASAdditions.h b/iOS_Tips/Pods/Headers/Public/Masonry/ViewController+MASAdditions.h deleted file mode 120000 index 12320e3f..00000000 --- a/iOS_Tips/Pods/Headers/Public/Masonry/ViewController+MASAdditions.h +++ /dev/null @@ -1 +0,0 @@ -../../../Masonry/Masonry/ViewController+MASAdditions.h \ No newline at end of file diff --git a/iOS_Tips/Pods/MBProgressHUD/LICENSE b/iOS_Tips/Pods/MBProgressHUD/LICENSE deleted file mode 100644 index 1c0d59bb..00000000 --- a/iOS_Tips/Pods/MBProgressHUD/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright © 2009-2016 Matej Bukovinski - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file diff --git a/iOS_Tips/Pods/MBProgressHUD/MBProgressHUD.h b/iOS_Tips/Pods/MBProgressHUD/MBProgressHUD.h deleted file mode 100644 index a7b54ee9..00000000 --- a/iOS_Tips/Pods/MBProgressHUD/MBProgressHUD.h +++ /dev/null @@ -1,443 +0,0 @@ -// -// MBProgressHUD.h -// Version 1.1.0 -// Created by Matej Bukovinski on 2.4.09. -// - -// This code is distributed under the terms and conditions of the MIT license. - -// Copyright © 2009-2016 Matej Bukovinski -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#import -#import -#import - -@class MBBackgroundView; -@protocol MBProgressHUDDelegate; - - -extern CGFloat const MBProgressMaxOffset; - -typedef NS_ENUM(NSInteger, MBProgressHUDMode) { - /// UIActivityIndicatorView. - MBProgressHUDModeIndeterminate, - /// A round, pie-chart like, progress view. - MBProgressHUDModeDeterminate, - /// Horizontal progress bar. - MBProgressHUDModeDeterminateHorizontalBar, - /// Ring-shaped progress view. - MBProgressHUDModeAnnularDeterminate, - /// Shows a custom view. - MBProgressHUDModeCustomView, - /// Shows only labels. - MBProgressHUDModeText -}; - -typedef NS_ENUM(NSInteger, MBProgressHUDAnimation) { - /// Opacity animation - MBProgressHUDAnimationFade, - /// Opacity + scale animation (zoom in when appearing zoom out when disappearing) - MBProgressHUDAnimationZoom, - /// Opacity + scale animation (zoom out style) - MBProgressHUDAnimationZoomOut, - /// Opacity + scale animation (zoom in style) - MBProgressHUDAnimationZoomIn -}; - -typedef NS_ENUM(NSInteger, MBProgressHUDBackgroundStyle) { - /// Solid color background - MBProgressHUDBackgroundStyleSolidColor, - /// UIVisualEffectView or UIToolbar.layer background view - MBProgressHUDBackgroundStyleBlur -}; - -typedef void (^MBProgressHUDCompletionBlock)(void); - - -NS_ASSUME_NONNULL_BEGIN - - -/** - * Displays a simple HUD window containing a progress indicator and two optional labels for short messages. - * - * This is a simple drop-in class for displaying a progress HUD view similar to Apple's private UIProgressHUD class. - * The MBProgressHUD window spans over the entire space given to it by the initWithFrame: constructor and catches all - * user input on this region, thereby preventing the user operations on components below the view. - * - * @note To still allow touches to pass through the HUD, you can set hud.userInteractionEnabled = NO. - * @attention MBProgressHUD is a UI class and should therefore only be accessed on the main thread. - */ -@interface MBProgressHUD : UIView - -/** - * Creates a new HUD, adds it to provided view and shows it. The counterpart to this method is hideHUDForView:animated:. - * - * @note This method sets removeFromSuperViewOnHide. The HUD will automatically be removed from the view hierarchy when hidden. - * - * @param view The view that the HUD will be added to - * @param animated If set to YES the HUD will appear using the current animationType. If set to NO the HUD will not use - * animations while appearing. - * @return A reference to the created HUD. - * - * @see hideHUDForView:animated: - * @see animationType - */ -+ (instancetype)showHUDAddedTo:(UIView *)view animated:(BOOL)animated; - -/// @name Showing and hiding - -/** - * Finds the top-most HUD subview that hasn't finished and hides it. The counterpart to this method is showHUDAddedTo:animated:. - * - * @note This method sets removeFromSuperViewOnHide. The HUD will automatically be removed from the view hierarchy when hidden. - * - * @param view The view that is going to be searched for a HUD subview. - * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use - * animations while disappearing. - * @return YES if a HUD was found and removed, NO otherwise. - * - * @see showHUDAddedTo:animated: - * @see animationType - */ -+ (BOOL)hideHUDForView:(UIView *)view animated:(BOOL)animated; - -/** - * Finds the top-most HUD subview that hasn't finished and returns it. - * - * @param view The view that is going to be searched. - * @return A reference to the last HUD subview discovered. - */ -+ (nullable MBProgressHUD *)HUDForView:(UIView *)view; - -/** - * A convenience constructor that initializes the HUD with the view's bounds. Calls the designated constructor with - * view.bounds as the parameter. - * - * @param view The view instance that will provide the bounds for the HUD. Should be the same instance as - * the HUD's superview (i.e., the view that the HUD will be added to). - */ -- (instancetype)initWithView:(UIView *)view; - -/** - * Displays the HUD. - * - * @note You need to make sure that the main thread completes its run loop soon after this method call so that - * the user interface can be updated. Call this method when your task is already set up to be executed in a new thread - * (e.g., when using something like NSOperation or making an asynchronous call like NSURLRequest). - * - * @param animated If set to YES the HUD will appear using the current animationType. If set to NO the HUD will not use - * animations while appearing. - * - * @see animationType - */ -- (void)showAnimated:(BOOL)animated; - -/** - * Hides the HUD. This still calls the hudWasHidden: delegate. This is the counterpart of the show: method. Use it to - * hide the HUD when your task completes. - * - * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use - * animations while disappearing. - * - * @see animationType - */ -- (void)hideAnimated:(BOOL)animated; - -/** - * Hides the HUD after a delay. This still calls the hudWasHidden: delegate. This is the counterpart of the show: method. Use it to - * hide the HUD when your task completes. - * - * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use - * animations while disappearing. - * @param delay Delay in seconds until the HUD is hidden. - * - * @see animationType - */ -- (void)hideAnimated:(BOOL)animated afterDelay:(NSTimeInterval)delay; - -/** - * The HUD delegate object. Receives HUD state notifications. - */ -@property (weak, nonatomic) id delegate; - -/** - * Called after the HUD is hiden. - */ -@property (copy, nullable) MBProgressHUDCompletionBlock completionBlock; - -/* - * Grace period is the time (in seconds) that the invoked method may be run without - * showing the HUD. If the task finishes before the grace time runs out, the HUD will - * not be shown at all. - * This may be used to prevent HUD display for very short tasks. - * Defaults to 0 (no grace time). - */ -@property (assign, nonatomic) NSTimeInterval graceTime; - -/** - * The minimum time (in seconds) that the HUD is shown. - * This avoids the problem of the HUD being shown and than instantly hidden. - * Defaults to 0 (no minimum show time). - */ -@property (assign, nonatomic) NSTimeInterval minShowTime; - -/** - * Removes the HUD from its parent view when hidden. - * Defaults to NO. - */ -@property (assign, nonatomic) BOOL removeFromSuperViewOnHide; - -/// @name Appearance - -/** - * MBProgressHUD operation mode. The default is MBProgressHUDModeIndeterminate. - */ -@property (assign, nonatomic) MBProgressHUDMode mode; - -/** - * A color that gets forwarded to all labels and supported indicators. Also sets the tintColor - * for custom views on iOS 7+. Set to nil to manage color individually. - * Defaults to semi-translucent black on iOS 7 and later and white on earlier iOS versions. - */ -@property (strong, nonatomic, nullable) UIColor *contentColor UI_APPEARANCE_SELECTOR; - -/** - * The animation type that should be used when the HUD is shown and hidden. - */ -@property (assign, nonatomic) MBProgressHUDAnimation animationType UI_APPEARANCE_SELECTOR; - -/** - * The bezel offset relative to the center of the view. You can use MBProgressMaxOffset - * and -MBProgressMaxOffset to move the HUD all the way to the screen edge in each direction. - * E.g., CGPointMake(0.f, MBProgressMaxOffset) would position the HUD centered on the bottom edge. - */ -@property (assign, nonatomic) CGPoint offset UI_APPEARANCE_SELECTOR; - -/** - * The amount of space between the HUD edge and the HUD elements (labels, indicators or custom views). - * This also represents the minimum bezel distance to the edge of the HUD view. - * Defaults to 20.f - */ -@property (assign, nonatomic) CGFloat margin UI_APPEARANCE_SELECTOR; - -/** - * The minimum size of the HUD bezel. Defaults to CGSizeZero (no minimum size). - */ -@property (assign, nonatomic) CGSize minSize UI_APPEARANCE_SELECTOR; - -/** - * Force the HUD dimensions to be equal if possible. - */ -@property (assign, nonatomic, getter = isSquare) BOOL square UI_APPEARANCE_SELECTOR; - -/** - * When enabled, the bezel center gets slightly affected by the device accelerometer data. - * Has no effect on iOS < 7.0. Defaults to YES. - */ -@property (assign, nonatomic, getter=areDefaultMotionEffectsEnabled) BOOL defaultMotionEffectsEnabled UI_APPEARANCE_SELECTOR; - -/// @name Progress - -/** - * The progress of the progress indicator, from 0.0 to 1.0. Defaults to 0.0. - */ -@property (assign, nonatomic) float progress; - -/// @name ProgressObject - -/** - * The NSProgress object feeding the progress information to the progress indicator. - */ -@property (strong, nonatomic, nullable) NSProgress *progressObject; - -/// @name Views - -/** - * The view containing the labels and indicator (or customView). - */ -@property (strong, nonatomic, readonly) MBBackgroundView *bezelView; - -/** - * View covering the entire HUD area, placed behind bezelView. - */ -@property (strong, nonatomic, readonly) MBBackgroundView *backgroundView; - -/** - * The UIView (e.g., a UIImageView) to be shown when the HUD is in MBProgressHUDModeCustomView. - * The view should implement intrinsicContentSize for proper sizing. For best results use approximately 37 by 37 pixels. - */ -@property (strong, nonatomic, nullable) UIView *customView; - -/** - * A label that holds an optional short message to be displayed below the activity indicator. The HUD is automatically resized to fit - * the entire text. - */ -@property (strong, nonatomic, readonly) UILabel *label; - -/** - * A label that holds an optional details message displayed below the labelText message. The details text can span multiple lines. - */ -@property (strong, nonatomic, readonly) UILabel *detailsLabel; - -/** - * A button that is placed below the labels. Visible only if a target / action is added. - */ -@property (strong, nonatomic, readonly) UIButton *button; - -@end - - -@protocol MBProgressHUDDelegate - -@optional - -/** - * Called after the HUD was fully hidden from the screen. - */ -- (void)hudWasHidden:(MBProgressHUD *)hud; - -@end - - -/** - * A progress view for showing definite progress by filling up a circle (pie chart). - */ -@interface MBRoundProgressView : UIView - -/** - * Progress (0.0 to 1.0) - */ -@property (nonatomic, assign) float progress; - -/** - * Indicator progress color. - * Defaults to white [UIColor whiteColor]. - */ -@property (nonatomic, strong) UIColor *progressTintColor; - -/** - * Indicator background (non-progress) color. - * Only applicable on iOS versions older than iOS 7. - * Defaults to translucent white (alpha 0.1). - */ -@property (nonatomic, strong) UIColor *backgroundTintColor; - -/* - * Display mode - NO = round or YES = annular. Defaults to round. - */ -@property (nonatomic, assign, getter = isAnnular) BOOL annular; - -@end - - -/** - * A flat bar progress view. - */ -@interface MBBarProgressView : UIView - -/** - * Progress (0.0 to 1.0) - */ -@property (nonatomic, assign) float progress; - -/** - * Bar border line color. - * Defaults to white [UIColor whiteColor]. - */ -@property (nonatomic, strong) UIColor *lineColor; - -/** - * Bar background color. - * Defaults to clear [UIColor clearColor]; - */ -@property (nonatomic, strong) UIColor *progressRemainingColor; - -/** - * Bar progress color. - * Defaults to white [UIColor whiteColor]. - */ -@property (nonatomic, strong) UIColor *progressColor; - -@end - - -@interface MBBackgroundView : UIView - -/** - * The background style. - * Defaults to MBProgressHUDBackgroundStyleBlur on iOS 7 or later and MBProgressHUDBackgroundStyleSolidColor otherwise. - * @note Due to iOS 7 not supporting UIVisualEffectView, the blur effect differs slightly between iOS 7 and later versions. - */ -@property (nonatomic) MBProgressHUDBackgroundStyle style; - -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 || TARGET_OS_TV -/** - * The blur effect style, when using MBProgressHUDBackgroundStyleBlur. - * Defaults to UIBlurEffectStyleLight. - */ -@property (nonatomic) UIBlurEffectStyle blurEffectStyle; -#endif - -/** - * The background color or the blur tint color. - * @note Due to iOS 7 not supporting UIVisualEffectView, the blur effect differs slightly between iOS 7 and later versions. - */ -@property (nonatomic, strong) UIColor *color; - -@end - -@interface MBProgressHUD (Deprecated) - -+ (NSArray *)allHUDsForView:(UIView *)view __attribute__((deprecated("Store references when using more than one HUD per view."))); -+ (NSUInteger)hideAllHUDsForView:(UIView *)view animated:(BOOL)animated __attribute__((deprecated("Store references when using more than one HUD per view."))); - -- (id)initWithWindow:(UIWindow *)window __attribute__((deprecated("Use initWithView: instead."))); - -- (void)show:(BOOL)animated __attribute__((deprecated("Use showAnimated: instead."))); -- (void)hide:(BOOL)animated __attribute__((deprecated("Use hideAnimated: instead."))); -- (void)hide:(BOOL)animated afterDelay:(NSTimeInterval)delay __attribute__((deprecated("Use hideAnimated:afterDelay: instead."))); - -- (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated __attribute__((deprecated("Use GCD directly."))); -- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block __attribute__((deprecated("Use GCD directly."))); -- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block completionBlock:(nullable MBProgressHUDCompletionBlock)completion __attribute__((deprecated("Use GCD directly."))); -- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue __attribute__((deprecated("Use GCD directly."))); -- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue - completionBlock:(nullable MBProgressHUDCompletionBlock)completion __attribute__((deprecated("Use GCD directly."))); -@property (assign) BOOL taskInProgress __attribute__((deprecated("No longer needed."))); - -@property (nonatomic, copy) NSString *labelText __attribute__((deprecated("Use label.text instead."))); -@property (nonatomic, strong) UIFont *labelFont __attribute__((deprecated("Use label.font instead."))); -@property (nonatomic, strong) UIColor *labelColor __attribute__((deprecated("Use label.textColor instead."))); -@property (nonatomic, copy) NSString *detailsLabelText __attribute__((deprecated("Use detailsLabel.text instead."))); -@property (nonatomic, strong) UIFont *detailsLabelFont __attribute__((deprecated("Use detailsLabel.font instead."))); -@property (nonatomic, strong) UIColor *detailsLabelColor __attribute__((deprecated("Use detailsLabel.textColor instead."))); -@property (assign, nonatomic) CGFloat opacity __attribute__((deprecated("Customize bezelView properties instead."))); -@property (strong, nonatomic) UIColor *color __attribute__((deprecated("Customize the bezelView color instead."))); -@property (assign, nonatomic) CGFloat xOffset __attribute__((deprecated("Set offset.x instead."))); -@property (assign, nonatomic) CGFloat yOffset __attribute__((deprecated("Set offset.y instead."))); -@property (assign, nonatomic) CGFloat cornerRadius __attribute__((deprecated("Set bezelView.layer.cornerRadius instead."))); -@property (assign, nonatomic) BOOL dimBackground __attribute__((deprecated("Customize HUD background properties instead."))); -@property (strong, nonatomic) UIColor *activityIndicatorColor __attribute__((deprecated("Use UIAppearance to customize UIActivityIndicatorView. E.g.: [UIActivityIndicatorView appearanceWhenContainedIn:[MBProgressHUD class], nil].color = [UIColor redColor];"))); -@property (atomic, assign, readonly) CGSize size __attribute__((deprecated("Get the bezelView.frame.size instead."))); - -@end - -NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/Pods/MBProgressHUD/MBProgressHUD.m b/iOS_Tips/Pods/MBProgressHUD/MBProgressHUD.m deleted file mode 100644 index 1bcf9e99..00000000 --- a/iOS_Tips/Pods/MBProgressHUD/MBProgressHUD.m +++ /dev/null @@ -1,1495 +0,0 @@ -// -// MBProgressHUD.m -// Version 1.1.0 -// Created by Matej Bukovinski on 2.4.09. -// - -#import "MBProgressHUD.h" -#import - - -#ifndef kCFCoreFoundationVersionNumber_iOS_7_0 - #define kCFCoreFoundationVersionNumber_iOS_7_0 847.20 -#endif - -#ifndef kCFCoreFoundationVersionNumber_iOS_8_0 - #define kCFCoreFoundationVersionNumber_iOS_8_0 1129.15 -#endif - -#define MBMainThreadAssert() NSAssert([NSThread isMainThread], @"MBProgressHUD needs to be accessed on the main thread."); - -CGFloat const MBProgressMaxOffset = 1000000.f; - -static const CGFloat MBDefaultPadding = 4.f; -static const CGFloat MBDefaultLabelFontSize = 16.f; -static const CGFloat MBDefaultDetailsLabelFontSize = 12.f; - - -@interface MBProgressHUD () { - // Deprecated - UIColor *_activityIndicatorColor; - CGFloat _opacity; -} - -@property (nonatomic, assign) BOOL useAnimation; -@property (nonatomic, assign, getter=hasFinished) BOOL finished; -@property (nonatomic, strong) UIView *indicator; -@property (nonatomic, strong) NSDate *showStarted; -@property (nonatomic, strong) NSArray *paddingConstraints; -@property (nonatomic, strong) NSArray *bezelConstraints; -@property (nonatomic, strong) UIView *topSpacer; -@property (nonatomic, strong) UIView *bottomSpacer; -@property (nonatomic, weak) NSTimer *graceTimer; -@property (nonatomic, weak) NSTimer *minShowTimer; -@property (nonatomic, weak) NSTimer *hideDelayTimer; -@property (nonatomic, weak) CADisplayLink *progressObjectDisplayLink; - -// Deprecated -@property (assign) BOOL taskInProgress; - -@end - - -@interface MBProgressHUDRoundedButton : UIButton -@end - - -@implementation MBProgressHUD - -#pragma mark - Class methods - -+ (instancetype)showHUDAddedTo:(UIView *)view animated:(BOOL)animated { - MBProgressHUD *hud = [[self alloc] initWithView:view]; - hud.removeFromSuperViewOnHide = YES; - [view addSubview:hud]; - [hud showAnimated:animated]; - return hud; -} - -+ (BOOL)hideHUDForView:(UIView *)view animated:(BOOL)animated { - MBProgressHUD *hud = [self HUDForView:view]; - if (hud != nil) { - hud.removeFromSuperViewOnHide = YES; - [hud hideAnimated:animated]; - return YES; - } - return NO; -} - -+ (MBProgressHUD *)HUDForView:(UIView *)view { - NSEnumerator *subviewsEnum = [view.subviews reverseObjectEnumerator]; - for (UIView *subview in subviewsEnum) { - if ([subview isKindOfClass:self]) { - MBProgressHUD *hud = (MBProgressHUD *)subview; - if (hud.hasFinished == NO) { - return hud; - } - } - } - return nil; -} - -#pragma mark - Lifecycle - -- (void)commonInit { - // Set default values for properties - _animationType = MBProgressHUDAnimationFade; - _mode = MBProgressHUDModeIndeterminate; - _margin = 20.0f; - _opacity = 1.f; - _defaultMotionEffectsEnabled = YES; - - // Default color, depending on the current iOS version - BOOL isLegacy = kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_7_0; - _contentColor = isLegacy ? [UIColor whiteColor] : [UIColor colorWithWhite:0.f alpha:0.7f]; - // Transparent background - self.opaque = NO; - self.backgroundColor = [UIColor clearColor]; - // Make it invisible for now - self.alpha = 0.0f; - self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - self.layer.allowsGroupOpacity = NO; - - [self setupViews]; - [self updateIndicators]; - [self registerForNotifications]; -} - -- (instancetype)initWithFrame:(CGRect)frame { - if ((self = [super initWithFrame:frame])) { - [self commonInit]; - } - return self; -} - -- (instancetype)initWithCoder:(NSCoder *)aDecoder { - if ((self = [super initWithCoder:aDecoder])) { - [self commonInit]; - } - return self; -} - -- (id)initWithView:(UIView *)view { - NSAssert(view, @"View must not be nil."); - return [self initWithFrame:view.bounds]; -} - -- (void)dealloc { - [self unregisterFromNotifications]; -} - -#pragma mark - Show & hide - -- (void)showAnimated:(BOOL)animated { - MBMainThreadAssert(); - [self.minShowTimer invalidate]; - self.useAnimation = animated; - self.finished = NO; - // If the grace time is set, postpone the HUD display - if (self.graceTime > 0.0) { - NSTimer *timer = [NSTimer timerWithTimeInterval:self.graceTime target:self selector:@selector(handleGraceTimer:) userInfo:nil repeats:NO]; - [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; - self.graceTimer = timer; - } - // ... otherwise show the HUD immediately - else { - [self showUsingAnimation:self.useAnimation]; - } -} - -- (void)hideAnimated:(BOOL)animated { - MBMainThreadAssert(); - [self.graceTimer invalidate]; - self.useAnimation = animated; - self.finished = YES; - // If the minShow time is set, calculate how long the HUD was shown, - // and postpone the hiding operation if necessary - if (self.minShowTime > 0.0 && self.showStarted) { - NSTimeInterval interv = [[NSDate date] timeIntervalSinceDate:self.showStarted]; - if (interv < self.minShowTime) { - NSTimer *timer = [NSTimer timerWithTimeInterval:(self.minShowTime - interv) target:self selector:@selector(handleMinShowTimer:) userInfo:nil repeats:NO]; - [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; - self.minShowTimer = timer; - return; - } - } - // ... otherwise hide the HUD immediately - [self hideUsingAnimation:self.useAnimation]; -} - -- (void)hideAnimated:(BOOL)animated afterDelay:(NSTimeInterval)delay { - // Cancel any scheduled hideDelayed: calls - [self.hideDelayTimer invalidate]; - - NSTimer *timer = [NSTimer timerWithTimeInterval:delay target:self selector:@selector(handleHideTimer:) userInfo:@(animated) repeats:NO]; - [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; - self.hideDelayTimer = timer; -} - -#pragma mark - Timer callbacks - -- (void)handleGraceTimer:(NSTimer *)theTimer { - // Show the HUD only if the task is still running - if (!self.hasFinished) { - [self showUsingAnimation:self.useAnimation]; - } -} - -- (void)handleMinShowTimer:(NSTimer *)theTimer { - [self hideUsingAnimation:self.useAnimation]; -} - -- (void)handleHideTimer:(NSTimer *)timer { - [self hideAnimated:[timer.userInfo boolValue]]; -} - -#pragma mark - View Hierrarchy - -- (void)didMoveToSuperview { - [self updateForCurrentOrientationAnimated:NO]; -} - -#pragma mark - Internal show & hide operations - -- (void)showUsingAnimation:(BOOL)animated { - // Cancel any previous animations - [self.bezelView.layer removeAllAnimations]; - [self.backgroundView.layer removeAllAnimations]; - - // Cancel any scheduled hideDelayed: calls - [self.hideDelayTimer invalidate]; - - self.showStarted = [NSDate date]; - self.alpha = 1.f; - - // Needed in case we hide and re-show with the same NSProgress object attached. - [self setNSProgressDisplayLinkEnabled:YES]; - - if (animated) { - [self animateIn:YES withType:self.animationType completion:NULL]; - } else { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - self.bezelView.alpha = self.opacity; -#pragma clang diagnostic pop - self.backgroundView.alpha = 1.f; - } -} - -- (void)hideUsingAnimation:(BOOL)animated { - if (animated && self.showStarted) { - self.showStarted = nil; - [self animateIn:NO withType:self.animationType completion:^(BOOL finished) { - [self done]; - }]; - } else { - self.showStarted = nil; - self.bezelView.alpha = 0.f; - self.backgroundView.alpha = 1.f; - [self done]; - } -} - -- (void)animateIn:(BOOL)animatingIn withType:(MBProgressHUDAnimation)type completion:(void(^)(BOOL finished))completion { - // Automatically determine the correct zoom animation type - if (type == MBProgressHUDAnimationZoom) { - type = animatingIn ? MBProgressHUDAnimationZoomIn : MBProgressHUDAnimationZoomOut; - } - - CGAffineTransform small = CGAffineTransformMakeScale(0.5f, 0.5f); - CGAffineTransform large = CGAffineTransformMakeScale(1.5f, 1.5f); - - // Set starting state - UIView *bezelView = self.bezelView; - if (animatingIn && bezelView.alpha == 0.f && type == MBProgressHUDAnimationZoomIn) { - bezelView.transform = small; - } else if (animatingIn && bezelView.alpha == 0.f && type == MBProgressHUDAnimationZoomOut) { - bezelView.transform = large; - } - - // Perform animations - dispatch_block_t animations = ^{ - if (animatingIn) { - bezelView.transform = CGAffineTransformIdentity; - } else if (!animatingIn && type == MBProgressHUDAnimationZoomIn) { - bezelView.transform = large; - } else if (!animatingIn && type == MBProgressHUDAnimationZoomOut) { - bezelView.transform = small; - } -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - bezelView.alpha = animatingIn ? self.opacity : 0.f; -#pragma clang diagnostic pop - self.backgroundView.alpha = animatingIn ? 1.f : 0.f; - }; - - // Spring animations are nicer, but only available on iOS 7+ -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 || TARGET_OS_TV - if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_7_0) { - [UIView animateWithDuration:0.3 delay:0. usingSpringWithDamping:1.f initialSpringVelocity:0.f options:UIViewAnimationOptionBeginFromCurrentState animations:animations completion:completion]; - return; - } -#endif - [UIView animateWithDuration:0.3 delay:0. options:UIViewAnimationOptionBeginFromCurrentState animations:animations completion:completion]; -} - -- (void)done { - // Cancel any scheduled hideDelayed: calls - [self.hideDelayTimer invalidate]; - [self setNSProgressDisplayLinkEnabled:NO]; - - if (self.hasFinished) { - self.alpha = 0.0f; - if (self.removeFromSuperViewOnHide) { - [self removeFromSuperview]; - } - } - MBProgressHUDCompletionBlock completionBlock = self.completionBlock; - if (completionBlock) { - completionBlock(); - } - id delegate = self.delegate; - if ([delegate respondsToSelector:@selector(hudWasHidden:)]) { - [delegate performSelector:@selector(hudWasHidden:) withObject:self]; - } -} - -#pragma mark - UI - -- (void)setupViews { - UIColor *defaultColor = self.contentColor; - - MBBackgroundView *backgroundView = [[MBBackgroundView alloc] initWithFrame:self.bounds]; - backgroundView.style = MBProgressHUDBackgroundStyleSolidColor; - backgroundView.backgroundColor = [UIColor clearColor]; - backgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - backgroundView.alpha = 0.f; - [self addSubview:backgroundView]; - _backgroundView = backgroundView; - - MBBackgroundView *bezelView = [MBBackgroundView new]; - bezelView.translatesAutoresizingMaskIntoConstraints = NO; - bezelView.layer.cornerRadius = 5.f; - bezelView.alpha = 0.f; - [self addSubview:bezelView]; - _bezelView = bezelView; - [self updateBezelMotionEffects]; - - UILabel *label = [UILabel new]; - label.adjustsFontSizeToFitWidth = NO; - label.textAlignment = NSTextAlignmentCenter; - label.textColor = defaultColor; - label.font = [UIFont boldSystemFontOfSize:MBDefaultLabelFontSize]; - label.opaque = NO; - label.backgroundColor = [UIColor clearColor]; - _label = label; - - UILabel *detailsLabel = [UILabel new]; - detailsLabel.adjustsFontSizeToFitWidth = NO; - detailsLabel.textAlignment = NSTextAlignmentCenter; - detailsLabel.textColor = defaultColor; - detailsLabel.numberOfLines = 0; - detailsLabel.font = [UIFont boldSystemFontOfSize:MBDefaultDetailsLabelFontSize]; - detailsLabel.opaque = NO; - detailsLabel.backgroundColor = [UIColor clearColor]; - _detailsLabel = detailsLabel; - - UIButton *button = [MBProgressHUDRoundedButton buttonWithType:UIButtonTypeCustom]; - button.titleLabel.textAlignment = NSTextAlignmentCenter; - button.titleLabel.font = [UIFont boldSystemFontOfSize:MBDefaultDetailsLabelFontSize]; - [button setTitleColor:defaultColor forState:UIControlStateNormal]; - _button = button; - - for (UIView *view in @[label, detailsLabel, button]) { - view.translatesAutoresizingMaskIntoConstraints = NO; - [view setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisHorizontal]; - [view setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisVertical]; - [bezelView addSubview:view]; - } - - UIView *topSpacer = [UIView new]; - topSpacer.translatesAutoresizingMaskIntoConstraints = NO; - topSpacer.hidden = YES; - [bezelView addSubview:topSpacer]; - _topSpacer = topSpacer; - - UIView *bottomSpacer = [UIView new]; - bottomSpacer.translatesAutoresizingMaskIntoConstraints = NO; - bottomSpacer.hidden = YES; - [bezelView addSubview:bottomSpacer]; - _bottomSpacer = bottomSpacer; -} - -- (void)updateIndicators { - UIView *indicator = self.indicator; - BOOL isActivityIndicator = [indicator isKindOfClass:[UIActivityIndicatorView class]]; - BOOL isRoundIndicator = [indicator isKindOfClass:[MBRoundProgressView class]]; - - MBProgressHUDMode mode = self.mode; - if (mode == MBProgressHUDModeIndeterminate) { - if (!isActivityIndicator) { - // Update to indeterminate indicator - [indicator removeFromSuperview]; - indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; - [(UIActivityIndicatorView *)indicator startAnimating]; - [self.bezelView addSubview:indicator]; - } - } - else if (mode == MBProgressHUDModeDeterminateHorizontalBar) { - // Update to bar determinate indicator - [indicator removeFromSuperview]; - indicator = [[MBBarProgressView alloc] init]; - [self.bezelView addSubview:indicator]; - } - else if (mode == MBProgressHUDModeDeterminate || mode == MBProgressHUDModeAnnularDeterminate) { - if (!isRoundIndicator) { - // Update to determinante indicator - [indicator removeFromSuperview]; - indicator = [[MBRoundProgressView alloc] init]; - [self.bezelView addSubview:indicator]; - } - if (mode == MBProgressHUDModeAnnularDeterminate) { - [(MBRoundProgressView *)indicator setAnnular:YES]; - } - } - else if (mode == MBProgressHUDModeCustomView && self.customView != indicator) { - // Update custom view indicator - [indicator removeFromSuperview]; - indicator = self.customView; - [self.bezelView addSubview:indicator]; - } - else if (mode == MBProgressHUDModeText) { - [indicator removeFromSuperview]; - indicator = nil; - } - indicator.translatesAutoresizingMaskIntoConstraints = NO; - self.indicator = indicator; - - if ([indicator respondsToSelector:@selector(setProgress:)]) { - [(id)indicator setValue:@(self.progress) forKey:@"progress"]; - } - - [indicator setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisHorizontal]; - [indicator setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisVertical]; - - [self updateViewsForColor:self.contentColor]; - [self setNeedsUpdateConstraints]; -} - -- (void)updateViewsForColor:(UIColor *)color { - if (!color) return; - - self.label.textColor = color; - self.detailsLabel.textColor = color; - [self.button setTitleColor:color forState:UIControlStateNormal]; - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - if (self.activityIndicatorColor) { - color = self.activityIndicatorColor; - } -#pragma clang diagnostic pop - - // UIAppearance settings are prioritized. If they are preset the set color is ignored. - - UIView *indicator = self.indicator; - if ([indicator isKindOfClass:[UIActivityIndicatorView class]]) { - UIActivityIndicatorView *appearance = nil; -#if __IPHONE_OS_VERSION_MIN_REQUIRED < 90000 - appearance = [UIActivityIndicatorView appearanceWhenContainedIn:[MBProgressHUD class], nil]; -#else - // For iOS 9+ - appearance = [UIActivityIndicatorView appearanceWhenContainedInInstancesOfClasses:@[[MBProgressHUD class]]]; -#endif - - if (appearance.color == nil) { - ((UIActivityIndicatorView *)indicator).color = color; - } - } else if ([indicator isKindOfClass:[MBRoundProgressView class]]) { - MBRoundProgressView *appearance = nil; -#if __IPHONE_OS_VERSION_MIN_REQUIRED < 90000 - appearance = [MBRoundProgressView appearanceWhenContainedIn:[MBProgressHUD class], nil]; -#else - appearance = [MBRoundProgressView appearanceWhenContainedInInstancesOfClasses:@[[MBProgressHUD class]]]; -#endif - if (appearance.progressTintColor == nil) { - ((MBRoundProgressView *)indicator).progressTintColor = color; - } - if (appearance.backgroundTintColor == nil) { - ((MBRoundProgressView *)indicator).backgroundTintColor = [color colorWithAlphaComponent:0.1]; - } - } else if ([indicator isKindOfClass:[MBBarProgressView class]]) { - MBBarProgressView *appearance = nil; -#if __IPHONE_OS_VERSION_MIN_REQUIRED < 90000 - appearance = [MBBarProgressView appearanceWhenContainedIn:[MBProgressHUD class], nil]; -#else - appearance = [MBBarProgressView appearanceWhenContainedInInstancesOfClasses:@[[MBProgressHUD class]]]; -#endif - if (appearance.progressColor == nil) { - ((MBBarProgressView *)indicator).progressColor = color; - } - if (appearance.lineColor == nil) { - ((MBBarProgressView *)indicator).lineColor = color; - } - } else { -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 || TARGET_OS_TV - if ([indicator respondsToSelector:@selector(setTintColor:)]) { - [indicator setTintColor:color]; - } -#endif - } -} - -- (void)updateBezelMotionEffects { -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 || TARGET_OS_TV - MBBackgroundView *bezelView = self.bezelView; - if (![bezelView respondsToSelector:@selector(addMotionEffect:)]) return; - - if (self.defaultMotionEffectsEnabled) { - CGFloat effectOffset = 10.f; - UIInterpolatingMotionEffect *effectX = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; - effectX.maximumRelativeValue = @(effectOffset); - effectX.minimumRelativeValue = @(-effectOffset); - - UIInterpolatingMotionEffect *effectY = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis]; - effectY.maximumRelativeValue = @(effectOffset); - effectY.minimumRelativeValue = @(-effectOffset); - - UIMotionEffectGroup *group = [[UIMotionEffectGroup alloc] init]; - group.motionEffects = @[effectX, effectY]; - - [bezelView addMotionEffect:group]; - } else { - NSArray *effects = [bezelView motionEffects]; - for (UIMotionEffect *effect in effects) { - [bezelView removeMotionEffect:effect]; - } - } -#endif -} - -#pragma mark - Layout - -- (void)updateConstraints { - UIView *bezel = self.bezelView; - UIView *topSpacer = self.topSpacer; - UIView *bottomSpacer = self.bottomSpacer; - CGFloat margin = self.margin; - NSMutableArray *bezelConstraints = [NSMutableArray array]; - NSDictionary *metrics = @{@"margin": @(margin)}; - - NSMutableArray *subviews = [NSMutableArray arrayWithObjects:self.topSpacer, self.label, self.detailsLabel, self.button, self.bottomSpacer, nil]; - if (self.indicator) [subviews insertObject:self.indicator atIndex:1]; - - // Remove existing constraints - [self removeConstraints:self.constraints]; - [topSpacer removeConstraints:topSpacer.constraints]; - [bottomSpacer removeConstraints:bottomSpacer.constraints]; - if (self.bezelConstraints) { - [bezel removeConstraints:self.bezelConstraints]; - self.bezelConstraints = nil; - } - - // Center bezel in container (self), applying the offset if set - CGPoint offset = self.offset; - NSMutableArray *centeringConstraints = [NSMutableArray array]; - [centeringConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1.f constant:offset.x]]; - [centeringConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.f constant:offset.y]]; - [self applyPriority:998.f toConstraints:centeringConstraints]; - [self addConstraints:centeringConstraints]; - - // Ensure minimum side margin is kept - NSMutableArray *sideConstraints = [NSMutableArray array]; - [sideConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"|-(>=margin)-[bezel]-(>=margin)-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(bezel)]]; - [sideConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=margin)-[bezel]-(>=margin)-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(bezel)]]; - [self applyPriority:999.f toConstraints:sideConstraints]; - [self addConstraints:sideConstraints]; - - // Minimum bezel size, if set - CGSize minimumSize = self.minSize; - if (!CGSizeEqualToSize(minimumSize, CGSizeZero)) { - NSMutableArray *minSizeConstraints = [NSMutableArray array]; - [minSizeConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:minimumSize.width]]; - [minSizeConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:minimumSize.height]]; - [self applyPriority:997.f toConstraints:minSizeConstraints]; - [bezelConstraints addObjectsFromArray:minSizeConstraints]; - } - - // Square aspect ratio, if set - if (self.square) { - NSLayoutConstraint *square = [NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeWidth multiplier:1.f constant:0]; - square.priority = 997.f; - [bezelConstraints addObject:square]; - } - - // Top and bottom spacing - [topSpacer addConstraint:[NSLayoutConstraint constraintWithItem:topSpacer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:margin]]; - [bottomSpacer addConstraint:[NSLayoutConstraint constraintWithItem:bottomSpacer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:margin]]; - // Top and bottom spaces should be equal - [bezelConstraints addObject:[NSLayoutConstraint constraintWithItem:topSpacer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:bottomSpacer attribute:NSLayoutAttributeHeight multiplier:1.f constant:0.f]]; - - // Layout subviews in bezel - NSMutableArray *paddingConstraints = [NSMutableArray new]; - [subviews enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) { - // Center in bezel - [bezelConstraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeCenterX multiplier:1.f constant:0.f]]; - // Ensure the minimum edge margin is kept - [bezelConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"|-(>=margin)-[view]-(>=margin)-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(view)]]; - // Element spacing - if (idx == 0) { - // First, ensure spacing to bezel edge - [bezelConstraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeTop multiplier:1.f constant:0.f]]; - } else if (idx == subviews.count - 1) { - // Last, ensure spacing to bezel edge - [bezelConstraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeBottom multiplier:1.f constant:0.f]]; - } - if (idx > 0) { - // Has previous - NSLayoutConstraint *padding = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:subviews[idx - 1] attribute:NSLayoutAttributeBottom multiplier:1.f constant:0.f]; - [bezelConstraints addObject:padding]; - [paddingConstraints addObject:padding]; - } - }]; - - [bezel addConstraints:bezelConstraints]; - self.bezelConstraints = bezelConstraints; - - self.paddingConstraints = [paddingConstraints copy]; - [self updatePaddingConstraints]; - - [super updateConstraints]; -} - -- (void)layoutSubviews { - // There is no need to update constraints if they are going to - // be recreated in [super layoutSubviews] due to needsUpdateConstraints being set. - // This also avoids an issue on iOS 8, where updatePaddingConstraints - // would trigger a zombie object access. - if (!self.needsUpdateConstraints) { - [self updatePaddingConstraints]; - } - [super layoutSubviews]; -} - -- (void)updatePaddingConstraints { - // Set padding dynamically, depending on whether the view is visible or not - __block BOOL hasVisibleAncestors = NO; - [self.paddingConstraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *padding, NSUInteger idx, BOOL *stop) { - UIView *firstView = (UIView *)padding.firstItem; - UIView *secondView = (UIView *)padding.secondItem; - BOOL firstVisible = !firstView.hidden && !CGSizeEqualToSize(firstView.intrinsicContentSize, CGSizeZero); - BOOL secondVisible = !secondView.hidden && !CGSizeEqualToSize(secondView.intrinsicContentSize, CGSizeZero); - // Set if both views are visible or if there's a visible view on top that doesn't have padding - // added relative to the current view yet - padding.constant = (firstVisible && (secondVisible || hasVisibleAncestors)) ? MBDefaultPadding : 0.f; - hasVisibleAncestors |= secondVisible; - }]; -} - -- (void)applyPriority:(UILayoutPriority)priority toConstraints:(NSArray *)constraints { - for (NSLayoutConstraint *constraint in constraints) { - constraint.priority = priority; - } -} - -#pragma mark - Properties - -- (void)setMode:(MBProgressHUDMode)mode { - if (mode != _mode) { - _mode = mode; - [self updateIndicators]; - } -} - -- (void)setCustomView:(UIView *)customView { - if (customView != _customView) { - _customView = customView; - if (self.mode == MBProgressHUDModeCustomView) { - [self updateIndicators]; - } - } -} - -- (void)setOffset:(CGPoint)offset { - if (!CGPointEqualToPoint(offset, _offset)) { - _offset = offset; - [self setNeedsUpdateConstraints]; - } -} - -- (void)setMargin:(CGFloat)margin { - if (margin != _margin) { - _margin = margin; - [self setNeedsUpdateConstraints]; - } -} - -- (void)setMinSize:(CGSize)minSize { - if (!CGSizeEqualToSize(minSize, _minSize)) { - _minSize = minSize; - [self setNeedsUpdateConstraints]; - } -} - -- (void)setSquare:(BOOL)square { - if (square != _square) { - _square = square; - [self setNeedsUpdateConstraints]; - } -} - -- (void)setProgressObjectDisplayLink:(CADisplayLink *)progressObjectDisplayLink { - if (progressObjectDisplayLink != _progressObjectDisplayLink) { - [_progressObjectDisplayLink invalidate]; - - _progressObjectDisplayLink = progressObjectDisplayLink; - - [_progressObjectDisplayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; - } -} - -- (void)setProgressObject:(NSProgress *)progressObject { - if (progressObject != _progressObject) { - _progressObject = progressObject; - [self setNSProgressDisplayLinkEnabled:YES]; - } -} - -- (void)setProgress:(float)progress { - if (progress != _progress) { - _progress = progress; - UIView *indicator = self.indicator; - if ([indicator respondsToSelector:@selector(setProgress:)]) { - [(id)indicator setValue:@(self.progress) forKey:@"progress"]; - } - } -} - -- (void)setContentColor:(UIColor *)contentColor { - if (contentColor != _contentColor && ![contentColor isEqual:_contentColor]) { - _contentColor = contentColor; - [self updateViewsForColor:contentColor]; - } -} - -- (void)setDefaultMotionEffectsEnabled:(BOOL)defaultMotionEffectsEnabled { - if (defaultMotionEffectsEnabled != _defaultMotionEffectsEnabled) { - _defaultMotionEffectsEnabled = defaultMotionEffectsEnabled; - [self updateBezelMotionEffects]; - } -} - -#pragma mark - NSProgress - -- (void)setNSProgressDisplayLinkEnabled:(BOOL)enabled { - // We're using CADisplayLink, because NSProgress can change very quickly and observing it may starve the main thread, - // so we're refreshing the progress only every frame draw - if (enabled && self.progressObject) { - // Only create if not already active. - if (!self.progressObjectDisplayLink) { - self.progressObjectDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateProgressFromProgressObject)]; - } - } else { - self.progressObjectDisplayLink = nil; - } -} - -- (void)updateProgressFromProgressObject { - self.progress = self.progressObject.fractionCompleted; -} - -#pragma mark - Notifications - -- (void)registerForNotifications { -#if !TARGET_OS_TV - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - - [nc addObserver:self selector:@selector(statusBarOrientationDidChange:) - name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; -#endif -} - -- (void)unregisterFromNotifications { -#if !TARGET_OS_TV - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - [nc removeObserver:self name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; -#endif -} - -#if !TARGET_OS_TV -- (void)statusBarOrientationDidChange:(NSNotification *)notification { - UIView *superview = self.superview; - if (!superview) { - return; - } else { - [self updateForCurrentOrientationAnimated:YES]; - } -} -#endif - -- (void)updateForCurrentOrientationAnimated:(BOOL)animated { - // Stay in sync with the superview in any case - if (self.superview) { - self.frame = self.superview.bounds; - } - - // Not needed on iOS 8+, compile out when the deployment target allows, - // to avoid sharedApplication problems on extension targets -#if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000 - // Only needed pre iOS 8 when added to a window - BOOL iOS8OrLater = kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_8_0; - if (iOS8OrLater || ![self.superview isKindOfClass:[UIWindow class]]) return; - - // Make extension friendly. Will not get called on extensions (iOS 8+) due to the above check. - // This just ensures we don't get a warning about extension-unsafe API. - Class UIApplicationClass = NSClassFromString(@"UIApplication"); - if (!UIApplicationClass || ![UIApplicationClass respondsToSelector:@selector(sharedApplication)]) return; - - UIApplication *application = [UIApplication performSelector:@selector(sharedApplication)]; - UIInterfaceOrientation orientation = application.statusBarOrientation; - CGFloat radians = 0; - - if (UIInterfaceOrientationIsLandscape(orientation)) { - radians = orientation == UIInterfaceOrientationLandscapeLeft ? -(CGFloat)M_PI_2 : (CGFloat)M_PI_2; - // Window coordinates differ! - self.bounds = CGRectMake(0, 0, self.bounds.size.height, self.bounds.size.width); - } else { - radians = orientation == UIInterfaceOrientationPortraitUpsideDown ? (CGFloat)M_PI : 0.f; - } - - if (animated) { - [UIView animateWithDuration:0.3 animations:^{ - self.transform = CGAffineTransformMakeRotation(radians); - }]; - } else { - self.transform = CGAffineTransformMakeRotation(radians); - } -#endif -} - -@end - - -@implementation MBRoundProgressView - -#pragma mark - Lifecycle - -- (id)init { - return [self initWithFrame:CGRectMake(0.f, 0.f, 37.f, 37.f)]; -} - -- (id)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - self.backgroundColor = [UIColor clearColor]; - self.opaque = NO; - _progress = 0.f; - _annular = NO; - _progressTintColor = [[UIColor alloc] initWithWhite:1.f alpha:1.f]; - _backgroundTintColor = [[UIColor alloc] initWithWhite:1.f alpha:.1f]; - } - return self; -} - -#pragma mark - Layout - -- (CGSize)intrinsicContentSize { - return CGSizeMake(37.f, 37.f); -} - -#pragma mark - Properties - -- (void)setProgress:(float)progress { - if (progress != _progress) { - _progress = progress; - [self setNeedsDisplay]; - } -} - -- (void)setProgressTintColor:(UIColor *)progressTintColor { - NSAssert(progressTintColor, @"The color should not be nil."); - if (progressTintColor != _progressTintColor && ![progressTintColor isEqual:_progressTintColor]) { - _progressTintColor = progressTintColor; - [self setNeedsDisplay]; - } -} - -- (void)setBackgroundTintColor:(UIColor *)backgroundTintColor { - NSAssert(backgroundTintColor, @"The color should not be nil."); - if (backgroundTintColor != _backgroundTintColor && ![backgroundTintColor isEqual:_backgroundTintColor]) { - _backgroundTintColor = backgroundTintColor; - [self setNeedsDisplay]; - } -} - -#pragma mark - Drawing - -- (void)drawRect:(CGRect)rect { - CGContextRef context = UIGraphicsGetCurrentContext(); - BOOL isPreiOS7 = kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_7_0; - - if (_annular) { - // Draw background - CGFloat lineWidth = isPreiOS7 ? 5.f : 2.f; - UIBezierPath *processBackgroundPath = [UIBezierPath bezierPath]; - processBackgroundPath.lineWidth = lineWidth; - processBackgroundPath.lineCapStyle = kCGLineCapButt; - CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); - CGFloat radius = (self.bounds.size.width - lineWidth)/2; - CGFloat startAngle = - ((float)M_PI / 2); // 90 degrees - CGFloat endAngle = (2 * (float)M_PI) + startAngle; - [processBackgroundPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; - [_backgroundTintColor set]; - [processBackgroundPath stroke]; - // Draw progress - UIBezierPath *processPath = [UIBezierPath bezierPath]; - processPath.lineCapStyle = isPreiOS7 ? kCGLineCapRound : kCGLineCapSquare; - processPath.lineWidth = lineWidth; - endAngle = (self.progress * 2 * (float)M_PI) + startAngle; - [processPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; - [_progressTintColor set]; - [processPath stroke]; - } else { - // Draw background - CGFloat lineWidth = 2.f; - CGRect allRect = self.bounds; - CGRect circleRect = CGRectInset(allRect, lineWidth/2.f, lineWidth/2.f); - CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); - [_progressTintColor setStroke]; - [_backgroundTintColor setFill]; - CGContextSetLineWidth(context, lineWidth); - if (isPreiOS7) { - CGContextFillEllipseInRect(context, circleRect); - } - CGContextStrokeEllipseInRect(context, circleRect); - // 90 degrees - CGFloat startAngle = - ((float)M_PI / 2.f); - // Draw progress - if (isPreiOS7) { - CGFloat radius = (CGRectGetWidth(self.bounds) / 2.f) - lineWidth; - CGFloat endAngle = (self.progress * 2.f * (float)M_PI) + startAngle; - [_progressTintColor setFill]; - CGContextMoveToPoint(context, center.x, center.y); - CGContextAddArc(context, center.x, center.y, radius, startAngle, endAngle, 0); - CGContextClosePath(context); - CGContextFillPath(context); - } else { - UIBezierPath *processPath = [UIBezierPath bezierPath]; - processPath.lineCapStyle = kCGLineCapButt; - processPath.lineWidth = lineWidth * 2.f; - CGFloat radius = (CGRectGetWidth(self.bounds) / 2.f) - (processPath.lineWidth / 2.f); - CGFloat endAngle = (self.progress * 2.f * (float)M_PI) + startAngle; - [processPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; - // Ensure that we don't get color overlapping when _progressTintColor alpha < 1.f. - CGContextSetBlendMode(context, kCGBlendModeCopy); - [_progressTintColor set]; - [processPath stroke]; - } - } -} - -@end - - -@implementation MBBarProgressView - -#pragma mark - Lifecycle - -- (id)init { - return [self initWithFrame:CGRectMake(.0f, .0f, 120.0f, 20.0f)]; -} - -- (id)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - _progress = 0.f; - _lineColor = [UIColor whiteColor]; - _progressColor = [UIColor whiteColor]; - _progressRemainingColor = [UIColor clearColor]; - self.backgroundColor = [UIColor clearColor]; - self.opaque = NO; - } - return self; -} - -#pragma mark - Layout - -- (CGSize)intrinsicContentSize { - BOOL isPreiOS7 = kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_7_0; - return CGSizeMake(120.f, isPreiOS7 ? 20.f : 10.f); -} - -#pragma mark - Properties - -- (void)setProgress:(float)progress { - if (progress != _progress) { - _progress = progress; - [self setNeedsDisplay]; - } -} - -- (void)setProgressColor:(UIColor *)progressColor { - NSAssert(progressColor, @"The color should not be nil."); - if (progressColor != _progressColor && ![progressColor isEqual:_progressColor]) { - _progressColor = progressColor; - [self setNeedsDisplay]; - } -} - -- (void)setProgressRemainingColor:(UIColor *)progressRemainingColor { - NSAssert(progressRemainingColor, @"The color should not be nil."); - if (progressRemainingColor != _progressRemainingColor && ![progressRemainingColor isEqual:_progressRemainingColor]) { - _progressRemainingColor = progressRemainingColor; - [self setNeedsDisplay]; - } -} - -#pragma mark - Drawing - -- (void)drawRect:(CGRect)rect { - CGContextRef context = UIGraphicsGetCurrentContext(); - - CGContextSetLineWidth(context, 2); - CGContextSetStrokeColorWithColor(context,[_lineColor CGColor]); - CGContextSetFillColorWithColor(context, [_progressRemainingColor CGColor]); - - // Draw background and Border - CGFloat radius = (rect.size.height / 2) - 2; - CGContextMoveToPoint(context, 2, rect.size.height/2); - CGContextAddArcToPoint(context, 2, 2, radius + 2, 2, radius); - CGContextAddArcToPoint(context, rect.size.width - 2, 2, rect.size.width - 2, rect.size.height / 2, radius); - CGContextAddArcToPoint(context, rect.size.width - 2, rect.size.height - 2, rect.size.width - radius - 2, rect.size.height - 2, radius); - CGContextAddArcToPoint(context, 2, rect.size.height - 2, 2, rect.size.height/2, radius); - CGContextDrawPath(context, kCGPathFillStroke); - - CGContextSetFillColorWithColor(context, [_progressColor CGColor]); - radius = radius - 2; - CGFloat amount = self.progress * rect.size.width; - - // Progress in the middle area - if (amount >= radius + 4 && amount <= (rect.size.width - radius - 4)) { - CGContextMoveToPoint(context, 4, rect.size.height/2); - CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius); - CGContextAddLineToPoint(context, amount, 4); - CGContextAddLineToPoint(context, amount, radius + 4); - - CGContextMoveToPoint(context, 4, rect.size.height/2); - CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius); - CGContextAddLineToPoint(context, amount, rect.size.height - 4); - CGContextAddLineToPoint(context, amount, radius + 4); - - CGContextFillPath(context); - } - - // Progress in the right arc - else if (amount > radius + 4) { - CGFloat x = amount - (rect.size.width - radius - 4); - - CGContextMoveToPoint(context, 4, rect.size.height/2); - CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius); - CGContextAddLineToPoint(context, rect.size.width - radius - 4, 4); - CGFloat angle = -acos(x/radius); - if (isnan(angle)) angle = 0; - CGContextAddArc(context, rect.size.width - radius - 4, rect.size.height/2, radius, M_PI, angle, 0); - CGContextAddLineToPoint(context, amount, rect.size.height/2); - - CGContextMoveToPoint(context, 4, rect.size.height/2); - CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius); - CGContextAddLineToPoint(context, rect.size.width - radius - 4, rect.size.height - 4); - angle = acos(x/radius); - if (isnan(angle)) angle = 0; - CGContextAddArc(context, rect.size.width - radius - 4, rect.size.height/2, radius, -M_PI, angle, 1); - CGContextAddLineToPoint(context, amount, rect.size.height/2); - - CGContextFillPath(context); - } - - // Progress is in the left arc - else if (amount < radius + 4 && amount > 0) { - CGContextMoveToPoint(context, 4, rect.size.height/2); - CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius); - CGContextAddLineToPoint(context, radius + 4, rect.size.height/2); - - CGContextMoveToPoint(context, 4, rect.size.height/2); - CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius); - CGContextAddLineToPoint(context, radius + 4, rect.size.height/2); - - CGContextFillPath(context); - } -} - -@end - - -@interface MBBackgroundView () - -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 || TARGET_OS_TV -@property UIVisualEffectView *effectView; -#endif -#if !TARGET_OS_TV -@property UIToolbar *toolbar; -#endif - -@end - - -@implementation MBBackgroundView - -#pragma mark - Lifecycle - -- (instancetype)initWithFrame:(CGRect)frame { - if ((self = [super initWithFrame:frame])) { - if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_7_0) { - _style = MBProgressHUDBackgroundStyleBlur; -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 || TARGET_OS_TV - _blurEffectStyle = UIBlurEffectStyleLight; -#endif - if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_8_0) { - _color = [UIColor colorWithWhite:0.8f alpha:0.6f]; - } else { - _color = [UIColor colorWithWhite:0.95f alpha:0.6f]; - } - } else { - _style = MBProgressHUDBackgroundStyleSolidColor; - _color = [[UIColor blackColor] colorWithAlphaComponent:0.8]; - } - - self.clipsToBounds = YES; - - [self updateForBackgroundStyle]; - } - return self; -} - -#pragma mark - Layout - -- (CGSize)intrinsicContentSize { - // Smallest size possible. Content pushes against this. - return CGSizeZero; -} - -#pragma mark - Appearance - -- (void)setStyle:(MBProgressHUDBackgroundStyle)style { - if (style == MBProgressHUDBackgroundStyleBlur && kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_7_0) { - style = MBProgressHUDBackgroundStyleSolidColor; - } - if (_style != style) { - _style = style; - [self updateForBackgroundStyle]; - } -} - -- (void)setColor:(UIColor *)color { - NSAssert(color, @"The color should not be nil."); - if (color != _color && ![color isEqual:_color]) { - _color = color; - [self updateViewsForColor:color]; - } -} - -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 || TARGET_OS_TV - -- (void)setBlurEffectStyle:(UIBlurEffectStyle)blurEffectStyle { - if (_blurEffectStyle == blurEffectStyle) { - return; - } - - _blurEffectStyle = blurEffectStyle; - - [self updateForBackgroundStyle]; -} - -#endif - -/////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark - Views - -- (void)updateForBackgroundStyle { - MBProgressHUDBackgroundStyle style = self.style; - if (style == MBProgressHUDBackgroundStyleBlur) { -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 || TARGET_OS_TV - if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_8_0) { - UIBlurEffect *effect = [UIBlurEffect effectWithStyle:self.blurEffectStyle]; - UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:effect]; - [self addSubview:effectView]; - effectView.frame = self.bounds; - effectView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; - self.backgroundColor = self.color; - self.layer.allowsGroupOpacity = NO; - self.effectView = effectView; - } else { -#endif -#if !TARGET_OS_TV - UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame:CGRectInset(self.bounds, -100.f, -100.f)]; - toolbar.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; - toolbar.barTintColor = self.color; - toolbar.translucent = YES; - [self addSubview:toolbar]; - self.toolbar = toolbar; -#endif -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 || TARGET_OS_TV - } -#endif - } else { -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 || TARGET_OS_TV - if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_8_0) { - [self.effectView removeFromSuperview]; - self.effectView = nil; - } else { -#endif -#if !TARGET_OS_TV - [self.toolbar removeFromSuperview]; - self.toolbar = nil; -#endif -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 || TARGET_OS_TV - } -#endif - self.backgroundColor = self.color; - } -} - -- (void)updateViewsForColor:(UIColor *)color { - if (self.style == MBProgressHUDBackgroundStyleBlur) { - if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_8_0) { - self.backgroundColor = self.color; - } else { -#if !TARGET_OS_TV - self.toolbar.barTintColor = color; -#endif - } - } else { - self.backgroundColor = self.color; - } -} - -@end - - -@implementation MBProgressHUD (Deprecated) - -#pragma mark - Class - -+ (NSUInteger)hideAllHUDsForView:(UIView *)view animated:(BOOL)animated { - NSArray *huds = [MBProgressHUD allHUDsForView:view]; - for (MBProgressHUD *hud in huds) { - hud.removeFromSuperViewOnHide = YES; - [hud hideAnimated:animated]; - } - return [huds count]; -} - -+ (NSArray *)allHUDsForView:(UIView *)view { - NSMutableArray *huds = [NSMutableArray array]; - NSArray *subviews = view.subviews; - for (UIView *aView in subviews) { - if ([aView isKindOfClass:self]) { - [huds addObject:aView]; - } - } - return [NSArray arrayWithArray:huds]; -} - -#pragma mark - Lifecycle - -- (id)initWithWindow:(UIWindow *)window { - return [self initWithView:window]; -} - -#pragma mark - Show & hide - -- (void)show:(BOOL)animated { - [self showAnimated:animated]; -} - -- (void)hide:(BOOL)animated { - [self hideAnimated:animated]; -} - -- (void)hide:(BOOL)animated afterDelay:(NSTimeInterval)delay { - [self hideAnimated:animated afterDelay:delay]; -} - -#pragma mark - Threading - -- (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated { - [self showAnimated:animated whileExecutingBlock:^{ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Warc-performSelector-leaks" - // Start executing the requested task - [target performSelector:method withObject:object]; -#pragma clang diagnostic pop - }]; -} - -- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block { - dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - [self showAnimated:animated whileExecutingBlock:block onQueue:queue completionBlock:NULL]; -} - -- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block completionBlock:(void (^)(void))completion { - dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - [self showAnimated:animated whileExecutingBlock:block onQueue:queue completionBlock:completion]; -} - -- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue { - [self showAnimated:animated whileExecutingBlock:block onQueue:queue completionBlock:NULL]; -} - -- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue completionBlock:(nullable MBProgressHUDCompletionBlock)completion { - self.taskInProgress = YES; - self.completionBlock = completion; - dispatch_async(queue, ^(void) { - block(); - dispatch_async(dispatch_get_main_queue(), ^(void) { - [self cleanUp]; - }); - }); - [self showAnimated:animated]; -} - -- (void)cleanUp { - self.taskInProgress = NO; - [self hideAnimated:self.useAnimation]; -} - -#pragma mark - Labels - -- (NSString *)labelText { - return self.label.text; -} - -- (void)setLabelText:(NSString *)labelText { - MBMainThreadAssert(); - self.label.text = labelText; -} - -- (UIFont *)labelFont { - return self.label.font; -} - -- (void)setLabelFont:(UIFont *)labelFont { - MBMainThreadAssert(); - self.label.font = labelFont; -} - -- (UIColor *)labelColor { - return self.label.textColor; -} - -- (void)setLabelColor:(UIColor *)labelColor { - MBMainThreadAssert(); - self.label.textColor = labelColor; -} - -- (NSString *)detailsLabelText { - return self.detailsLabel.text; -} - -- (void)setDetailsLabelText:(NSString *)detailsLabelText { - MBMainThreadAssert(); - self.detailsLabel.text = detailsLabelText; -} - -- (UIFont *)detailsLabelFont { - return self.detailsLabel.font; -} - -- (void)setDetailsLabelFont:(UIFont *)detailsLabelFont { - MBMainThreadAssert(); - self.detailsLabel.font = detailsLabelFont; -} - -- (UIColor *)detailsLabelColor { - return self.detailsLabel.textColor; -} - -- (void)setDetailsLabelColor:(UIColor *)detailsLabelColor { - MBMainThreadAssert(); - self.detailsLabel.textColor = detailsLabelColor; -} - -- (CGFloat)opacity { - return _opacity; -} - -- (void)setOpacity:(CGFloat)opacity { - MBMainThreadAssert(); - _opacity = opacity; -} - -- (UIColor *)color { - return self.bezelView.color; -} - -- (void)setColor:(UIColor *)color { - MBMainThreadAssert(); - self.bezelView.color = color; -} - -- (CGFloat)yOffset { - return self.offset.y; -} - -- (void)setYOffset:(CGFloat)yOffset { - MBMainThreadAssert(); - self.offset = CGPointMake(self.offset.x, yOffset); -} - -- (CGFloat)xOffset { - return self.offset.x; -} - -- (void)setXOffset:(CGFloat)xOffset { - MBMainThreadAssert(); - self.offset = CGPointMake(xOffset, self.offset.y); -} - -- (CGFloat)cornerRadius { - return self.bezelView.layer.cornerRadius; -} - -- (void)setCornerRadius:(CGFloat)cornerRadius { - MBMainThreadAssert(); - self.bezelView.layer.cornerRadius = cornerRadius; -} - -- (BOOL)dimBackground { - MBBackgroundView *backgroundView = self.backgroundView; - UIColor *dimmedColor = [UIColor colorWithWhite:0.f alpha:.2f]; - return backgroundView.style == MBProgressHUDBackgroundStyleSolidColor && [backgroundView.color isEqual:dimmedColor]; -} - -- (void)setDimBackground:(BOOL)dimBackground { - MBMainThreadAssert(); - self.backgroundView.style = MBProgressHUDBackgroundStyleSolidColor; - self.backgroundView.color = dimBackground ? [UIColor colorWithWhite:0.f alpha:.2f] : [UIColor clearColor]; -} - -- (CGSize)size { - return self.bezelView.frame.size; -} - -- (UIColor *)activityIndicatorColor { - return _activityIndicatorColor; -} - -- (void)setActivityIndicatorColor:(UIColor *)activityIndicatorColor { - if (activityIndicatorColor != _activityIndicatorColor) { - _activityIndicatorColor = activityIndicatorColor; - UIActivityIndicatorView *indicator = (UIActivityIndicatorView *)self.indicator; - if ([indicator isKindOfClass:[UIActivityIndicatorView class]]) { - [indicator setColor:activityIndicatorColor]; - } - } -} - -@end - -@implementation MBProgressHUDRoundedButton - -#pragma mark - Lifecycle - -- (instancetype)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - CALayer *layer = self.layer; - layer.borderWidth = 1.f; - } - return self; -} - -#pragma mark - Layout - -- (void)layoutSubviews { - [super layoutSubviews]; - // Fully rounded corners - CGFloat height = CGRectGetHeight(self.bounds); - self.layer.cornerRadius = ceil(height / 2.f); -} - -- (CGSize)intrinsicContentSize { - // Only show if we have associated control events - if (self.allControlEvents == 0) return CGSizeZero; - CGSize size = [super intrinsicContentSize]; - // Add some side padding - size.width += 20.f; - return size; -} - -#pragma mark - Color - -- (void)setTitleColor:(UIColor *)color forState:(UIControlState)state { - [super setTitleColor:color forState:state]; - // Update related colors - [self setHighlighted:self.highlighted]; - self.layer.borderColor = color.CGColor; -} - -- (void)setHighlighted:(BOOL)highlighted { - [super setHighlighted:highlighted]; - UIColor *baseColor = [self titleColorForState:UIControlStateSelected]; - self.backgroundColor = highlighted ? [baseColor colorWithAlphaComponent:0.1f] : [UIColor clearColor]; -} - -@end diff --git a/iOS_Tips/Pods/MBProgressHUD/README.mdown b/iOS_Tips/Pods/MBProgressHUD/README.mdown deleted file mode 100644 index 21ba843b..00000000 --- a/iOS_Tips/Pods/MBProgressHUD/README.mdown +++ /dev/null @@ -1,126 +0,0 @@ -# MBProgressHUD - -[![Build Status](https://travis-ci.org/matej/MBProgressHUD.svg?branch=master)](https://travis-ci.org/matej/MBProgressHUD) [![codecov.io](https://codecov.io/github/matej/MBProgressHUD/coverage.svg?branch=master)](https://codecov.io/github/matej/MBProgressHUD?branch=master) - [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) [![CocoaPods compatible](https://img.shields.io/cocoapods/v/MBProgressHUD.svg?style=flat)](https://cocoapods.org/pods/MBProgressHUD) [![License: MIT](https://img.shields.io/cocoapods/l/MBProgressHUD.svg?style=flat)](http://opensource.org/licenses/MIT) - -`MBProgressHUD` is an iOS drop-in class that displays a translucent HUD with an indicator and/or labels while work is being done in a background thread. The HUD is meant as a replacement for the undocumented, private `UIKit` `UIProgressHUD` with some additional features. - -[![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/1-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/1.png) -[![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/2-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/2.png) -[![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/3-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/3.png) -[![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/4-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/4.png) -[![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/5-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/5.png) -[![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/6-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/6.png) -[![](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/7-small.png)](https://raw.githubusercontent.com/wiki/matej/MBProgressHUD/Screenshots/7.png) - -**NOTE:** The class has recently undergone a major rewrite. The old version is available in the [legacy](https://github.com/jdg/MBProgressHUD/tree/legacy) branch, should you need it. - -## Requirements - -`MBProgressHUD` works on iOS 6+ and requires ARC to build. It depends on the following Apple frameworks, which should already be included with most Xcode templates: - -* Foundation.framework -* UIKit.framework -* CoreGraphics.framework - -You will need the latest developer tools in order to build `MBProgressHUD`. Old Xcode versions might work, but compatibility will not be explicitly maintained. - -## Adding MBProgressHUD to your project - -### CocoaPods - -[CocoaPods](http://cocoapods.org) is the recommended way to add MBProgressHUD to your project. - -1. Add a pod entry for MBProgressHUD to your Podfile `pod 'MBProgressHUD', '~> 1.1.0'` -2. Install the pod(s) by running `pod install`. -3. Include MBProgressHUD wherever you need it with `#import "MBProgressHUD.h"`. - -### Carthage - -1. Add MBProgressHUD to your Cartfile. e.g., `github "jdg/MBProgressHUD" ~> 1.1.0` -2. Run `carthage update` -3. Follow the rest of the [standard Carthage installation instructions](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) to add MBProgressHUD to your project. - -### Source files - -Alternatively you can directly add the `MBProgressHUD.h` and `MBProgressHUD.m` source files to your project. - -1. Download the [latest code version](https://github.com/matej/MBProgressHUD/archive/master.zip) or add the repository as a git submodule to your git-tracked project. -2. Open your project in Xcode, then drag and drop `MBProgressHUD.h` and `MBProgressHUD.m` onto your project (use the "Product Navigator view"). Make sure to select Copy items when asked if you extracted the code archive outside of your project. -3. Include MBProgressHUD wherever you need it with `#import "MBProgressHUD.h"`. - -### Static library - -You can also add MBProgressHUD as a static library to your project or workspace. - -1. Download the [latest code version](https://github.com/matej/MBProgressHUD/downloads) or add the repository as a git submodule to your git-tracked project. -2. Open your project in Xcode, then drag and drop `MBProgressHUD.xcodeproj` onto your project or workspace (use the "Product Navigator view"). -3. Select your target and go to the Build phases tab. In the Link Binary With Libraries section select the add button. On the sheet find and add `libMBProgressHUD.a`. You might also need to add `MBProgressHUD` to the Target Dependencies list. -4. Include MBProgressHUD wherever you need it with `#import `. - -## Usage - -The main guideline you need to follow when dealing with MBProgressHUD while running long-running tasks is keeping the main thread work-free, so the UI can be updated promptly. The recommended way of using MBProgressHUD is therefore to set it up on the main thread and then spinning the task, that you want to perform, off onto a new thread. - -```objective-c -[MBProgressHUD showHUDAddedTo:self.view animated:YES]; -dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ - // Do something... - dispatch_async(dispatch_get_main_queue(), ^{ - [MBProgressHUD hideHUDForView:self.view animated:YES]; - }); -}); -``` - -You can add the HUD on any view or window. It is however a good idea to avoid adding the HUD to certain `UIKit` views with complex view hierarchies - like `UITableView` or `UICollectionView`. Those can mutate their subviews in unexpected ways and thereby break HUD display. - -If you need to configure the HUD you can do this by using the MBProgressHUD reference that showHUDAddedTo:animated: returns. - -```objective-c -MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; -hud.mode = MBProgressHUDModeAnnularDeterminate; -hud.label.text = @"Loading"; -[self doSomethingInBackgroundWithProgressCallback:^(float progress) { - hud.progress = progress; -} completionCallback:^{ - [hud hideAnimated:YES]; -}]; -``` - -You can also use a `NSProgress` object and MBProgressHUD will update itself when there is progress reported through that object. - -```objective-c -MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; -hud.mode = MBProgressHUDModeAnnularDeterminate; -hud.label.text = @"Loading"; -NSProgress *progress = [self doSomethingInBackgroundCompletion:^{ - [hud hideAnimated:YES]; -}]; -hud.progressObject = progress; -``` - -Keep in mind that UI updates, inclining calls to MBProgressHUD should always be done on the main thread. - -If you need to run your long-running task in the main thread, you should perform it with a slight delay, so UIKit will have enough time to update the UI (i.e., draw the HUD) before you block the main thread with your task. - -```objective-c -[MBProgressHUD showHUDAddedTo:self.view animated:YES]; -dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0.01 * NSEC_PER_SEC); -dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ - // Do something... - [MBProgressHUD hideHUDForView:self.view animated:YES]; -}); -``` - -You should be aware that any HUD updates issued inside the above block won't be displayed until the block completes. - -For more examples, including how to use MBProgressHUD with asynchronous operations such as NSURLConnection, take a look at the bundled demo project. Extensive API documentation is provided in the header file (MBProgressHUD.h). - - -## License - -This code is distributed under the terms and conditions of the [MIT license](LICENSE). - -## Change-log - -A brief summary of each MBProgressHUD release can be found in the [CHANGELOG](CHANGELOG.mdown). diff --git a/iOS_Tips/Pods/MLeaksFinder/LICENSE b/iOS_Tips/Pods/MLeaksFinder/LICENSE deleted file mode 100644 index 0739a90e..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2016 Zeposhe - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/MLeakedObjectProxy.h b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/MLeakedObjectProxy.h deleted file mode 100644 index 94898394..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/MLeakedObjectProxy.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// MLeakedObjectProxy.h -// MLeaksFinder -// -// Created by 佘泽坡 on 7/15/16. -// Copyright © 2016 zeposhe. All rights reserved. -// - -#import - -@interface MLeakedObjectProxy : NSObject - -+ (BOOL)isAnyObjectLeakedAtPtrs:(NSSet *)ptrs; -+ (void)addLeakedObject:(id)object; - -@end diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/MLeakedObjectProxy.m b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/MLeakedObjectProxy.m deleted file mode 100644 index d25d9acd..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/MLeakedObjectProxy.m +++ /dev/null @@ -1,141 +0,0 @@ -// -// MLeakedObjectProxy.m -// MLeaksFinder -// -// Created by 佘泽坡 on 7/15/16. -// Copyright © 2016 zeposhe. All rights reserved. -// - -#import "MLeakedObjectProxy.h" -#import "MLeaksFinder.h" -#import "MLeaksMessenger.h" -#import "NSObject+MemoryLeak.h" -#import -#import - -#if _INTERNAL_MLF_RC_ENABLED -#import -#endif - -static NSMutableSet *leakedObjectPtrs; - -@interface MLeakedObjectProxy () -@property (nonatomic, weak) id object; -@property (nonatomic, strong) NSNumber *objectPtr; -@property (nonatomic, strong) NSArray *viewStack; -@end - -@implementation MLeakedObjectProxy - -+ (BOOL)isAnyObjectLeakedAtPtrs:(NSSet *)ptrs { - NSAssert([NSThread isMainThread], @"Must be in main thread."); - - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - leakedObjectPtrs = [[NSMutableSet alloc] init]; - }); - - if (!ptrs.count) { - return NO; - } - if ([leakedObjectPtrs intersectsSet:ptrs]) { - return YES; - } else { - return NO; - } -} - -+ (void)addLeakedObject:(id)object { - NSAssert([NSThread isMainThread], @"Must be in main thread."); - - MLeakedObjectProxy *proxy = [[MLeakedObjectProxy alloc] init]; - proxy.object = object; - proxy.objectPtr = @((uintptr_t)object); - proxy.viewStack = [object viewStack]; - static const void *const kLeakedObjectProxyKey = &kLeakedObjectProxyKey; - objc_setAssociatedObject(object, kLeakedObjectProxyKey, proxy, OBJC_ASSOCIATION_RETAIN); - - [leakedObjectPtrs addObject:proxy.objectPtr]; - -#if _INTERNAL_MLF_RC_ENABLED - [MLeaksMessenger alertWithTitle:@"Memory Leak" - message:[NSString stringWithFormat:@"%@", proxy.viewStack] - delegate:proxy - additionalButtonTitle:@"Retain Cycle"]; -#else - [MLeaksMessenger alertWithTitle:@"Memory Leak" - message:[NSString stringWithFormat:@"%@", proxy.viewStack]]; -#endif -} - -- (void)dealloc { - NSNumber *objectPtr = _objectPtr; - NSArray *viewStack = _viewStack; - dispatch_async(dispatch_get_main_queue(), ^{ - [leakedObjectPtrs removeObject:objectPtr]; - [MLeaksMessenger alertWithTitle:@"Object Deallocated" - message:[NSString stringWithFormat:@"%@", viewStack]]; - }); -} - -#pragma mark - UIAlertViewDelegate - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { - if (!buttonIndex) { - return; - } - - id object = self.object; - if (!object) { - return; - } - -#if _INTERNAL_MLF_RC_ENABLED - dispatch_async(dispatch_get_global_queue(0, 0), ^{ - FBRetainCycleDetector *detector = [FBRetainCycleDetector new]; - [detector addCandidate:self.object]; - NSSet *retainCycles = [detector findRetainCyclesWithMaxCycleLength:20]; - - BOOL hasFound = NO; - for (NSArray *retainCycle in retainCycles) { - NSInteger index = 0; - for (FBObjectiveCGraphElement *element in retainCycle) { - if (element.object == object) { - NSArray *shiftedRetainCycle = [self shiftArray:retainCycle toIndex:index]; - - dispatch_async(dispatch_get_main_queue(), ^{ - [MLeaksMessenger alertWithTitle:@"Retain Cycle" - message:[NSString stringWithFormat:@"%@", shiftedRetainCycle]]; - }); - hasFound = YES; - break; - } - - ++index; - } - if (hasFound) { - break; - } - } - if (!hasFound) { - dispatch_async(dispatch_get_main_queue(), ^{ - [MLeaksMessenger alertWithTitle:@"Retain Cycle" - message:@"Fail to find a retain cycle"]; - }); - } - }); -#endif -} - -- (NSArray *)shiftArray:(NSArray *)array toIndex:(NSInteger)index { - if (index == 0) { - return array; - } - - NSRange range = NSMakeRange(index, array.count - index); - NSMutableArray *result = [[array subarrayWithRange:range] mutableCopy]; - [result addObjectsFromArray:[array subarrayWithRange:NSMakeRange(0, index)]]; - return result; -} - -@end diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/MLeaksFinder.h b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/MLeaksFinder.h deleted file mode 100644 index a46760c3..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/MLeaksFinder.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// MLeaksFinder.h -// MLeaksFinder -// -// Created by zeposhe on 12/12/15. -// Copyright © 2015 zeposhe. All rights reserved. -// - -#import "NSObject+MemoryLeak.h" - -//#define MEMORY_LEAKS_FINDER_ENABLED 0 - -#ifdef MEMORY_LEAKS_FINDER_ENABLED -#define _INTERNAL_MLF_ENABLED MEMORY_LEAKS_FINDER_ENABLED -#else -#define _INTERNAL_MLF_ENABLED DEBUG -#endif - -//#define MEMORY_LEAKS_FINDER_RETAIN_CYCLE_ENABLED 1 - -#ifdef MEMORY_LEAKS_FINDER_RETAIN_CYCLE_ENABLED -#define _INTERNAL_MLF_RC_ENABLED MEMORY_LEAKS_FINDER_RETAIN_CYCLE_ENABLED -#elif COCOAPODS -#define _INTERNAL_MLF_RC_ENABLED COCOAPODS -#endif diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/MLeaksMessenger.h b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/MLeaksMessenger.h deleted file mode 100644 index c4d0147d..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/MLeaksMessenger.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// MLeaksMessenger.h -// MLeaksFinder -// -// Created by 佘泽坡 on 7/17/16. -// Copyright © 2016 zeposhe. All rights reserved. -// - -#import -#import - -@interface MLeaksMessenger : NSObject - -+ (void)alertWithTitle:(NSString *)title message:(NSString *)message; -+ (void)alertWithTitle:(NSString *)title - message:(NSString *)message - delegate:(id)delegate - additionalButtonTitle:(NSString *)additionalButtonTitle; - -@end diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/MLeaksMessenger.m b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/MLeaksMessenger.m deleted file mode 100644 index 561b4f40..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/MLeaksMessenger.m +++ /dev/null @@ -1,35 +0,0 @@ -// -// MLeaksMessenger.m -// MLeaksFinder -// -// Created by 佘泽坡 on 7/17/16. -// Copyright © 2016 zeposhe. All rights reserved. -// - -#import "MLeaksMessenger.h" - -static __weak UIAlertView *alertView; - -@implementation MLeaksMessenger - -+ (void)alertWithTitle:(NSString *)title message:(NSString *)message { - [self alertWithTitle:title message:message delegate:nil additionalButtonTitle:nil]; -} - -+ (void)alertWithTitle:(NSString *)title - message:(NSString *)message - delegate:(id)delegate - additionalButtonTitle:(NSString *)additionalButtonTitle { - [alertView dismissWithClickedButtonIndex:0 animated:NO]; - UIAlertView *alertViewTemp = [[UIAlertView alloc] initWithTitle:title - message:message - delegate:delegate - cancelButtonTitle:@"OK" - otherButtonTitles:additionalButtonTitle, nil]; - [alertViewTemp show]; - alertView = alertViewTemp; - - NSLog(@"%@: %@", title, message); -} - -@end diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/NSObject+MemoryLeak.h b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/NSObject+MemoryLeak.h deleted file mode 100644 index 822df2c6..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/NSObject+MemoryLeak.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// NSObject+MemoryLeak.h -// MLeaksFinder -// -// Created by zeposhe on 12/12/15. -// Copyright © 2015 zeposhe. All rights reserved. -// - -#import - -#define MLCheck(TARGET) [self willReleaseObject:(TARGET) relationship:@#TARGET]; - -@interface NSObject (MemoryLeak) - -- (BOOL)willDealloc; -- (void)willReleaseObject:(id)object relationship:(NSString *)relationship; - -- (void)willReleaseChild:(id)child; -- (void)willReleaseChildren:(NSArray *)children; - -- (NSArray *)viewStack; - -+ (void)addClassNamesToWhitelist:(NSArray *)classNames; - -+ (void)swizzleSEL:(SEL)originalSEL withSEL:(SEL)swizzledSEL; - -@end diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/NSObject+MemoryLeak.m b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/NSObject+MemoryLeak.m deleted file mode 100644 index 0e0ec91c..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/NSObject+MemoryLeak.m +++ /dev/null @@ -1,169 +0,0 @@ -// -// NSObject+MemoryLeak.m -// MLeaksFinder -// -// Created by zeposhe on 12/12/15. -// Copyright © 2015 zeposhe. All rights reserved. -// - -#import "NSObject+MemoryLeak.h" -#import "MLeakedObjectProxy.h" -#import "MLeaksFinder.h" -#import -#import - -#if _INTERNAL_MLF_RC_ENABLED -#import -#endif - -static const void *const kViewStackKey = &kViewStackKey; -static const void *const kParentPtrsKey = &kParentPtrsKey; -const void *const kLatestSenderKey = &kLatestSenderKey; - -@implementation NSObject (MemoryLeak) - -- (BOOL)willDealloc { - NSString *className = NSStringFromClass([self class]); - if ([[NSObject classNamesWhitelist] containsObject:className]) - return NO; - - NSNumber *senderPtr = objc_getAssociatedObject([UIApplication sharedApplication], kLatestSenderKey); - if ([senderPtr isEqualToNumber:@((uintptr_t)self)]) - return NO; - - __weak id weakSelf = self; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - __strong id strongSelf = weakSelf; - [strongSelf assertNotDealloc]; - }); - - return YES; -} - -- (void)assertNotDealloc { - if ([MLeakedObjectProxy isAnyObjectLeakedAtPtrs:[self parentPtrs]]) { - return; - } - [MLeakedObjectProxy addLeakedObject:self]; - - NSString *className = NSStringFromClass([self class]); - NSLog(@"Possibly Memory Leak.\nIn case that %@ should not be dealloced, override -willDealloc in %@ by returning NO.\nView-ViewController stack: %@", className, className, [self viewStack]); -} - -- (void)willReleaseObject:(id)object relationship:(NSString *)relationship { - if ([relationship hasPrefix:@"self"]) { - relationship = [relationship stringByReplacingCharactersInRange:NSMakeRange(0, 4) withString:@""]; - } - NSString *className = NSStringFromClass([object class]); - className = [NSString stringWithFormat:@"%@(%@), ", relationship, className]; - - [object setViewStack:[[self viewStack] arrayByAddingObject:className]]; - [object setParentPtrs:[[self parentPtrs] setByAddingObject:@((uintptr_t)object)]]; - [object willDealloc]; -} - -- (void)willReleaseChild:(id)child { - if (!child) { - return; - } - - [self willReleaseChildren:@[ child ]]; -} - -- (void)willReleaseChildren:(NSArray *)children { - NSArray *viewStack = [self viewStack]; - NSSet *parentPtrs = [self parentPtrs]; - for (id child in children) { - NSString *className = NSStringFromClass([child class]); - [child setViewStack:[viewStack arrayByAddingObject:className]]; - [child setParentPtrs:[parentPtrs setByAddingObject:@((uintptr_t)child)]]; - [child willDealloc]; - } -} - -- (NSArray *)viewStack { - NSArray *viewStack = objc_getAssociatedObject(self, kViewStackKey); - if (viewStack) { - return viewStack; - } - - NSString *className = NSStringFromClass([self class]); - return @[ className ]; -} - -- (void)setViewStack:(NSArray *)viewStack { - objc_setAssociatedObject(self, kViewStackKey, viewStack, OBJC_ASSOCIATION_RETAIN); -} - -- (NSSet *)parentPtrs { - NSSet *parentPtrs = objc_getAssociatedObject(self, kParentPtrsKey); - if (!parentPtrs) { - parentPtrs = [[NSSet alloc] initWithObjects:@((uintptr_t)self), nil]; - } - return parentPtrs; -} - -- (void)setParentPtrs:(NSSet *)parentPtrs { - objc_setAssociatedObject(self, kParentPtrsKey, parentPtrs, OBJC_ASSOCIATION_RETAIN); -} - -+ (NSMutableSet *)classNamesWhitelist { - static NSMutableSet *whitelist = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - whitelist = [NSMutableSet setWithObjects: - @"UIFieldEditor", // UIAlertControllerTextField - @"UINavigationBar", - @"_UIAlertControllerActionView", - @"_UIVisualEffectBackdropView", - nil]; - - // System's bug since iOS 10 and not fixed yet up to this ci. - NSString *systemVersion = [UIDevice currentDevice].systemVersion; - if ([systemVersion compare:@"10.0" options:NSNumericSearch] != NSOrderedAscending) { - [whitelist addObject:@"UISwitch"]; - } - }); - return whitelist; -} - -+ (void)addClassNamesToWhitelist:(NSArray *)classNames { - [[self classNamesWhitelist] addObjectsFromArray:classNames]; -} - -+ (void)swizzleSEL:(SEL)originalSEL withSEL:(SEL)swizzledSEL { -#if _INTERNAL_MLF_ENABLED - -#if _INTERNAL_MLF_RC_ENABLED - // Just find a place to set up FBRetainCycleDetector. - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - dispatch_async(dispatch_get_main_queue(), ^{ - [FBAssociationManager hook]; - }); - }); -#endif - - Class class = [self class]; - - Method originalMethod = class_getInstanceMethod(class, originalSEL); - Method swizzledMethod = class_getInstanceMethod(class, swizzledSEL); - - BOOL didAddMethod = - class_addMethod(class, - originalSEL, - method_getImplementation(swizzledMethod), - method_getTypeEncoding(swizzledMethod)); - - if (didAddMethod) { - class_replaceMethod(class, - swizzledSEL, - method_getImplementation(originalMethod), - method_getTypeEncoding(originalMethod)); - } else { - method_exchangeImplementations(originalMethod, swizzledMethod); - } -#endif -} - -@end diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIApplication+MemoryLeak.h b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIApplication+MemoryLeak.h deleted file mode 100644 index d5711a04..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIApplication+MemoryLeak.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// UIApplication+MemoryLeak.h -// MLeaksFinder -// -// Created by 佘泽坡 on 5/11/16. -// Copyright © 2016 zeposhe. All rights reserved. -// - -#import -#import "MLeaksFinder.h" - -#if _INTERNAL_MLF_ENABLED - -@interface UIApplication (MemoryLeak) - -@end - -#endif diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIApplication+MemoryLeak.m b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIApplication+MemoryLeak.m deleted file mode 100644 index 3079aad3..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIApplication+MemoryLeak.m +++ /dev/null @@ -1,34 +0,0 @@ -// -// UIApplication+MemoryLeak.m -// MLeaksFinder -// -// Created by 佘泽坡 on 5/11/16. -// Copyright © 2016 zeposhe. All rights reserved. -// - -#import "UIApplication+MemoryLeak.h" -#import "NSObject+MemoryLeak.h" -#import - -#if _INTERNAL_MLF_ENABLED - -extern const void *const kLatestSenderKey; - -@implementation UIApplication (MemoryLeak) - -+ (void)load { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - [self swizzleSEL:@selector(sendAction:to:from:forEvent:) withSEL:@selector(swizzled_sendAction:to:from:forEvent:)]; - }); -} - -- (BOOL)swizzled_sendAction:(SEL)action to:(id)target from:(id)sender forEvent:(UIEvent *)event { - objc_setAssociatedObject(self, kLatestSenderKey, @((uintptr_t)sender), OBJC_ASSOCIATION_RETAIN); - - return [self swizzled_sendAction:action to:target from:sender forEvent:event]; -} - -@end - -#endif diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UINavigationController+MemoryLeak.h b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UINavigationController+MemoryLeak.h deleted file mode 100644 index 8d201699..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UINavigationController+MemoryLeak.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// UINavigationController+MemoryLeak.h -// MLeaksFinder -// -// Created by zeposhe on 12/12/15. -// Copyright © 2015 zeposhe. All rights reserved. -// - -#import -#import "MLeaksFinder.h" - -#if _INTERNAL_MLF_ENABLED - -@interface UINavigationController (MemoryLeak) - -@end - -#endif diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UINavigationController+MemoryLeak.m b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UINavigationController+MemoryLeak.m deleted file mode 100644 index 94e2add1..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UINavigationController+MemoryLeak.m +++ /dev/null @@ -1,95 +0,0 @@ -// -// UINavigationController+MemoryLeak.m -// MLeaksFinder -// -// Created by zeposhe on 12/12/15. -// Copyright © 2015 zeposhe. All rights reserved. -// - -#import "UINavigationController+MemoryLeak.h" -#import "NSObject+MemoryLeak.h" -#import - -#if _INTERNAL_MLF_ENABLED - -static const void *const kPoppedDetailVCKey = &kPoppedDetailVCKey; - -@implementation UINavigationController (MemoryLeak) - -+ (void)load { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - [self swizzleSEL:@selector(pushViewController:animated:) withSEL:@selector(swizzled_pushViewController:animated:)]; - [self swizzleSEL:@selector(popViewControllerAnimated:) withSEL:@selector(swizzled_popViewControllerAnimated:)]; - [self swizzleSEL:@selector(popToViewController:animated:) withSEL:@selector(swizzled_popToViewController:animated:)]; - [self swizzleSEL:@selector(popToRootViewControllerAnimated:) withSEL:@selector(swizzled_popToRootViewControllerAnimated:)]; - }); -} - -- (void)swizzled_pushViewController:(UIViewController *)viewController animated:(BOOL)animated { - if (self.splitViewController) { - id detailViewController = objc_getAssociatedObject(self, kPoppedDetailVCKey); - if ([detailViewController isKindOfClass:[UIViewController class]]) { - [detailViewController willDealloc]; - objc_setAssociatedObject(self, kPoppedDetailVCKey, nil, OBJC_ASSOCIATION_RETAIN); - } - } - - [self swizzled_pushViewController:viewController animated:animated]; -} - -- (UIViewController *)swizzled_popViewControllerAnimated:(BOOL)animated { - UIViewController *poppedViewController = [self swizzled_popViewControllerAnimated:animated]; - - if (!poppedViewController) { - return nil; - } - - // Detail VC in UISplitViewController is not dealloced until another detail VC is shown - if (self.splitViewController && - self.splitViewController.viewControllers.firstObject == self && - self.splitViewController == poppedViewController.splitViewController) { - objc_setAssociatedObject(self, kPoppedDetailVCKey, poppedViewController, OBJC_ASSOCIATION_RETAIN); - return poppedViewController; - } - - // VC is not dealloced until disappear when popped using a left-edge swipe gesture - extern const void *const kHasBeenPoppedKey; - objc_setAssociatedObject(poppedViewController, kHasBeenPoppedKey, @(YES), OBJC_ASSOCIATION_RETAIN); - - return poppedViewController; -} - -- (NSArray *)swizzled_popToViewController:(UIViewController *)viewController animated:(BOOL)animated { - NSArray *poppedViewControllers = [self swizzled_popToViewController:viewController animated:animated]; - - for (UIViewController *viewController in poppedViewControllers) { - [viewController willDealloc]; - } - - return poppedViewControllers; -} - -- (NSArray *)swizzled_popToRootViewControllerAnimated:(BOOL)animated { - NSArray *poppedViewControllers = [self swizzled_popToRootViewControllerAnimated:animated]; - - for (UIViewController *viewController in poppedViewControllers) { - [viewController willDealloc]; - } - - return poppedViewControllers; -} - -- (BOOL)willDealloc { - if (![super willDealloc]) { - return NO; - } - - [self willReleaseChildren:self.viewControllers]; - - return YES; -} - -@end - -#endif diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIPageViewController+MemoryLeak.h b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIPageViewController+MemoryLeak.h deleted file mode 100644 index c86b9009..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIPageViewController+MemoryLeak.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// UIPageViewController+MemoryLeak.h -// MLeaksFinder -// -// Created by zeposhe on 12/12/15. -// Copyright © 2015 zeposhe. All rights reserved. -// - -#import -#import "MLeaksFinder.h" - -#if _INTERNAL_MLF_ENABLED - -@interface UIPageViewController (MemoryLeak) - -@end - -#endif diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIPageViewController+MemoryLeak.m b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIPageViewController+MemoryLeak.m deleted file mode 100644 index be088cc2..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIPageViewController+MemoryLeak.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// UIPageViewController+MemoryLeak.m -// MLeaksFinder -// -// Created by zeposhe on 12/12/15. -// Copyright © 2015 zeposhe. All rights reserved. -// - -#import "UIPageViewController+MemoryLeak.h" -#import "NSObject+MemoryLeak.h" - -#if _INTERNAL_MLF_ENABLED - -@implementation UIPageViewController (MemoryLeak) - -- (BOOL)willDealloc { - if (![super willDealloc]) { - return NO; - } - - [self willReleaseChildren:self.viewControllers]; - - return YES; -} - -@end - -#endif diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UISplitViewController+MemoryLeak.h b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UISplitViewController+MemoryLeak.h deleted file mode 100644 index 2fe868d1..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UISplitViewController+MemoryLeak.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// UISplitViewController+MemoryLeak.h -// MLeaksFinder -// -// Created by zeposhe on 12/12/15. -// Copyright © 2015 zeposhe. All rights reserved. -// - -#import -#import "MLeaksFinder.h" - -#if _INTERNAL_MLF_ENABLED - -@interface UISplitViewController (MemoryLeak) - -@end - -#endif diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UISplitViewController+MemoryLeak.m b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UISplitViewController+MemoryLeak.m deleted file mode 100644 index 5143c139..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UISplitViewController+MemoryLeak.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// UISplitViewController+MemoryLeak.m -// MLeaksFinder -// -// Created by zeposhe on 12/12/15. -// Copyright © 2015 zeposhe. All rights reserved. -// - -#import "UISplitViewController+MemoryLeak.h" -#import "NSObject+MemoryLeak.h" - -#if _INTERNAL_MLF_ENABLED - -@implementation UISplitViewController (MemoryLeak) - -- (BOOL)willDealloc { - if (![super willDealloc]) { - return NO; - } - - [self willReleaseChildren:self.viewControllers]; - - return YES; -} - -@end - -#endif diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UITabBarController+MemoryLeak.h b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UITabBarController+MemoryLeak.h deleted file mode 100644 index 561ab41a..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UITabBarController+MemoryLeak.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// UITabBarController+MemoryLeak.h -// MLeaksFinder -// -// Created by zeposhe on 12/12/15. -// Copyright © 2015 zeposhe. All rights reserved. -// - -#import -#import "MLeaksFinder.h" - -#if _INTERNAL_MLF_ENABLED - -@interface UITabBarController (MemoryLeak) - -@end - -#endif diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UITabBarController+MemoryLeak.m b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UITabBarController+MemoryLeak.m deleted file mode 100644 index b9b6e243..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UITabBarController+MemoryLeak.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// UITabBarController+MemoryLeak.m -// MLeaksFinder -// -// Created by zeposhe on 12/12/15. -// Copyright © 2015 zeposhe. All rights reserved. -// - -#import "UITabBarController+MemoryLeak.h" -#import "NSObject+MemoryLeak.h" - -#if _INTERNAL_MLF_ENABLED - -@implementation UITabBarController (MemoryLeak) - -- (BOOL)willDealloc { - if (![super willDealloc]) { - return NO; - } - - [self willReleaseChildren:self.viewControllers]; - - return YES; -} - -@end - -#endif diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UITouch+MemoryLeak.h b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UITouch+MemoryLeak.h deleted file mode 100644 index 1f89c914..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UITouch+MemoryLeak.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// UITouch+MemoryLeak.h -// MLeaksFinder -// -// Created by 佘泽坡 on 8/31/16. -// Copyright © 2016 zeposhe. All rights reserved. -// - -#import -#import "MLeaksFinder.h" - -#if _INTERNAL_MLF_ENABLED - -@interface UITouch (MemoryLeak) - -@end - -#endif diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UITouch+MemoryLeak.m b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UITouch+MemoryLeak.m deleted file mode 100644 index 807ba8ad..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UITouch+MemoryLeak.m +++ /dev/null @@ -1,38 +0,0 @@ -// -// UITouch+MemoryLeak.m -// MLeaksFinder -// -// Created by 佘泽坡 on 8/31/16. -// Copyright © 2016 zeposhe. All rights reserved. -// - -#import "UITouch+MemoryLeak.h" -#import - -#if _INTERNAL_MLF_ENABLED - -extern const void *const kLatestSenderKey; - -@implementation UITouch (MemoryLeak) - -+ (void)load { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - [self swizzleSEL:@selector(setView:) withSEL:@selector(swizzled_setView:)]; - }); -} - -- (void)swizzled_setView:(UIView *)view { - [self swizzled_setView:view]; - - if (view) { - objc_setAssociatedObject([UIApplication sharedApplication], - kLatestSenderKey, - @((uintptr_t)view), - OBJC_ASSOCIATION_RETAIN); - } -} - -@end - -#endif diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIView+MemoryLeak.h b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIView+MemoryLeak.h deleted file mode 100644 index 908762d3..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIView+MemoryLeak.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// UIView+MemoryLeak.h -// MLeaksFinder -// -// Created by zeposhe on 12/12/15. -// Copyright © 2015 zeposhe. All rights reserved. -// - -#import -#import "MLeaksFinder.h" - -#if _INTERNAL_MLF_ENABLED - -@interface UIView (MemoryLeak) - -@end - -#endif diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIView+MemoryLeak.m b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIView+MemoryLeak.m deleted file mode 100644 index 23ef50e7..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIView+MemoryLeak.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// UIView+MemoryLeak.m -// MLeaksFinder -// -// Created by zeposhe on 12/12/15. -// Copyright © 2015 zeposhe. All rights reserved. -// - -#import "UIView+MemoryLeak.h" -#import "NSObject+MemoryLeak.h" - -#if _INTERNAL_MLF_ENABLED - -@implementation UIView (MemoryLeak) - -- (BOOL)willDealloc { - if (![super willDealloc]) { - return NO; - } - - [self willReleaseChildren:self.subviews]; - - return YES; -} - -@end - -#endif diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIViewController+MemoryLeak.h b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIViewController+MemoryLeak.h deleted file mode 100644 index b646a3eb..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIViewController+MemoryLeak.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// UIViewController+MemoryLeak.h -// MLeaksFinder -// -// Created by zeposhe on 12/12/15. -// Copyright © 2015 zeposhe. All rights reserved. -// - -#import -#import "MLeaksFinder.h" - -#if _INTERNAL_MLF_ENABLED - -@interface UIViewController (MemoryLeak) - -@end - -#endif diff --git a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIViewController+MemoryLeak.m b/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIViewController+MemoryLeak.m deleted file mode 100644 index f7dee545..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/MLeaksFinder/UIViewController+MemoryLeak.m +++ /dev/null @@ -1,72 +0,0 @@ -// -// UIViewController+MemoryLeak.m -// MLeaksFinder -// -// Created by zeposhe on 12/12/15. -// Copyright © 2015 zeposhe. All rights reserved. -// - -#import "UIViewController+MemoryLeak.h" -#import "NSObject+MemoryLeak.h" -#import - -#if _INTERNAL_MLF_ENABLED - -const void *const kHasBeenPoppedKey = &kHasBeenPoppedKey; - -@implementation UIViewController (MemoryLeak) - -+ (void)load { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - [self swizzleSEL:@selector(viewDidDisappear:) withSEL:@selector(swizzled_viewDidDisappear:)]; - [self swizzleSEL:@selector(viewWillAppear:) withSEL:@selector(swizzled_viewWillAppear:)]; - [self swizzleSEL:@selector(dismissViewControllerAnimated:completion:) withSEL:@selector(swizzled_dismissViewControllerAnimated:completion:)]; - }); -} - -- (void)swizzled_viewDidDisappear:(BOOL)animated { - [self swizzled_viewDidDisappear:animated]; - - if ([objc_getAssociatedObject(self, kHasBeenPoppedKey) boolValue]) { - [self willDealloc]; - } -} - -- (void)swizzled_viewWillAppear:(BOOL)animated { - [self swizzled_viewWillAppear:animated]; - - objc_setAssociatedObject(self, kHasBeenPoppedKey, @(NO), OBJC_ASSOCIATION_RETAIN); -} - -- (void)swizzled_dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion { - [self swizzled_dismissViewControllerAnimated:flag completion:completion]; - - UIViewController *dismissedViewController = self.presentedViewController; - if (!dismissedViewController && self.presentingViewController) { - dismissedViewController = self; - } - - if (!dismissedViewController) return; - - [dismissedViewController willDealloc]; -} - -- (BOOL)willDealloc { - if (![super willDealloc]) { - return NO; - } - - [self willReleaseChildren:self.childViewControllers]; - [self willReleaseChild:self.presentedViewController]; - - if (self.isViewLoaded) { - [self willReleaseChild:self.view]; - } - - return YES; -} - -@end - -#endif diff --git a/iOS_Tips/Pods/MLeaksFinder/README-CN.md b/iOS_Tips/Pods/MLeaksFinder/README-CN.md deleted file mode 100644 index 1e87e494..00000000 --- a/iOS_Tips/Pods/MLeaksFinder/README-CN.md +++ /dev/null @@ -1,19 +0,0 @@ -# FAQ -**1) 引进 MLeaksFinder 后没生效?** - -* 先验证引进是否正确,在 UIViewController+MemoryLeak.m 的 `+ (void)load` 方法里加断点,app 启动时进入该方法则引进成功,否则引进失败。 -* 用 CocoaPods 安装时注意有没有 warnings,特别是 `OTHER_LDFLAGS` 相关的 warnings。如果有 warnings,可以在主工程的 Build Settings -> Other Linker Flags 加上 `-ObjC`。 - -**2) 可以手动引进 MLeaksFinder 吗?** - -* 直接把 MLeaksFinder 的代码放到项目里即生效。如果把 MLeaksFinder 做为子工程,需要在主工程的 Build Settings -> Other Linker Flags 加上 `-ObjC`。 -* 引进 MLeaksFinder 的代码后即可检测内存泄漏,但查找循环引用的功能还未生效。可以再手动加入 FBRetainCycleDetector 代码,然后把 MLeaksFinder.h 里的 `//#define MEMORY_LEAKS_FINDER_RETAIN_CYCLE_ENABLED 1` 打开。 - -**3) Fail to find a retain cycle?** - -* 内存泄漏不一定是循环引用造成的。 -* 有的循环引用 FBRetainCycleDetector 不一定能找出。 - -**4) 如何关掉 MLeaksFinder?** - -* MLeaksFinder 默认只在 debug 下生效,当然也可以通过 MLeaksFinder.h 里的 `//#define MEMORY_LEAKS_FINDER_ENABLED 0` 来手动控制开关。 diff --git a/iOS_Tips/Pods/Manifest.lock b/iOS_Tips/Pods/Manifest.lock deleted file mode 100644 index 3be33660..00000000 --- a/iOS_Tips/Pods/Manifest.lock +++ /dev/null @@ -1,43 +0,0 @@ -PODS: - - GPUImage (0.1.7) - - Masonry (1.1.0) - - MBProgressHUD (1.1.0) - - YYCache (1.0.4) - - YYImage (1.0.4): - - YYImage/Core (= 1.0.4) - - YYImage/Core (1.0.4) - - YYModel (1.0.4) - - YYWebImage (1.0.5): - - YYCache - - YYImage - -DEPENDENCIES: - - GPUImage - - Masonry - - MBProgressHUD - - YYImage - - YYModel - - YYWebImage - -SPEC REPOS: - https://github.com/CocoaPods/Specs.git: - - GPUImage - - Masonry - - MBProgressHUD - - YYCache - - YYImage - - YYModel - - YYWebImage - -SPEC CHECKSUMS: - GPUImage: 733a5f0fab92df9de1c37ba9df520a833ccb406d - Masonry: 678fab65091a9290e40e2832a55e7ab731aad201 - MBProgressHUD: e7baa36a220447d8aeb12769bf0585582f3866d9 - YYCache: 8105b6638f5e849296c71f331ff83891a4942952 - YYImage: 1e1b62a9997399593e4b9c4ecfbbabbf1d3f3b54 - YYModel: 2a7fdd96aaa4b86a824e26d0c517de8928c04b30 - YYWebImage: 5f7f36aee2ae293f016d418c7d6ba05c4863e928 - -PODFILE CHECKSUM: b400933f5b26aee061a3055185a9866897951c9e - -COCOAPODS: 1.9.1 diff --git a/iOS_Tips/Pods/Masonry/LICENSE b/iOS_Tips/Pods/Masonry/LICENSE deleted file mode 100644 index a843c00c..00000000 --- a/iOS_Tips/Pods/Masonry/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2011-2012 Masonry Team - https://github.com/Masonry - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file diff --git a/iOS_Tips/Pods/Masonry/Masonry/MASCompositeConstraint.h b/iOS_Tips/Pods/Masonry/Masonry/MASCompositeConstraint.h deleted file mode 100644 index 934c6f16..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/MASCompositeConstraint.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// MASCompositeConstraint.h -// Masonry -// -// Created by Jonas Budelmann on 21/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import "MASConstraint.h" -#import "MASUtilities.h" - -/** - * A group of MASConstraint objects - */ -@interface MASCompositeConstraint : MASConstraint - -/** - * Creates a composite with a predefined array of children - * - * @param children child MASConstraints - * - * @return a composite constraint - */ -- (id)initWithChildren:(NSArray *)children; - -@end diff --git a/iOS_Tips/Pods/Masonry/Masonry/MASCompositeConstraint.m b/iOS_Tips/Pods/Masonry/Masonry/MASCompositeConstraint.m deleted file mode 100644 index 2002a405..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/MASCompositeConstraint.m +++ /dev/null @@ -1,183 +0,0 @@ -// -// MASCompositeConstraint.m -// Masonry -// -// Created by Jonas Budelmann on 21/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import "MASCompositeConstraint.h" -#import "MASConstraint+Private.h" - -@interface MASCompositeConstraint () - -@property (nonatomic, strong) id mas_key; -@property (nonatomic, strong) NSMutableArray *childConstraints; - -@end - -@implementation MASCompositeConstraint - -- (id)initWithChildren:(NSArray *)children { - self = [super init]; - if (!self) return nil; - - _childConstraints = [children mutableCopy]; - for (MASConstraint *constraint in _childConstraints) { - constraint.delegate = self; - } - - return self; -} - -#pragma mark - MASConstraintDelegate - -- (void)constraint:(MASConstraint *)constraint shouldBeReplacedWithConstraint:(MASConstraint *)replacementConstraint { - NSUInteger index = [self.childConstraints indexOfObject:constraint]; - NSAssert(index != NSNotFound, @"Could not find constraint %@", constraint); - [self.childConstraints replaceObjectAtIndex:index withObject:replacementConstraint]; -} - -- (MASConstraint *)constraint:(MASConstraint __unused *)constraint addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute { - id strongDelegate = self.delegate; - MASConstraint *newConstraint = [strongDelegate constraint:self addConstraintWithLayoutAttribute:layoutAttribute]; - newConstraint.delegate = self; - [self.childConstraints addObject:newConstraint]; - return newConstraint; -} - -#pragma mark - NSLayoutConstraint multiplier proxies - -- (MASConstraint * (^)(CGFloat))multipliedBy { - return ^id(CGFloat multiplier) { - for (MASConstraint *constraint in self.childConstraints) { - constraint.multipliedBy(multiplier); - } - return self; - }; -} - -- (MASConstraint * (^)(CGFloat))dividedBy { - return ^id(CGFloat divider) { - for (MASConstraint *constraint in self.childConstraints) { - constraint.dividedBy(divider); - } - return self; - }; -} - -#pragma mark - MASLayoutPriority proxy - -- (MASConstraint * (^)(MASLayoutPriority))priority { - return ^id(MASLayoutPriority priority) { - for (MASConstraint *constraint in self.childConstraints) { - constraint.priority(priority); - } - return self; - }; -} - -#pragma mark - NSLayoutRelation proxy - -- (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation { - return ^id(id attr, NSLayoutRelation relation) { - for (MASConstraint *constraint in self.childConstraints.copy) { - constraint.equalToWithRelation(attr, relation); - } - return self; - }; -} - -#pragma mark - attribute chaining - -- (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute { - [self constraint:self addConstraintWithLayoutAttribute:layoutAttribute]; - return self; -} - -#pragma mark - Animator proxy - -#if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV) - -- (MASConstraint *)animator { - for (MASConstraint *constraint in self.childConstraints) { - [constraint animator]; - } - return self; -} - -#endif - -#pragma mark - debug helpers - -- (MASConstraint * (^)(id))key { - return ^id(id key) { - self.mas_key = key; - int i = 0; - for (MASConstraint *constraint in self.childConstraints) { - constraint.key([NSString stringWithFormat:@"%@[%d]", key, i++]); - } - return self; - }; -} - -#pragma mark - NSLayoutConstraint constant setters - -- (void)setInsets:(MASEdgeInsets)insets { - for (MASConstraint *constraint in self.childConstraints) { - constraint.insets = insets; - } -} - -- (void)setInset:(CGFloat)inset { - for (MASConstraint *constraint in self.childConstraints) { - constraint.inset = inset; - } -} - -- (void)setOffset:(CGFloat)offset { - for (MASConstraint *constraint in self.childConstraints) { - constraint.offset = offset; - } -} - -- (void)setSizeOffset:(CGSize)sizeOffset { - for (MASConstraint *constraint in self.childConstraints) { - constraint.sizeOffset = sizeOffset; - } -} - -- (void)setCenterOffset:(CGPoint)centerOffset { - for (MASConstraint *constraint in self.childConstraints) { - constraint.centerOffset = centerOffset; - } -} - -#pragma mark - MASConstraint - -- (void)activate { - for (MASConstraint *constraint in self.childConstraints) { - [constraint activate]; - } -} - -- (void)deactivate { - for (MASConstraint *constraint in self.childConstraints) { - [constraint deactivate]; - } -} - -- (void)install { - for (MASConstraint *constraint in self.childConstraints) { - constraint.updateExisting = self.updateExisting; - [constraint install]; - } -} - -- (void)uninstall { - for (MASConstraint *constraint in self.childConstraints) { - [constraint uninstall]; - } -} - -@end diff --git a/iOS_Tips/Pods/Masonry/Masonry/MASConstraint+Private.h b/iOS_Tips/Pods/Masonry/Masonry/MASConstraint+Private.h deleted file mode 100644 index ee0fd960..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/MASConstraint+Private.h +++ /dev/null @@ -1,66 +0,0 @@ -// -// MASConstraint+Private.h -// Masonry -// -// Created by Nick Tymchenko on 29/04/14. -// Copyright (c) 2014 cloudling. All rights reserved. -// - -#import "MASConstraint.h" - -@protocol MASConstraintDelegate; - - -@interface MASConstraint () - -/** - * Whether or not to check for an existing constraint instead of adding constraint - */ -@property (nonatomic, assign) BOOL updateExisting; - -/** - * Usually MASConstraintMaker but could be a parent MASConstraint - */ -@property (nonatomic, weak) id delegate; - -/** - * Based on a provided value type, is equal to calling: - * NSNumber - setOffset: - * NSValue with CGPoint - setPointOffset: - * NSValue with CGSize - setSizeOffset: - * NSValue with MASEdgeInsets - setInsets: - */ -- (void)setLayoutConstantWithValue:(NSValue *)value; - -@end - - -@interface MASConstraint (Abstract) - -/** - * Sets the constraint relation to given NSLayoutRelation - * returns a block which accepts one of the following: - * MASViewAttribute, UIView, NSValue, NSArray - * see readme for more details. - */ -- (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation; - -/** - * Override to set a custom chaining behaviour - */ -- (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute; - -@end - - -@protocol MASConstraintDelegate - -/** - * Notifies the delegate when the constraint needs to be replaced with another constraint. For example - * A MASViewConstraint may turn into a MASCompositeConstraint when an array is passed to one of the equality blocks - */ -- (void)constraint:(MASConstraint *)constraint shouldBeReplacedWithConstraint:(MASConstraint *)replacementConstraint; - -- (MASConstraint *)constraint:(MASConstraint *)constraint addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute; - -@end diff --git a/iOS_Tips/Pods/Masonry/Masonry/MASConstraint.h b/iOS_Tips/Pods/Masonry/Masonry/MASConstraint.h deleted file mode 100644 index 3eaa8a10..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/MASConstraint.h +++ /dev/null @@ -1,272 +0,0 @@ -// -// MASConstraint.h -// Masonry -// -// Created by Jonas Budelmann on 22/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import "MASUtilities.h" - -/** - * Enables Constraints to be created with chainable syntax - * Constraint can represent single NSLayoutConstraint (MASViewConstraint) - * or a group of NSLayoutConstraints (MASComposisteConstraint) - */ -@interface MASConstraint : NSObject - -// Chaining Support - -/** - * Modifies the NSLayoutConstraint constant, - * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following - * NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight - */ -- (MASConstraint * (^)(MASEdgeInsets insets))insets; - -/** - * Modifies the NSLayoutConstraint constant, - * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following - * NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight - */ -- (MASConstraint * (^)(CGFloat inset))inset; - -/** - * Modifies the NSLayoutConstraint constant, - * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following - * NSLayoutAttributeWidth, NSLayoutAttributeHeight - */ -- (MASConstraint * (^)(CGSize offset))sizeOffset; - -/** - * Modifies the NSLayoutConstraint constant, - * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following - * NSLayoutAttributeCenterX, NSLayoutAttributeCenterY - */ -- (MASConstraint * (^)(CGPoint offset))centerOffset; - -/** - * Modifies the NSLayoutConstraint constant - */ -- (MASConstraint * (^)(CGFloat offset))offset; - -/** - * Modifies the NSLayoutConstraint constant based on a value type - */ -- (MASConstraint * (^)(NSValue *value))valueOffset; - -/** - * Sets the NSLayoutConstraint multiplier property - */ -- (MASConstraint * (^)(CGFloat multiplier))multipliedBy; - -/** - * Sets the NSLayoutConstraint multiplier to 1.0/dividedBy - */ -- (MASConstraint * (^)(CGFloat divider))dividedBy; - -/** - * Sets the NSLayoutConstraint priority to a float or MASLayoutPriority - */ -- (MASConstraint * (^)(MASLayoutPriority priority))priority; - -/** - * Sets the NSLayoutConstraint priority to MASLayoutPriorityLow - */ -- (MASConstraint * (^)(void))priorityLow; - -/** - * Sets the NSLayoutConstraint priority to MASLayoutPriorityMedium - */ -- (MASConstraint * (^)(void))priorityMedium; - -/** - * Sets the NSLayoutConstraint priority to MASLayoutPriorityHigh - */ -- (MASConstraint * (^)(void))priorityHigh; - -/** - * Sets the constraint relation to NSLayoutRelationEqual - * returns a block which accepts one of the following: - * MASViewAttribute, UIView, NSValue, NSArray - * see readme for more details. - */ -- (MASConstraint * (^)(id attr))equalTo; - -/** - * Sets the constraint relation to NSLayoutRelationGreaterThanOrEqual - * returns a block which accepts one of the following: - * MASViewAttribute, UIView, NSValue, NSArray - * see readme for more details. - */ -- (MASConstraint * (^)(id attr))greaterThanOrEqualTo; - -/** - * Sets the constraint relation to NSLayoutRelationLessThanOrEqual - * returns a block which accepts one of the following: - * MASViewAttribute, UIView, NSValue, NSArray - * see readme for more details. - */ -- (MASConstraint * (^)(id attr))lessThanOrEqualTo; - -/** - * Optional semantic property which has no effect but improves the readability of constraint - */ -- (MASConstraint *)with; - -/** - * Optional semantic property which has no effect but improves the readability of constraint - */ -- (MASConstraint *)and; - -/** - * Creates a new MASCompositeConstraint with the called attribute and reciever - */ -- (MASConstraint *)left; -- (MASConstraint *)top; -- (MASConstraint *)right; -- (MASConstraint *)bottom; -- (MASConstraint *)leading; -- (MASConstraint *)trailing; -- (MASConstraint *)width; -- (MASConstraint *)height; -- (MASConstraint *)centerX; -- (MASConstraint *)centerY; -- (MASConstraint *)baseline; - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - -- (MASConstraint *)firstBaseline; -- (MASConstraint *)lastBaseline; - -#endif - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - -- (MASConstraint *)leftMargin; -- (MASConstraint *)rightMargin; -- (MASConstraint *)topMargin; -- (MASConstraint *)bottomMargin; -- (MASConstraint *)leadingMargin; -- (MASConstraint *)trailingMargin; -- (MASConstraint *)centerXWithinMargins; -- (MASConstraint *)centerYWithinMargins; - -#endif - - -/** - * Sets the constraint debug name - */ -- (MASConstraint * (^)(id key))key; - -// NSLayoutConstraint constant Setters -// for use outside of mas_updateConstraints/mas_makeConstraints blocks - -/** - * Modifies the NSLayoutConstraint constant, - * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following - * NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight - */ -- (void)setInsets:(MASEdgeInsets)insets; - -/** - * Modifies the NSLayoutConstraint constant, - * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following - * NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight - */ -- (void)setInset:(CGFloat)inset; - -/** - * Modifies the NSLayoutConstraint constant, - * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following - * NSLayoutAttributeWidth, NSLayoutAttributeHeight - */ -- (void)setSizeOffset:(CGSize)sizeOffset; - -/** - * Modifies the NSLayoutConstraint constant, - * only affects MASConstraints in which the first item's NSLayoutAttribute is one of the following - * NSLayoutAttributeCenterX, NSLayoutAttributeCenterY - */ -- (void)setCenterOffset:(CGPoint)centerOffset; - -/** - * Modifies the NSLayoutConstraint constant - */ -- (void)setOffset:(CGFloat)offset; - - -// NSLayoutConstraint Installation support - -#if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV) -/** - * Whether or not to go through the animator proxy when modifying the constraint - */ -@property (nonatomic, copy, readonly) MASConstraint *animator; -#endif - -/** - * Activates an NSLayoutConstraint if it's supported by an OS. - * Invokes install otherwise. - */ -- (void)activate; - -/** - * Deactivates previously installed/activated NSLayoutConstraint. - */ -- (void)deactivate; - -/** - * Creates a NSLayoutConstraint and adds it to the appropriate view. - */ -- (void)install; - -/** - * Removes previously installed NSLayoutConstraint - */ -- (void)uninstall; - -@end - - -/** - * Convenience auto-boxing macros for MASConstraint methods. - * - * Defining MAS_SHORTHAND_GLOBALS will turn on auto-boxing for default syntax. - * A potential drawback of this is that the unprefixed macros will appear in global scope. - */ -#define mas_equalTo(...) equalTo(MASBoxValue((__VA_ARGS__))) -#define mas_greaterThanOrEqualTo(...) greaterThanOrEqualTo(MASBoxValue((__VA_ARGS__))) -#define mas_lessThanOrEqualTo(...) lessThanOrEqualTo(MASBoxValue((__VA_ARGS__))) - -#define mas_offset(...) valueOffset(MASBoxValue((__VA_ARGS__))) - - -#ifdef MAS_SHORTHAND_GLOBALS - -#define equalTo(...) mas_equalTo(__VA_ARGS__) -#define greaterThanOrEqualTo(...) mas_greaterThanOrEqualTo(__VA_ARGS__) -#define lessThanOrEqualTo(...) mas_lessThanOrEqualTo(__VA_ARGS__) - -#define offset(...) mas_offset(__VA_ARGS__) - -#endif - - -@interface MASConstraint (AutoboxingSupport) - -/** - * Aliases to corresponding relation methods (for shorthand macros) - * Also needed to aid autocompletion - */ -- (MASConstraint * (^)(id attr))mas_equalTo; -- (MASConstraint * (^)(id attr))mas_greaterThanOrEqualTo; -- (MASConstraint * (^)(id attr))mas_lessThanOrEqualTo; - -/** - * A dummy method to aid autocompletion - */ -- (MASConstraint * (^)(id offset))mas_offset; - -@end diff --git a/iOS_Tips/Pods/Masonry/Masonry/MASConstraint.m b/iOS_Tips/Pods/Masonry/Masonry/MASConstraint.m deleted file mode 100644 index 52de590c..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/MASConstraint.m +++ /dev/null @@ -1,301 +0,0 @@ -// -// MASConstraint.m -// Masonry -// -// Created by Nick Tymchenko on 1/20/14. -// - -#import "MASConstraint.h" -#import "MASConstraint+Private.h" - -#define MASMethodNotImplemented() \ - @throw [NSException exceptionWithName:NSInternalInconsistencyException \ - reason:[NSString stringWithFormat:@"You must override %@ in a subclass.", NSStringFromSelector(_cmd)] \ - userInfo:nil] - -@implementation MASConstraint - -#pragma mark - Init - -- (id)init { - NSAssert(![self isMemberOfClass:[MASConstraint class]], @"MASConstraint is an abstract class, you should not instantiate it directly."); - return [super init]; -} - -#pragma mark - NSLayoutRelation proxies - -- (MASConstraint * (^)(id))equalTo { - return ^id(id attribute) { - return self.equalToWithRelation(attribute, NSLayoutRelationEqual); - }; -} - -- (MASConstraint * (^)(id))mas_equalTo { - return ^id(id attribute) { - return self.equalToWithRelation(attribute, NSLayoutRelationEqual); - }; -} - -- (MASConstraint * (^)(id))greaterThanOrEqualTo { - return ^id(id attribute) { - return self.equalToWithRelation(attribute, NSLayoutRelationGreaterThanOrEqual); - }; -} - -- (MASConstraint * (^)(id))mas_greaterThanOrEqualTo { - return ^id(id attribute) { - return self.equalToWithRelation(attribute, NSLayoutRelationGreaterThanOrEqual); - }; -} - -- (MASConstraint * (^)(id))lessThanOrEqualTo { - return ^id(id attribute) { - return self.equalToWithRelation(attribute, NSLayoutRelationLessThanOrEqual); - }; -} - -- (MASConstraint * (^)(id))mas_lessThanOrEqualTo { - return ^id(id attribute) { - return self.equalToWithRelation(attribute, NSLayoutRelationLessThanOrEqual); - }; -} - -#pragma mark - MASLayoutPriority proxies - -- (MASConstraint * (^)(void))priorityLow { - return ^id{ - self.priority(MASLayoutPriorityDefaultLow); - return self; - }; -} - -- (MASConstraint * (^)(void))priorityMedium { - return ^id{ - self.priority(MASLayoutPriorityDefaultMedium); - return self; - }; -} - -- (MASConstraint * (^)(void))priorityHigh { - return ^id{ - self.priority(MASLayoutPriorityDefaultHigh); - return self; - }; -} - -#pragma mark - NSLayoutConstraint constant proxies - -- (MASConstraint * (^)(MASEdgeInsets))insets { - return ^id(MASEdgeInsets insets){ - self.insets = insets; - return self; - }; -} - -- (MASConstraint * (^)(CGFloat))inset { - return ^id(CGFloat inset){ - self.inset = inset; - return self; - }; -} - -- (MASConstraint * (^)(CGSize))sizeOffset { - return ^id(CGSize offset) { - self.sizeOffset = offset; - return self; - }; -} - -- (MASConstraint * (^)(CGPoint))centerOffset { - return ^id(CGPoint offset) { - self.centerOffset = offset; - return self; - }; -} - -- (MASConstraint * (^)(CGFloat))offset { - return ^id(CGFloat offset){ - self.offset = offset; - return self; - }; -} - -- (MASConstraint * (^)(NSValue *value))valueOffset { - return ^id(NSValue *offset) { - NSAssert([offset isKindOfClass:NSValue.class], @"expected an NSValue offset, got: %@", offset); - [self setLayoutConstantWithValue:offset]; - return self; - }; -} - -- (MASConstraint * (^)(id offset))mas_offset { - // Will never be called due to macro - return nil; -} - -#pragma mark - NSLayoutConstraint constant setter - -- (void)setLayoutConstantWithValue:(NSValue *)value { - if ([value isKindOfClass:NSNumber.class]) { - self.offset = [(NSNumber *)value doubleValue]; - } else if (strcmp(value.objCType, @encode(CGPoint)) == 0) { - CGPoint point; - [value getValue:&point]; - self.centerOffset = point; - } else if (strcmp(value.objCType, @encode(CGSize)) == 0) { - CGSize size; - [value getValue:&size]; - self.sizeOffset = size; - } else if (strcmp(value.objCType, @encode(MASEdgeInsets)) == 0) { - MASEdgeInsets insets; - [value getValue:&insets]; - self.insets = insets; - } else { - NSAssert(NO, @"attempting to set layout constant with unsupported value: %@", value); - } -} - -#pragma mark - Semantic properties - -- (MASConstraint *)with { - return self; -} - -- (MASConstraint *)and { - return self; -} - -#pragma mark - Chaining - -- (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute __unused)layoutAttribute { - MASMethodNotImplemented(); -} - -- (MASConstraint *)left { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeft]; -} - -- (MASConstraint *)top { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTop]; -} - -- (MASConstraint *)right { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRight]; -} - -- (MASConstraint *)bottom { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottom]; -} - -- (MASConstraint *)leading { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeading]; -} - -- (MASConstraint *)trailing { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailing]; -} - -- (MASConstraint *)width { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeWidth]; -} - -- (MASConstraint *)height { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeHeight]; -} - -- (MASConstraint *)centerX { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterX]; -} - -- (MASConstraint *)centerY { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterY]; -} - -- (MASConstraint *)baseline { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBaseline]; -} - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - -- (MASConstraint *)firstBaseline { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeFirstBaseline]; -} -- (MASConstraint *)lastBaseline { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLastBaseline]; -} - -#endif - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - -- (MASConstraint *)leftMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeftMargin]; -} - -- (MASConstraint *)rightMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRightMargin]; -} - -- (MASConstraint *)topMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTopMargin]; -} - -- (MASConstraint *)bottomMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottomMargin]; -} - -- (MASConstraint *)leadingMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeadingMargin]; -} - -- (MASConstraint *)trailingMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailingMargin]; -} - -- (MASConstraint *)centerXWithinMargins { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterXWithinMargins]; -} - -- (MASConstraint *)centerYWithinMargins { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterYWithinMargins]; -} - -#endif - -#pragma mark - Abstract - -- (MASConstraint * (^)(CGFloat multiplier))multipliedBy { MASMethodNotImplemented(); } - -- (MASConstraint * (^)(CGFloat divider))dividedBy { MASMethodNotImplemented(); } - -- (MASConstraint * (^)(MASLayoutPriority priority))priority { MASMethodNotImplemented(); } - -- (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation { MASMethodNotImplemented(); } - -- (MASConstraint * (^)(id key))key { MASMethodNotImplemented(); } - -- (void)setInsets:(MASEdgeInsets __unused)insets { MASMethodNotImplemented(); } - -- (void)setInset:(CGFloat __unused)inset { MASMethodNotImplemented(); } - -- (void)setSizeOffset:(CGSize __unused)sizeOffset { MASMethodNotImplemented(); } - -- (void)setCenterOffset:(CGPoint __unused)centerOffset { MASMethodNotImplemented(); } - -- (void)setOffset:(CGFloat __unused)offset { MASMethodNotImplemented(); } - -#if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV) - -- (MASConstraint *)animator { MASMethodNotImplemented(); } - -#endif - -- (void)activate { MASMethodNotImplemented(); } - -- (void)deactivate { MASMethodNotImplemented(); } - -- (void)install { MASMethodNotImplemented(); } - -- (void)uninstall { MASMethodNotImplemented(); } - -@end diff --git a/iOS_Tips/Pods/Masonry/Masonry/MASConstraintMaker.h b/iOS_Tips/Pods/Masonry/Masonry/MASConstraintMaker.h deleted file mode 100644 index d9b58f4f..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/MASConstraintMaker.h +++ /dev/null @@ -1,146 +0,0 @@ -// -// MASConstraintMaker.h -// Masonry -// -// Created by Jonas Budelmann on 20/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import "MASConstraint.h" -#import "MASUtilities.h" - -typedef NS_OPTIONS(NSInteger, MASAttribute) { - MASAttributeLeft = 1 << NSLayoutAttributeLeft, - MASAttributeRight = 1 << NSLayoutAttributeRight, - MASAttributeTop = 1 << NSLayoutAttributeTop, - MASAttributeBottom = 1 << NSLayoutAttributeBottom, - MASAttributeLeading = 1 << NSLayoutAttributeLeading, - MASAttributeTrailing = 1 << NSLayoutAttributeTrailing, - MASAttributeWidth = 1 << NSLayoutAttributeWidth, - MASAttributeHeight = 1 << NSLayoutAttributeHeight, - MASAttributeCenterX = 1 << NSLayoutAttributeCenterX, - MASAttributeCenterY = 1 << NSLayoutAttributeCenterY, - MASAttributeBaseline = 1 << NSLayoutAttributeBaseline, - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - - MASAttributeFirstBaseline = 1 << NSLayoutAttributeFirstBaseline, - MASAttributeLastBaseline = 1 << NSLayoutAttributeLastBaseline, - -#endif - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - - MASAttributeLeftMargin = 1 << NSLayoutAttributeLeftMargin, - MASAttributeRightMargin = 1 << NSLayoutAttributeRightMargin, - MASAttributeTopMargin = 1 << NSLayoutAttributeTopMargin, - MASAttributeBottomMargin = 1 << NSLayoutAttributeBottomMargin, - MASAttributeLeadingMargin = 1 << NSLayoutAttributeLeadingMargin, - MASAttributeTrailingMargin = 1 << NSLayoutAttributeTrailingMargin, - MASAttributeCenterXWithinMargins = 1 << NSLayoutAttributeCenterXWithinMargins, - MASAttributeCenterYWithinMargins = 1 << NSLayoutAttributeCenterYWithinMargins, - -#endif - -}; - -/** - * Provides factory methods for creating MASConstraints. - * Constraints are collected until they are ready to be installed - * - */ -@interface MASConstraintMaker : NSObject - -/** - * The following properties return a new MASViewConstraint - * with the first item set to the makers associated view and the appropriate MASViewAttribute - */ -@property (nonatomic, strong, readonly) MASConstraint *left; -@property (nonatomic, strong, readonly) MASConstraint *top; -@property (nonatomic, strong, readonly) MASConstraint *right; -@property (nonatomic, strong, readonly) MASConstraint *bottom; -@property (nonatomic, strong, readonly) MASConstraint *leading; -@property (nonatomic, strong, readonly) MASConstraint *trailing; -@property (nonatomic, strong, readonly) MASConstraint *width; -@property (nonatomic, strong, readonly) MASConstraint *height; -@property (nonatomic, strong, readonly) MASConstraint *centerX; -@property (nonatomic, strong, readonly) MASConstraint *centerY; -@property (nonatomic, strong, readonly) MASConstraint *baseline; - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - -@property (nonatomic, strong, readonly) MASConstraint *firstBaseline; -@property (nonatomic, strong, readonly) MASConstraint *lastBaseline; - -#endif - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - -@property (nonatomic, strong, readonly) MASConstraint *leftMargin; -@property (nonatomic, strong, readonly) MASConstraint *rightMargin; -@property (nonatomic, strong, readonly) MASConstraint *topMargin; -@property (nonatomic, strong, readonly) MASConstraint *bottomMargin; -@property (nonatomic, strong, readonly) MASConstraint *leadingMargin; -@property (nonatomic, strong, readonly) MASConstraint *trailingMargin; -@property (nonatomic, strong, readonly) MASConstraint *centerXWithinMargins; -@property (nonatomic, strong, readonly) MASConstraint *centerYWithinMargins; - -#endif - -/** - * Returns a block which creates a new MASCompositeConstraint with the first item set - * to the makers associated view and children corresponding to the set bits in the - * MASAttribute parameter. Combine multiple attributes via binary-or. - */ -@property (nonatomic, strong, readonly) MASConstraint *(^attributes)(MASAttribute attrs); - -/** - * Creates a MASCompositeConstraint with type MASCompositeConstraintTypeEdges - * which generates the appropriate MASViewConstraint children (top, left, bottom, right) - * with the first item set to the makers associated view - */ -@property (nonatomic, strong, readonly) MASConstraint *edges; - -/** - * Creates a MASCompositeConstraint with type MASCompositeConstraintTypeSize - * which generates the appropriate MASViewConstraint children (width, height) - * with the first item set to the makers associated view - */ -@property (nonatomic, strong, readonly) MASConstraint *size; - -/** - * Creates a MASCompositeConstraint with type MASCompositeConstraintTypeCenter - * which generates the appropriate MASViewConstraint children (centerX, centerY) - * with the first item set to the makers associated view - */ -@property (nonatomic, strong, readonly) MASConstraint *center; - -/** - * Whether or not to check for an existing constraint instead of adding constraint - */ -@property (nonatomic, assign) BOOL updateExisting; - -/** - * Whether or not to remove existing constraints prior to installing - */ -@property (nonatomic, assign) BOOL removeExisting; - -/** - * initialises the maker with a default view - * - * @param view any MASConstraint are created with this view as the first item - * - * @return a new MASConstraintMaker - */ -- (id)initWithView:(MAS_VIEW *)view; - -/** - * Calls install method on any MASConstraints which have been created by this maker - * - * @return an array of all the installed MASConstraints - */ -- (NSArray *)install; - -- (MASConstraint * (^)(dispatch_block_t))group; - -@end diff --git a/iOS_Tips/Pods/Masonry/Masonry/MASConstraintMaker.m b/iOS_Tips/Pods/Masonry/Masonry/MASConstraintMaker.m deleted file mode 100644 index f11492ab..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/MASConstraintMaker.m +++ /dev/null @@ -1,273 +0,0 @@ -// -// MASConstraintMaker.m -// Masonry -// -// Created by Jonas Budelmann on 20/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import "MASConstraintMaker.h" -#import "MASViewConstraint.h" -#import "MASCompositeConstraint.h" -#import "MASConstraint+Private.h" -#import "MASViewAttribute.h" -#import "View+MASAdditions.h" - -@interface MASConstraintMaker () - -@property (nonatomic, weak) MAS_VIEW *view; -@property (nonatomic, strong) NSMutableArray *constraints; - -@end - -@implementation MASConstraintMaker - -- (id)initWithView:(MAS_VIEW *)view { - self = [super init]; - if (!self) return nil; - - self.view = view; - self.constraints = NSMutableArray.new; - - return self; -} - -- (NSArray *)install { - if (self.removeExisting) { - NSArray *installedConstraints = [MASViewConstraint installedConstraintsForView:self.view]; - for (MASConstraint *constraint in installedConstraints) { - [constraint uninstall]; - } - } - NSArray *constraints = self.constraints.copy; - for (MASConstraint *constraint in constraints) { - constraint.updateExisting = self.updateExisting; - [constraint install]; - } - [self.constraints removeAllObjects]; - return constraints; -} - -#pragma mark - MASConstraintDelegate - -- (void)constraint:(MASConstraint *)constraint shouldBeReplacedWithConstraint:(MASConstraint *)replacementConstraint { - NSUInteger index = [self.constraints indexOfObject:constraint]; - NSAssert(index != NSNotFound, @"Could not find constraint %@", constraint); - [self.constraints replaceObjectAtIndex:index withObject:replacementConstraint]; -} - -- (MASConstraint *)constraint:(MASConstraint *)constraint addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute { - MASViewAttribute *viewAttribute = [[MASViewAttribute alloc] initWithView:self.view layoutAttribute:layoutAttribute]; - MASViewConstraint *newConstraint = [[MASViewConstraint alloc] initWithFirstViewAttribute:viewAttribute]; - if ([constraint isKindOfClass:MASViewConstraint.class]) { - //replace with composite constraint - NSArray *children = @[constraint, newConstraint]; - MASCompositeConstraint *compositeConstraint = [[MASCompositeConstraint alloc] initWithChildren:children]; - compositeConstraint.delegate = self; - [self constraint:constraint shouldBeReplacedWithConstraint:compositeConstraint]; - return compositeConstraint; - } - if (!constraint) { - newConstraint.delegate = self; - [self.constraints addObject:newConstraint]; - } - return newConstraint; -} - -- (MASConstraint *)addConstraintWithAttributes:(MASAttribute)attrs { - __unused MASAttribute anyAttribute = (MASAttributeLeft | MASAttributeRight | MASAttributeTop | MASAttributeBottom | MASAttributeLeading - | MASAttributeTrailing | MASAttributeWidth | MASAttributeHeight | MASAttributeCenterX - | MASAttributeCenterY | MASAttributeBaseline -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - | MASAttributeFirstBaseline | MASAttributeLastBaseline -#endif -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - | MASAttributeLeftMargin | MASAttributeRightMargin | MASAttributeTopMargin | MASAttributeBottomMargin - | MASAttributeLeadingMargin | MASAttributeTrailingMargin | MASAttributeCenterXWithinMargins - | MASAttributeCenterYWithinMargins -#endif - ); - - NSAssert((attrs & anyAttribute) != 0, @"You didn't pass any attribute to make.attributes(...)"); - - NSMutableArray *attributes = [NSMutableArray array]; - - if (attrs & MASAttributeLeft) [attributes addObject:self.view.mas_left]; - if (attrs & MASAttributeRight) [attributes addObject:self.view.mas_right]; - if (attrs & MASAttributeTop) [attributes addObject:self.view.mas_top]; - if (attrs & MASAttributeBottom) [attributes addObject:self.view.mas_bottom]; - if (attrs & MASAttributeLeading) [attributes addObject:self.view.mas_leading]; - if (attrs & MASAttributeTrailing) [attributes addObject:self.view.mas_trailing]; - if (attrs & MASAttributeWidth) [attributes addObject:self.view.mas_width]; - if (attrs & MASAttributeHeight) [attributes addObject:self.view.mas_height]; - if (attrs & MASAttributeCenterX) [attributes addObject:self.view.mas_centerX]; - if (attrs & MASAttributeCenterY) [attributes addObject:self.view.mas_centerY]; - if (attrs & MASAttributeBaseline) [attributes addObject:self.view.mas_baseline]; - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - - if (attrs & MASAttributeFirstBaseline) [attributes addObject:self.view.mas_firstBaseline]; - if (attrs & MASAttributeLastBaseline) [attributes addObject:self.view.mas_lastBaseline]; - -#endif - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - - if (attrs & MASAttributeLeftMargin) [attributes addObject:self.view.mas_leftMargin]; - if (attrs & MASAttributeRightMargin) [attributes addObject:self.view.mas_rightMargin]; - if (attrs & MASAttributeTopMargin) [attributes addObject:self.view.mas_topMargin]; - if (attrs & MASAttributeBottomMargin) [attributes addObject:self.view.mas_bottomMargin]; - if (attrs & MASAttributeLeadingMargin) [attributes addObject:self.view.mas_leadingMargin]; - if (attrs & MASAttributeTrailingMargin) [attributes addObject:self.view.mas_trailingMargin]; - if (attrs & MASAttributeCenterXWithinMargins) [attributes addObject:self.view.mas_centerXWithinMargins]; - if (attrs & MASAttributeCenterYWithinMargins) [attributes addObject:self.view.mas_centerYWithinMargins]; - -#endif - - NSMutableArray *children = [NSMutableArray arrayWithCapacity:attributes.count]; - - for (MASViewAttribute *a in attributes) { - [children addObject:[[MASViewConstraint alloc] initWithFirstViewAttribute:a]]; - } - - MASCompositeConstraint *constraint = [[MASCompositeConstraint alloc] initWithChildren:children]; - constraint.delegate = self; - [self.constraints addObject:constraint]; - return constraint; -} - -#pragma mark - standard Attributes - -- (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute { - return [self constraint:nil addConstraintWithLayoutAttribute:layoutAttribute]; -} - -- (MASConstraint *)left { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeft]; -} - -- (MASConstraint *)top { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTop]; -} - -- (MASConstraint *)right { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRight]; -} - -- (MASConstraint *)bottom { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottom]; -} - -- (MASConstraint *)leading { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeading]; -} - -- (MASConstraint *)trailing { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailing]; -} - -- (MASConstraint *)width { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeWidth]; -} - -- (MASConstraint *)height { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeHeight]; -} - -- (MASConstraint *)centerX { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterX]; -} - -- (MASConstraint *)centerY { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterY]; -} - -- (MASConstraint *)baseline { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBaseline]; -} - -- (MASConstraint *(^)(MASAttribute))attributes { - return ^(MASAttribute attrs){ - return [self addConstraintWithAttributes:attrs]; - }; -} - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - -- (MASConstraint *)firstBaseline { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeFirstBaseline]; -} - -- (MASConstraint *)lastBaseline { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLastBaseline]; -} - -#endif - - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - -- (MASConstraint *)leftMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeftMargin]; -} - -- (MASConstraint *)rightMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeRightMargin]; -} - -- (MASConstraint *)topMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTopMargin]; -} - -- (MASConstraint *)bottomMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeBottomMargin]; -} - -- (MASConstraint *)leadingMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeadingMargin]; -} - -- (MASConstraint *)trailingMargin { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTrailingMargin]; -} - -- (MASConstraint *)centerXWithinMargins { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterXWithinMargins]; -} - -- (MASConstraint *)centerYWithinMargins { - return [self addConstraintWithLayoutAttribute:NSLayoutAttributeCenterYWithinMargins]; -} - -#endif - - -#pragma mark - composite Attributes - -- (MASConstraint *)edges { - return [self addConstraintWithAttributes:MASAttributeTop | MASAttributeLeft | MASAttributeRight | MASAttributeBottom]; -} - -- (MASConstraint *)size { - return [self addConstraintWithAttributes:MASAttributeWidth | MASAttributeHeight]; -} - -- (MASConstraint *)center { - return [self addConstraintWithAttributes:MASAttributeCenterX | MASAttributeCenterY]; -} - -#pragma mark - grouping - -- (MASConstraint *(^)(dispatch_block_t group))group { - return ^id(dispatch_block_t group) { - NSInteger previousCount = self.constraints.count; - group(); - - NSArray *children = [self.constraints subarrayWithRange:NSMakeRange(previousCount, self.constraints.count - previousCount)]; - MASCompositeConstraint *constraint = [[MASCompositeConstraint alloc] initWithChildren:children]; - constraint.delegate = self; - return constraint; - }; -} - -@end diff --git a/iOS_Tips/Pods/Masonry/Masonry/MASLayoutConstraint.h b/iOS_Tips/Pods/Masonry/Masonry/MASLayoutConstraint.h deleted file mode 100644 index 699041cb..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/MASLayoutConstraint.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// MASLayoutConstraint.h -// Masonry -// -// Created by Jonas Budelmann on 3/08/13. -// Copyright (c) 2013 Jonas Budelmann. All rights reserved. -// - -#import "MASUtilities.h" - -/** - * When you are debugging or printing the constraints attached to a view this subclass - * makes it easier to identify which constraints have been created via Masonry - */ -@interface MASLayoutConstraint : NSLayoutConstraint - -/** - * a key to associate with this constraint - */ -@property (nonatomic, strong) id mas_key; - -@end diff --git a/iOS_Tips/Pods/Masonry/Masonry/MASLayoutConstraint.m b/iOS_Tips/Pods/Masonry/Masonry/MASLayoutConstraint.m deleted file mode 100644 index 3483f026..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/MASLayoutConstraint.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// MASLayoutConstraint.m -// Masonry -// -// Created by Jonas Budelmann on 3/08/13. -// Copyright (c) 2013 Jonas Budelmann. All rights reserved. -// - -#import "MASLayoutConstraint.h" - -@implementation MASLayoutConstraint - -@end diff --git a/iOS_Tips/Pods/Masonry/Masonry/MASUtilities.h b/iOS_Tips/Pods/Masonry/Masonry/MASUtilities.h deleted file mode 100644 index 1dbfd938..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/MASUtilities.h +++ /dev/null @@ -1,136 +0,0 @@ -// -// MASUtilities.h -// Masonry -// -// Created by Jonas Budelmann on 19/08/13. -// Copyright (c) 2013 Jonas Budelmann. All rights reserved. -// - -#import - - - -#if TARGET_OS_IPHONE || TARGET_OS_TV - - #import - #define MAS_VIEW UIView - #define MAS_VIEW_CONTROLLER UIViewController - #define MASEdgeInsets UIEdgeInsets - - typedef UILayoutPriority MASLayoutPriority; - static const MASLayoutPriority MASLayoutPriorityRequired = UILayoutPriorityRequired; - static const MASLayoutPriority MASLayoutPriorityDefaultHigh = UILayoutPriorityDefaultHigh; - static const MASLayoutPriority MASLayoutPriorityDefaultMedium = 500; - static const MASLayoutPriority MASLayoutPriorityDefaultLow = UILayoutPriorityDefaultLow; - static const MASLayoutPriority MASLayoutPriorityFittingSizeLevel = UILayoutPriorityFittingSizeLevel; - -#elif TARGET_OS_MAC - - #import - #define MAS_VIEW NSView - #define MASEdgeInsets NSEdgeInsets - - typedef NSLayoutPriority MASLayoutPriority; - static const MASLayoutPriority MASLayoutPriorityRequired = NSLayoutPriorityRequired; - static const MASLayoutPriority MASLayoutPriorityDefaultHigh = NSLayoutPriorityDefaultHigh; - static const MASLayoutPriority MASLayoutPriorityDragThatCanResizeWindow = NSLayoutPriorityDragThatCanResizeWindow; - static const MASLayoutPriority MASLayoutPriorityDefaultMedium = 501; - static const MASLayoutPriority MASLayoutPriorityWindowSizeStayPut = NSLayoutPriorityWindowSizeStayPut; - static const MASLayoutPriority MASLayoutPriorityDragThatCannotResizeWindow = NSLayoutPriorityDragThatCannotResizeWindow; - static const MASLayoutPriority MASLayoutPriorityDefaultLow = NSLayoutPriorityDefaultLow; - static const MASLayoutPriority MASLayoutPriorityFittingSizeCompression = NSLayoutPriorityFittingSizeCompression; - -#endif - -/** - * Allows you to attach keys to objects matching the variable names passed. - * - * view1.mas_key = @"view1", view2.mas_key = @"view2"; - * - * is equivalent to: - * - * MASAttachKeys(view1, view2); - */ -#define MASAttachKeys(...) \ - { \ - NSDictionary *keyPairs = NSDictionaryOfVariableBindings(__VA_ARGS__); \ - for (id key in keyPairs.allKeys) { \ - id obj = keyPairs[key]; \ - NSAssert([obj respondsToSelector:@selector(setMas_key:)], \ - @"Cannot attach mas_key to %@", obj); \ - [obj setMas_key:key]; \ - } \ - } - -/** - * Used to create object hashes - * Based on http://www.mikeash.com/pyblog/friday-qa-2010-06-18-implementing-equality-and-hashing.html - */ -#define MAS_NSUINT_BIT (CHAR_BIT * sizeof(NSUInteger)) -#define MAS_NSUINTROTATE(val, howmuch) ((((NSUInteger)val) << howmuch) | (((NSUInteger)val) >> (MAS_NSUINT_BIT - howmuch))) - -/** - * Given a scalar or struct value, wraps it in NSValue - * Based on EXPObjectify: https://github.com/specta/expecta - */ -static inline id _MASBoxValue(const char *type, ...) { - va_list v; - va_start(v, type); - id obj = nil; - if (strcmp(type, @encode(id)) == 0) { - id actual = va_arg(v, id); - obj = actual; - } else if (strcmp(type, @encode(CGPoint)) == 0) { - CGPoint actual = (CGPoint)va_arg(v, CGPoint); - obj = [NSValue value:&actual withObjCType:type]; - } else if (strcmp(type, @encode(CGSize)) == 0) { - CGSize actual = (CGSize)va_arg(v, CGSize); - obj = [NSValue value:&actual withObjCType:type]; - } else if (strcmp(type, @encode(MASEdgeInsets)) == 0) { - MASEdgeInsets actual = (MASEdgeInsets)va_arg(v, MASEdgeInsets); - obj = [NSValue value:&actual withObjCType:type]; - } else if (strcmp(type, @encode(double)) == 0) { - double actual = (double)va_arg(v, double); - obj = [NSNumber numberWithDouble:actual]; - } else if (strcmp(type, @encode(float)) == 0) { - float actual = (float)va_arg(v, double); - obj = [NSNumber numberWithFloat:actual]; - } else if (strcmp(type, @encode(int)) == 0) { - int actual = (int)va_arg(v, int); - obj = [NSNumber numberWithInt:actual]; - } else if (strcmp(type, @encode(long)) == 0) { - long actual = (long)va_arg(v, long); - obj = [NSNumber numberWithLong:actual]; - } else if (strcmp(type, @encode(long long)) == 0) { - long long actual = (long long)va_arg(v, long long); - obj = [NSNumber numberWithLongLong:actual]; - } else if (strcmp(type, @encode(short)) == 0) { - short actual = (short)va_arg(v, int); - obj = [NSNumber numberWithShort:actual]; - } else if (strcmp(type, @encode(char)) == 0) { - char actual = (char)va_arg(v, int); - obj = [NSNumber numberWithChar:actual]; - } else if (strcmp(type, @encode(bool)) == 0) { - bool actual = (bool)va_arg(v, int); - obj = [NSNumber numberWithBool:actual]; - } else if (strcmp(type, @encode(unsigned char)) == 0) { - unsigned char actual = (unsigned char)va_arg(v, unsigned int); - obj = [NSNumber numberWithUnsignedChar:actual]; - } else if (strcmp(type, @encode(unsigned int)) == 0) { - unsigned int actual = (unsigned int)va_arg(v, unsigned int); - obj = [NSNumber numberWithUnsignedInt:actual]; - } else if (strcmp(type, @encode(unsigned long)) == 0) { - unsigned long actual = (unsigned long)va_arg(v, unsigned long); - obj = [NSNumber numberWithUnsignedLong:actual]; - } else if (strcmp(type, @encode(unsigned long long)) == 0) { - unsigned long long actual = (unsigned long long)va_arg(v, unsigned long long); - obj = [NSNumber numberWithUnsignedLongLong:actual]; - } else if (strcmp(type, @encode(unsigned short)) == 0) { - unsigned short actual = (unsigned short)va_arg(v, unsigned int); - obj = [NSNumber numberWithUnsignedShort:actual]; - } - va_end(v); - return obj; -} - -#define MASBoxValue(value) _MASBoxValue(@encode(__typeof__((value))), (value)) diff --git a/iOS_Tips/Pods/Masonry/Masonry/MASViewAttribute.h b/iOS_Tips/Pods/Masonry/Masonry/MASViewAttribute.h deleted file mode 100644 index 601c25d1..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/MASViewAttribute.h +++ /dev/null @@ -1,49 +0,0 @@ -// -// MASViewAttribute.h -// Masonry -// -// Created by Jonas Budelmann on 21/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import "MASUtilities.h" - -/** - * An immutable tuple which stores the view and the related NSLayoutAttribute. - * Describes part of either the left or right hand side of a constraint equation - */ -@interface MASViewAttribute : NSObject - -/** - * The view which the reciever relates to. Can be nil if item is not a view. - */ -@property (nonatomic, weak, readonly) MAS_VIEW *view; - -/** - * The item which the reciever relates to. - */ -@property (nonatomic, weak, readonly) id item; - -/** - * The attribute which the reciever relates to - */ -@property (nonatomic, assign, readonly) NSLayoutAttribute layoutAttribute; - -/** - * Convenience initializer. - */ -- (id)initWithView:(MAS_VIEW *)view layoutAttribute:(NSLayoutAttribute)layoutAttribute; - -/** - * The designated initializer. - */ -- (id)initWithView:(MAS_VIEW *)view item:(id)item layoutAttribute:(NSLayoutAttribute)layoutAttribute; - -/** - * Determine whether the layoutAttribute is a size attribute - * - * @return YES if layoutAttribute is equal to NSLayoutAttributeWidth or NSLayoutAttributeHeight - */ -- (BOOL)isSizeAttribute; - -@end diff --git a/iOS_Tips/Pods/Masonry/Masonry/MASViewAttribute.m b/iOS_Tips/Pods/Masonry/Masonry/MASViewAttribute.m deleted file mode 100644 index e573e8bd..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/MASViewAttribute.m +++ /dev/null @@ -1,46 +0,0 @@ -// -// MASViewAttribute.m -// Masonry -// -// Created by Jonas Budelmann on 21/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import "MASViewAttribute.h" - -@implementation MASViewAttribute - -- (id)initWithView:(MAS_VIEW *)view layoutAttribute:(NSLayoutAttribute)layoutAttribute { - self = [self initWithView:view item:view layoutAttribute:layoutAttribute]; - return self; -} - -- (id)initWithView:(MAS_VIEW *)view item:(id)item layoutAttribute:(NSLayoutAttribute)layoutAttribute { - self = [super init]; - if (!self) return nil; - - _view = view; - _item = item; - _layoutAttribute = layoutAttribute; - - return self; -} - -- (BOOL)isSizeAttribute { - return self.layoutAttribute == NSLayoutAttributeWidth - || self.layoutAttribute == NSLayoutAttributeHeight; -} - -- (BOOL)isEqual:(MASViewAttribute *)viewAttribute { - if ([viewAttribute isKindOfClass:self.class]) { - return self.view == viewAttribute.view - && self.layoutAttribute == viewAttribute.layoutAttribute; - } - return [super isEqual:viewAttribute]; -} - -- (NSUInteger)hash { - return MAS_NSUINTROTATE([self.view hash], MAS_NSUINT_BIT / 2) ^ self.layoutAttribute; -} - -@end diff --git a/iOS_Tips/Pods/Masonry/Masonry/MASViewConstraint.h b/iOS_Tips/Pods/Masonry/Masonry/MASViewConstraint.h deleted file mode 100644 index ec390d15..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/MASViewConstraint.h +++ /dev/null @@ -1,48 +0,0 @@ -// -// MASViewConstraint.h -// Masonry -// -// Created by Jonas Budelmann on 20/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import "MASViewAttribute.h" -#import "MASConstraint.h" -#import "MASLayoutConstraint.h" -#import "MASUtilities.h" - -/** - * A single constraint. - * Contains the attributes neccessary for creating a NSLayoutConstraint and adding it to the appropriate view - */ -@interface MASViewConstraint : MASConstraint - -/** - * First item/view and first attribute of the NSLayoutConstraint - */ -@property (nonatomic, strong, readonly) MASViewAttribute *firstViewAttribute; - -/** - * Second item/view and second attribute of the NSLayoutConstraint - */ -@property (nonatomic, strong, readonly) MASViewAttribute *secondViewAttribute; - -/** - * initialises the MASViewConstraint with the first part of the equation - * - * @param firstViewAttribute view.mas_left, view.mas_width etc. - * - * @return a new view constraint - */ -- (id)initWithFirstViewAttribute:(MASViewAttribute *)firstViewAttribute; - -/** - * Returns all MASViewConstraints installed with this view as a first item. - * - * @param view A view to retrieve constraints for. - * - * @return An array of MASViewConstraints. - */ -+ (NSArray *)installedConstraintsForView:(MAS_VIEW *)view; - -@end diff --git a/iOS_Tips/Pods/Masonry/Masonry/MASViewConstraint.m b/iOS_Tips/Pods/Masonry/Masonry/MASViewConstraint.m deleted file mode 100644 index 173eec16..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/MASViewConstraint.m +++ /dev/null @@ -1,401 +0,0 @@ -// -// MASViewConstraint.m -// Masonry -// -// Created by Jonas Budelmann on 20/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import "MASViewConstraint.h" -#import "MASConstraint+Private.h" -#import "MASCompositeConstraint.h" -#import "MASLayoutConstraint.h" -#import "View+MASAdditions.h" -#import - -@interface MAS_VIEW (MASConstraints) - -@property (nonatomic, readonly) NSMutableSet *mas_installedConstraints; - -@end - -@implementation MAS_VIEW (MASConstraints) - -static char kInstalledConstraintsKey; - -- (NSMutableSet *)mas_installedConstraints { - NSMutableSet *constraints = objc_getAssociatedObject(self, &kInstalledConstraintsKey); - if (!constraints) { - constraints = [NSMutableSet set]; - objc_setAssociatedObject(self, &kInstalledConstraintsKey, constraints, OBJC_ASSOCIATION_RETAIN_NONATOMIC); - } - return constraints; -} - -@end - - -@interface MASViewConstraint () - -@property (nonatomic, strong, readwrite) MASViewAttribute *secondViewAttribute; -@property (nonatomic, weak) MAS_VIEW *installedView; -@property (nonatomic, weak) MASLayoutConstraint *layoutConstraint; -@property (nonatomic, assign) NSLayoutRelation layoutRelation; -@property (nonatomic, assign) MASLayoutPriority layoutPriority; -@property (nonatomic, assign) CGFloat layoutMultiplier; -@property (nonatomic, assign) CGFloat layoutConstant; -@property (nonatomic, assign) BOOL hasLayoutRelation; -@property (nonatomic, strong) id mas_key; -@property (nonatomic, assign) BOOL useAnimator; - -@end - -@implementation MASViewConstraint - -- (id)initWithFirstViewAttribute:(MASViewAttribute *)firstViewAttribute { - self = [super init]; - if (!self) return nil; - - _firstViewAttribute = firstViewAttribute; - self.layoutPriority = MASLayoutPriorityRequired; - self.layoutMultiplier = 1; - - return self; -} - -#pragma mark - NSCoping - -- (id)copyWithZone:(NSZone __unused *)zone { - MASViewConstraint *constraint = [[MASViewConstraint alloc] initWithFirstViewAttribute:self.firstViewAttribute]; - constraint.layoutConstant = self.layoutConstant; - constraint.layoutRelation = self.layoutRelation; - constraint.layoutPriority = self.layoutPriority; - constraint.layoutMultiplier = self.layoutMultiplier; - constraint.delegate = self.delegate; - return constraint; -} - -#pragma mark - Public - -+ (NSArray *)installedConstraintsForView:(MAS_VIEW *)view { - return [view.mas_installedConstraints allObjects]; -} - -#pragma mark - Private - -- (void)setLayoutConstant:(CGFloat)layoutConstant { - _layoutConstant = layoutConstant; - -#if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV) - if (self.useAnimator) { - [self.layoutConstraint.animator setConstant:layoutConstant]; - } else { - self.layoutConstraint.constant = layoutConstant; - } -#else - self.layoutConstraint.constant = layoutConstant; -#endif -} - -- (void)setLayoutRelation:(NSLayoutRelation)layoutRelation { - _layoutRelation = layoutRelation; - self.hasLayoutRelation = YES; -} - -- (BOOL)supportsActiveProperty { - return [self.layoutConstraint respondsToSelector:@selector(isActive)]; -} - -- (BOOL)isActive { - BOOL active = YES; - if ([self supportsActiveProperty]) { - active = [self.layoutConstraint isActive]; - } - - return active; -} - -- (BOOL)hasBeenInstalled { - return (self.layoutConstraint != nil) && [self isActive]; -} - -- (void)setSecondViewAttribute:(id)secondViewAttribute { - if ([secondViewAttribute isKindOfClass:NSValue.class]) { - [self setLayoutConstantWithValue:secondViewAttribute]; - } else if ([secondViewAttribute isKindOfClass:MAS_VIEW.class]) { - _secondViewAttribute = [[MASViewAttribute alloc] initWithView:secondViewAttribute layoutAttribute:self.firstViewAttribute.layoutAttribute]; - } else if ([secondViewAttribute isKindOfClass:MASViewAttribute.class]) { - _secondViewAttribute = secondViewAttribute; - } else { - NSAssert(NO, @"attempting to add unsupported attribute: %@", secondViewAttribute); - } -} - -#pragma mark - NSLayoutConstraint multiplier proxies - -- (MASConstraint * (^)(CGFloat))multipliedBy { - return ^id(CGFloat multiplier) { - NSAssert(!self.hasBeenInstalled, - @"Cannot modify constraint multiplier after it has been installed"); - - self.layoutMultiplier = multiplier; - return self; - }; -} - - -- (MASConstraint * (^)(CGFloat))dividedBy { - return ^id(CGFloat divider) { - NSAssert(!self.hasBeenInstalled, - @"Cannot modify constraint multiplier after it has been installed"); - - self.layoutMultiplier = 1.0/divider; - return self; - }; -} - -#pragma mark - MASLayoutPriority proxy - -- (MASConstraint * (^)(MASLayoutPriority))priority { - return ^id(MASLayoutPriority priority) { - NSAssert(!self.hasBeenInstalled, - @"Cannot modify constraint priority after it has been installed"); - - self.layoutPriority = priority; - return self; - }; -} - -#pragma mark - NSLayoutRelation proxy - -- (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation { - return ^id(id attribute, NSLayoutRelation relation) { - if ([attribute isKindOfClass:NSArray.class]) { - NSAssert(!self.hasLayoutRelation, @"Redefinition of constraint relation"); - NSMutableArray *children = NSMutableArray.new; - for (id attr in attribute) { - MASViewConstraint *viewConstraint = [self copy]; - viewConstraint.layoutRelation = relation; - viewConstraint.secondViewAttribute = attr; - [children addObject:viewConstraint]; - } - MASCompositeConstraint *compositeConstraint = [[MASCompositeConstraint alloc] initWithChildren:children]; - compositeConstraint.delegate = self.delegate; - [self.delegate constraint:self shouldBeReplacedWithConstraint:compositeConstraint]; - return compositeConstraint; - } else { - NSAssert(!self.hasLayoutRelation || self.layoutRelation == relation && [attribute isKindOfClass:NSValue.class], @"Redefinition of constraint relation"); - self.layoutRelation = relation; - self.secondViewAttribute = attribute; - return self; - } - }; -} - -#pragma mark - Semantic properties - -- (MASConstraint *)with { - return self; -} - -- (MASConstraint *)and { - return self; -} - -#pragma mark - attribute chaining - -- (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute { - NSAssert(!self.hasLayoutRelation, @"Attributes should be chained before defining the constraint relation"); - - return [self.delegate constraint:self addConstraintWithLayoutAttribute:layoutAttribute]; -} - -#pragma mark - Animator proxy - -#if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV) - -- (MASConstraint *)animator { - self.useAnimator = YES; - return self; -} - -#endif - -#pragma mark - debug helpers - -- (MASConstraint * (^)(id))key { - return ^id(id key) { - self.mas_key = key; - return self; - }; -} - -#pragma mark - NSLayoutConstraint constant setters - -- (void)setInsets:(MASEdgeInsets)insets { - NSLayoutAttribute layoutAttribute = self.firstViewAttribute.layoutAttribute; - switch (layoutAttribute) { - case NSLayoutAttributeLeft: - case NSLayoutAttributeLeading: - self.layoutConstant = insets.left; - break; - case NSLayoutAttributeTop: - self.layoutConstant = insets.top; - break; - case NSLayoutAttributeBottom: - self.layoutConstant = -insets.bottom; - break; - case NSLayoutAttributeRight: - case NSLayoutAttributeTrailing: - self.layoutConstant = -insets.right; - break; - default: - break; - } -} - -- (void)setInset:(CGFloat)inset { - [self setInsets:(MASEdgeInsets){.top = inset, .left = inset, .bottom = inset, .right = inset}]; -} - -- (void)setOffset:(CGFloat)offset { - self.layoutConstant = offset; -} - -- (void)setSizeOffset:(CGSize)sizeOffset { - NSLayoutAttribute layoutAttribute = self.firstViewAttribute.layoutAttribute; - switch (layoutAttribute) { - case NSLayoutAttributeWidth: - self.layoutConstant = sizeOffset.width; - break; - case NSLayoutAttributeHeight: - self.layoutConstant = sizeOffset.height; - break; - default: - break; - } -} - -- (void)setCenterOffset:(CGPoint)centerOffset { - NSLayoutAttribute layoutAttribute = self.firstViewAttribute.layoutAttribute; - switch (layoutAttribute) { - case NSLayoutAttributeCenterX: - self.layoutConstant = centerOffset.x; - break; - case NSLayoutAttributeCenterY: - self.layoutConstant = centerOffset.y; - break; - default: - break; - } -} - -#pragma mark - MASConstraint - -- (void)activate { - [self install]; -} - -- (void)deactivate { - [self uninstall]; -} - -- (void)install { - if (self.hasBeenInstalled) { - return; - } - - if ([self supportsActiveProperty] && self.layoutConstraint) { - self.layoutConstraint.active = YES; - [self.firstViewAttribute.view.mas_installedConstraints addObject:self]; - return; - } - - MAS_VIEW *firstLayoutItem = self.firstViewAttribute.item; - NSLayoutAttribute firstLayoutAttribute = self.firstViewAttribute.layoutAttribute; - MAS_VIEW *secondLayoutItem = self.secondViewAttribute.item; - NSLayoutAttribute secondLayoutAttribute = self.secondViewAttribute.layoutAttribute; - - // alignment attributes must have a secondViewAttribute - // therefore we assume that is refering to superview - // eg make.left.equalTo(@10) - if (!self.firstViewAttribute.isSizeAttribute && !self.secondViewAttribute) { - secondLayoutItem = self.firstViewAttribute.view.superview; - secondLayoutAttribute = firstLayoutAttribute; - } - - MASLayoutConstraint *layoutConstraint - = [MASLayoutConstraint constraintWithItem:firstLayoutItem - attribute:firstLayoutAttribute - relatedBy:self.layoutRelation - toItem:secondLayoutItem - attribute:secondLayoutAttribute - multiplier:self.layoutMultiplier - constant:self.layoutConstant]; - - layoutConstraint.priority = self.layoutPriority; - layoutConstraint.mas_key = self.mas_key; - - if (self.secondViewAttribute.view) { - MAS_VIEW *closestCommonSuperview = [self.firstViewAttribute.view mas_closestCommonSuperview:self.secondViewAttribute.view]; - NSAssert(closestCommonSuperview, - @"couldn't find a common superview for %@ and %@", - self.firstViewAttribute.view, self.secondViewAttribute.view); - self.installedView = closestCommonSuperview; - } else if (self.firstViewAttribute.isSizeAttribute) { - self.installedView = self.firstViewAttribute.view; - } else { - self.installedView = self.firstViewAttribute.view.superview; - } - - - MASLayoutConstraint *existingConstraint = nil; - if (self.updateExisting) { - existingConstraint = [self layoutConstraintSimilarTo:layoutConstraint]; - } - if (existingConstraint) { - // just update the constant - existingConstraint.constant = layoutConstraint.constant; - self.layoutConstraint = existingConstraint; - } else { - [self.installedView addConstraint:layoutConstraint]; - self.layoutConstraint = layoutConstraint; - [firstLayoutItem.mas_installedConstraints addObject:self]; - } -} - -- (MASLayoutConstraint *)layoutConstraintSimilarTo:(MASLayoutConstraint *)layoutConstraint { - // check if any constraints are the same apart from the only mutable property constant - - // go through constraints in reverse as we do not want to match auto-resizing or interface builder constraints - // and they are likely to be added first. - for (NSLayoutConstraint *existingConstraint in self.installedView.constraints.reverseObjectEnumerator) { - if (![existingConstraint isKindOfClass:MASLayoutConstraint.class]) continue; - if (existingConstraint.firstItem != layoutConstraint.firstItem) continue; - if (existingConstraint.secondItem != layoutConstraint.secondItem) continue; - if (existingConstraint.firstAttribute != layoutConstraint.firstAttribute) continue; - if (existingConstraint.secondAttribute != layoutConstraint.secondAttribute) continue; - if (existingConstraint.relation != layoutConstraint.relation) continue; - if (existingConstraint.multiplier != layoutConstraint.multiplier) continue; - if (existingConstraint.priority != layoutConstraint.priority) continue; - - return (id)existingConstraint; - } - return nil; -} - -- (void)uninstall { - if ([self supportsActiveProperty]) { - self.layoutConstraint.active = NO; - [self.firstViewAttribute.view.mas_installedConstraints removeObject:self]; - return; - } - - [self.installedView removeConstraint:self.layoutConstraint]; - self.layoutConstraint = nil; - self.installedView = nil; - - [self.firstViewAttribute.view.mas_installedConstraints removeObject:self]; -} - -@end diff --git a/iOS_Tips/Pods/Masonry/Masonry/Masonry.h b/iOS_Tips/Pods/Masonry/Masonry/Masonry.h deleted file mode 100644 index d1bd579d..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/Masonry.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// Masonry.h -// Masonry -// -// Created by Jonas Budelmann on 20/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import - -//! Project version number for Masonry. -FOUNDATION_EXPORT double MasonryVersionNumber; - -//! Project version string for Masonry. -FOUNDATION_EXPORT const unsigned char MasonryVersionString[]; - -#import "MASUtilities.h" -#import "View+MASAdditions.h" -#import "View+MASShorthandAdditions.h" -#import "ViewController+MASAdditions.h" -#import "NSArray+MASAdditions.h" -#import "NSArray+MASShorthandAdditions.h" -#import "MASConstraint.h" -#import "MASCompositeConstraint.h" -#import "MASViewAttribute.h" -#import "MASViewConstraint.h" -#import "MASConstraintMaker.h" -#import "MASLayoutConstraint.h" -#import "NSLayoutConstraint+MASDebugAdditions.h" diff --git a/iOS_Tips/Pods/Masonry/Masonry/NSArray+MASAdditions.h b/iOS_Tips/Pods/Masonry/Masonry/NSArray+MASAdditions.h deleted file mode 100644 index 587618d9..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/NSArray+MASAdditions.h +++ /dev/null @@ -1,72 +0,0 @@ -// -// NSArray+MASAdditions.h -// -// -// Created by Daniel Hammond on 11/26/13. -// -// - -#import "MASUtilities.h" -#import "MASConstraintMaker.h" -#import "MASViewAttribute.h" - -typedef NS_ENUM(NSUInteger, MASAxisType) { - MASAxisTypeHorizontal, - MASAxisTypeVertical -}; - -@interface NSArray (MASAdditions) - -/** - * Creates a MASConstraintMaker with each view in the callee. - * Any constraints defined are added to the view or the appropriate superview once the block has finished executing on each view - * - * @param block scope within which you can build up the constraints which you wish to apply to each view. - * - * @return Array of created MASConstraints - */ -- (NSArray *)mas_makeConstraints:(void (NS_NOESCAPE ^)(MASConstraintMaker *make))block; - -/** - * Creates a MASConstraintMaker with each view in the callee. - * Any constraints defined are added to each view or the appropriate superview once the block has finished executing on each view. - * If an existing constraint exists then it will be updated instead. - * - * @param block scope within which you can build up the constraints which you wish to apply to each view. - * - * @return Array of created/updated MASConstraints - */ -- (NSArray *)mas_updateConstraints:(void (NS_NOESCAPE ^)(MASConstraintMaker *make))block; - -/** - * Creates a MASConstraintMaker with each view in the callee. - * Any constraints defined are added to each view or the appropriate superview once the block has finished executing on each view. - * All constraints previously installed for the views will be removed. - * - * @param block scope within which you can build up the constraints which you wish to apply to each view. - * - * @return Array of created/updated MASConstraints - */ -- (NSArray *)mas_remakeConstraints:(void (NS_NOESCAPE ^)(MASConstraintMaker *make))block; - -/** - * distribute with fixed spacing - * - * @param axisType which axis to distribute items along - * @param fixedSpacing the spacing between each item - * @param leadSpacing the spacing before the first item and the container - * @param tailSpacing the spacing after the last item and the container - */ -- (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedSpacing:(CGFloat)fixedSpacing leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing; - -/** - * distribute with fixed item size - * - * @param axisType which axis to distribute items along - * @param fixedItemLength the fixed length of each item - * @param leadSpacing the spacing before the first item and the container - * @param tailSpacing the spacing after the last item and the container - */ -- (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedItemLength:(CGFloat)fixedItemLength leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing; - -@end diff --git a/iOS_Tips/Pods/Masonry/Masonry/NSArray+MASAdditions.m b/iOS_Tips/Pods/Masonry/Masonry/NSArray+MASAdditions.m deleted file mode 100644 index 831d8cda..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/NSArray+MASAdditions.m +++ /dev/null @@ -1,162 +0,0 @@ -// -// NSArray+MASAdditions.m -// -// -// Created by Daniel Hammond on 11/26/13. -// -// - -#import "NSArray+MASAdditions.h" -#import "View+MASAdditions.h" - -@implementation NSArray (MASAdditions) - -- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *make))block { - NSMutableArray *constraints = [NSMutableArray array]; - for (MAS_VIEW *view in self) { - NSAssert([view isKindOfClass:[MAS_VIEW class]], @"All objects in the array must be views"); - [constraints addObjectsFromArray:[view mas_makeConstraints:block]]; - } - return constraints; -} - -- (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *make))block { - NSMutableArray *constraints = [NSMutableArray array]; - for (MAS_VIEW *view in self) { - NSAssert([view isKindOfClass:[MAS_VIEW class]], @"All objects in the array must be views"); - [constraints addObjectsFromArray:[view mas_updateConstraints:block]]; - } - return constraints; -} - -- (NSArray *)mas_remakeConstraints:(void(^)(MASConstraintMaker *make))block { - NSMutableArray *constraints = [NSMutableArray array]; - for (MAS_VIEW *view in self) { - NSAssert([view isKindOfClass:[MAS_VIEW class]], @"All objects in the array must be views"); - [constraints addObjectsFromArray:[view mas_remakeConstraints:block]]; - } - return constraints; -} - -- (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedSpacing:(CGFloat)fixedSpacing leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing { - if (self.count < 2) { - NSAssert(self.count>1,@"views to distribute need to bigger than one"); - return; - } - - MAS_VIEW *tempSuperView = [self mas_commonSuperviewOfViews]; - if (axisType == MASAxisTypeHorizontal) { - MAS_VIEW *prev; - for (int i = 0; i < self.count; i++) { - MAS_VIEW *v = self[i]; - [v mas_makeConstraints:^(MASConstraintMaker *make) { - if (prev) { - make.width.equalTo(prev); - make.left.equalTo(prev.mas_right).offset(fixedSpacing); - if (i == self.count - 1) {//last one - make.right.equalTo(tempSuperView).offset(-tailSpacing); - } - } - else {//first one - make.left.equalTo(tempSuperView).offset(leadSpacing); - } - - }]; - prev = v; - } - } - else { - MAS_VIEW *prev; - for (int i = 0; i < self.count; i++) { - MAS_VIEW *v = self[i]; - [v mas_makeConstraints:^(MASConstraintMaker *make) { - if (prev) { - make.height.equalTo(prev); - make.top.equalTo(prev.mas_bottom).offset(fixedSpacing); - if (i == self.count - 1) {//last one - make.bottom.equalTo(tempSuperView).offset(-tailSpacing); - } - } - else {//first one - make.top.equalTo(tempSuperView).offset(leadSpacing); - } - - }]; - prev = v; - } - } -} - -- (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType withFixedItemLength:(CGFloat)fixedItemLength leadSpacing:(CGFloat)leadSpacing tailSpacing:(CGFloat)tailSpacing { - if (self.count < 2) { - NSAssert(self.count>1,@"views to distribute need to bigger than one"); - return; - } - - MAS_VIEW *tempSuperView = [self mas_commonSuperviewOfViews]; - if (axisType == MASAxisTypeHorizontal) { - MAS_VIEW *prev; - for (int i = 0; i < self.count; i++) { - MAS_VIEW *v = self[i]; - [v mas_makeConstraints:^(MASConstraintMaker *make) { - make.width.equalTo(@(fixedItemLength)); - if (prev) { - if (i == self.count - 1) {//last one - make.right.equalTo(tempSuperView).offset(-tailSpacing); - } - else { - CGFloat offset = (1-(i/((CGFloat)self.count-1)))*(fixedItemLength+leadSpacing)-i*tailSpacing/(((CGFloat)self.count-1)); - make.right.equalTo(tempSuperView).multipliedBy(i/((CGFloat)self.count-1)).with.offset(offset); - } - } - else {//first one - make.left.equalTo(tempSuperView).offset(leadSpacing); - } - }]; - prev = v; - } - } - else { - MAS_VIEW *prev; - for (int i = 0; i < self.count; i++) { - MAS_VIEW *v = self[i]; - [v mas_makeConstraints:^(MASConstraintMaker *make) { - make.height.equalTo(@(fixedItemLength)); - if (prev) { - if (i == self.count - 1) {//last one - make.bottom.equalTo(tempSuperView).offset(-tailSpacing); - } - else { - CGFloat offset = (1-(i/((CGFloat)self.count-1)))*(fixedItemLength+leadSpacing)-i*tailSpacing/(((CGFloat)self.count-1)); - make.bottom.equalTo(tempSuperView).multipliedBy(i/((CGFloat)self.count-1)).with.offset(offset); - } - } - else {//first one - make.top.equalTo(tempSuperView).offset(leadSpacing); - } - }]; - prev = v; - } - } -} - -- (MAS_VIEW *)mas_commonSuperviewOfViews -{ - MAS_VIEW *commonSuperview = nil; - MAS_VIEW *previousView = nil; - for (id object in self) { - if ([object isKindOfClass:[MAS_VIEW class]]) { - MAS_VIEW *view = (MAS_VIEW *)object; - if (previousView) { - commonSuperview = [view mas_closestCommonSuperview:commonSuperview]; - } else { - commonSuperview = view; - } - previousView = view; - } - } - NSAssert(commonSuperview, @"Can't constrain views that do not share a common superview. Make sure that all the views in this array have been added into the same view hierarchy."); - return commonSuperview; -} - -@end diff --git a/iOS_Tips/Pods/Masonry/Masonry/NSArray+MASShorthandAdditions.h b/iOS_Tips/Pods/Masonry/Masonry/NSArray+MASShorthandAdditions.h deleted file mode 100644 index 8b473697..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/NSArray+MASShorthandAdditions.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// NSArray+MASShorthandAdditions.h -// Masonry -// -// Created by Jonas Budelmann on 22/07/13. -// Copyright (c) 2013 Jonas Budelmann. All rights reserved. -// - -#import "NSArray+MASAdditions.h" - -#ifdef MAS_SHORTHAND - -/** - * Shorthand array additions without the 'mas_' prefixes, - * only enabled if MAS_SHORTHAND is defined - */ -@interface NSArray (MASShorthandAdditions) - -- (NSArray *)makeConstraints:(void(^)(MASConstraintMaker *make))block; -- (NSArray *)updateConstraints:(void(^)(MASConstraintMaker *make))block; -- (NSArray *)remakeConstraints:(void(^)(MASConstraintMaker *make))block; - -@end - -@implementation NSArray (MASShorthandAdditions) - -- (NSArray *)makeConstraints:(void(^)(MASConstraintMaker *))block { - return [self mas_makeConstraints:block]; -} - -- (NSArray *)updateConstraints:(void(^)(MASConstraintMaker *))block { - return [self mas_updateConstraints:block]; -} - -- (NSArray *)remakeConstraints:(void(^)(MASConstraintMaker *))block { - return [self mas_remakeConstraints:block]; -} - -@end - -#endif diff --git a/iOS_Tips/Pods/Masonry/Masonry/NSLayoutConstraint+MASDebugAdditions.h b/iOS_Tips/Pods/Masonry/Masonry/NSLayoutConstraint+MASDebugAdditions.h deleted file mode 100644 index 1279b4fd..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/NSLayoutConstraint+MASDebugAdditions.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// NSLayoutConstraint+MASDebugAdditions.h -// Masonry -// -// Created by Jonas Budelmann on 3/08/13. -// Copyright (c) 2013 Jonas Budelmann. All rights reserved. -// - -#import "MASUtilities.h" - -/** - * makes debug and log output of NSLayoutConstraints more readable - */ -@interface NSLayoutConstraint (MASDebugAdditions) - -@end diff --git a/iOS_Tips/Pods/Masonry/Masonry/NSLayoutConstraint+MASDebugAdditions.m b/iOS_Tips/Pods/Masonry/Masonry/NSLayoutConstraint+MASDebugAdditions.m deleted file mode 100644 index ab539a21..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/NSLayoutConstraint+MASDebugAdditions.m +++ /dev/null @@ -1,146 +0,0 @@ -// -// NSLayoutConstraint+MASDebugAdditions.m -// Masonry -// -// Created by Jonas Budelmann on 3/08/13. -// Copyright (c) 2013 Jonas Budelmann. All rights reserved. -// - -#import "NSLayoutConstraint+MASDebugAdditions.h" -#import "MASConstraint.h" -#import "MASLayoutConstraint.h" - -@implementation NSLayoutConstraint (MASDebugAdditions) - -#pragma mark - description maps - -+ (NSDictionary *)layoutRelationDescriptionsByValue { - static dispatch_once_t once; - static NSDictionary *descriptionMap; - dispatch_once(&once, ^{ - descriptionMap = @{ - @(NSLayoutRelationEqual) : @"==", - @(NSLayoutRelationGreaterThanOrEqual) : @">=", - @(NSLayoutRelationLessThanOrEqual) : @"<=", - }; - }); - return descriptionMap; -} - -+ (NSDictionary *)layoutAttributeDescriptionsByValue { - static dispatch_once_t once; - static NSDictionary *descriptionMap; - dispatch_once(&once, ^{ - descriptionMap = @{ - @(NSLayoutAttributeTop) : @"top", - @(NSLayoutAttributeLeft) : @"left", - @(NSLayoutAttributeBottom) : @"bottom", - @(NSLayoutAttributeRight) : @"right", - @(NSLayoutAttributeLeading) : @"leading", - @(NSLayoutAttributeTrailing) : @"trailing", - @(NSLayoutAttributeWidth) : @"width", - @(NSLayoutAttributeHeight) : @"height", - @(NSLayoutAttributeCenterX) : @"centerX", - @(NSLayoutAttributeCenterY) : @"centerY", - @(NSLayoutAttributeBaseline) : @"baseline", - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - @(NSLayoutAttributeFirstBaseline) : @"firstBaseline", - @(NSLayoutAttributeLastBaseline) : @"lastBaseline", -#endif - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - @(NSLayoutAttributeLeftMargin) : @"leftMargin", - @(NSLayoutAttributeRightMargin) : @"rightMargin", - @(NSLayoutAttributeTopMargin) : @"topMargin", - @(NSLayoutAttributeBottomMargin) : @"bottomMargin", - @(NSLayoutAttributeLeadingMargin) : @"leadingMargin", - @(NSLayoutAttributeTrailingMargin) : @"trailingMargin", - @(NSLayoutAttributeCenterXWithinMargins) : @"centerXWithinMargins", - @(NSLayoutAttributeCenterYWithinMargins) : @"centerYWithinMargins", -#endif - - }; - - }); - return descriptionMap; -} - - -+ (NSDictionary *)layoutPriorityDescriptionsByValue { - static dispatch_once_t once; - static NSDictionary *descriptionMap; - dispatch_once(&once, ^{ -#if TARGET_OS_IPHONE || TARGET_OS_TV - descriptionMap = @{ - @(MASLayoutPriorityDefaultHigh) : @"high", - @(MASLayoutPriorityDefaultLow) : @"low", - @(MASLayoutPriorityDefaultMedium) : @"medium", - @(MASLayoutPriorityRequired) : @"required", - @(MASLayoutPriorityFittingSizeLevel) : @"fitting size", - }; -#elif TARGET_OS_MAC - descriptionMap = @{ - @(MASLayoutPriorityDefaultHigh) : @"high", - @(MASLayoutPriorityDragThatCanResizeWindow) : @"drag can resize window", - @(MASLayoutPriorityDefaultMedium) : @"medium", - @(MASLayoutPriorityWindowSizeStayPut) : @"window size stay put", - @(MASLayoutPriorityDragThatCannotResizeWindow) : @"drag cannot resize window", - @(MASLayoutPriorityDefaultLow) : @"low", - @(MASLayoutPriorityFittingSizeCompression) : @"fitting size", - @(MASLayoutPriorityRequired) : @"required", - }; -#endif - }); - return descriptionMap; -} - -#pragma mark - description override - -+ (NSString *)descriptionForObject:(id)obj { - if ([obj respondsToSelector:@selector(mas_key)] && [obj mas_key]) { - return [NSString stringWithFormat:@"%@:%@", [obj class], [obj mas_key]]; - } - return [NSString stringWithFormat:@"%@:%p", [obj class], obj]; -} - -- (NSString *)description { - NSMutableString *description = [[NSMutableString alloc] initWithString:@"<"]; - - [description appendString:[self.class descriptionForObject:self]]; - - [description appendFormat:@" %@", [self.class descriptionForObject:self.firstItem]]; - if (self.firstAttribute != NSLayoutAttributeNotAnAttribute) { - [description appendFormat:@".%@", self.class.layoutAttributeDescriptionsByValue[@(self.firstAttribute)]]; - } - - [description appendFormat:@" %@", self.class.layoutRelationDescriptionsByValue[@(self.relation)]]; - - if (self.secondItem) { - [description appendFormat:@" %@", [self.class descriptionForObject:self.secondItem]]; - } - if (self.secondAttribute != NSLayoutAttributeNotAnAttribute) { - [description appendFormat:@".%@", self.class.layoutAttributeDescriptionsByValue[@(self.secondAttribute)]]; - } - - if (self.multiplier != 1) { - [description appendFormat:@" * %g", self.multiplier]; - } - - if (self.secondAttribute == NSLayoutAttributeNotAnAttribute) { - [description appendFormat:@" %g", self.constant]; - } else { - if (self.constant) { - [description appendFormat:@" %@ %g", (self.constant < 0 ? @"-" : @"+"), ABS(self.constant)]; - } - } - - if (self.priority != MASLayoutPriorityRequired) { - [description appendFormat:@" ^%@", self.class.layoutPriorityDescriptionsByValue[@(self.priority)] ?: [NSNumber numberWithDouble:self.priority]]; - } - - [description appendString:@">"]; - return description; -} - -@end diff --git a/iOS_Tips/Pods/Masonry/Masonry/View+MASAdditions.h b/iOS_Tips/Pods/Masonry/Masonry/View+MASAdditions.h deleted file mode 100644 index f7343d26..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/View+MASAdditions.h +++ /dev/null @@ -1,111 +0,0 @@ -// -// UIView+MASAdditions.h -// Masonry -// -// Created by Jonas Budelmann on 20/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import "MASUtilities.h" -#import "MASConstraintMaker.h" -#import "MASViewAttribute.h" - -/** - * Provides constraint maker block - * and convience methods for creating MASViewAttribute which are view + NSLayoutAttribute pairs - */ -@interface MAS_VIEW (MASAdditions) - -/** - * following properties return a new MASViewAttribute with current view and appropriate NSLayoutAttribute - */ -@property (nonatomic, strong, readonly) MASViewAttribute *mas_left; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_top; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_right; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottom; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_leading; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_trailing; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_width; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_height; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerX; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerY; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_baseline; -@property (nonatomic, strong, readonly) MASViewAttribute *(^mas_attribute)(NSLayoutAttribute attr); - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - -@property (nonatomic, strong, readonly) MASViewAttribute *mas_firstBaseline; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_lastBaseline; - -#endif - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - -@property (nonatomic, strong, readonly) MASViewAttribute *mas_leftMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_rightMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_topMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottomMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_leadingMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_trailingMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerXWithinMargins; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerYWithinMargins; - -#endif - -#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000) - -@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuide API_AVAILABLE(ios(11.0),tvos(11.0)); -@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideTop API_AVAILABLE(ios(11.0),tvos(11.0)); -@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideBottom API_AVAILABLE(ios(11.0),tvos(11.0)); -@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideLeft API_AVAILABLE(ios(11.0),tvos(11.0)); -@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideRight API_AVAILABLE(ios(11.0),tvos(11.0)); - -#endif - -/** - * a key to associate with this view - */ -@property (nonatomic, strong) id mas_key; - -/** - * Finds the closest common superview between this view and another view - * - * @param view other view - * - * @return returns nil if common superview could not be found - */ -- (instancetype)mas_closestCommonSuperview:(MAS_VIEW *)view; - -/** - * Creates a MASConstraintMaker with the callee view. - * Any constraints defined are added to the view or the appropriate superview once the block has finished executing - * - * @param block scope within which you can build up the constraints which you wish to apply to the view. - * - * @return Array of created MASConstraints - */ -- (NSArray *)mas_makeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block; - -/** - * Creates a MASConstraintMaker with the callee view. - * Any constraints defined are added to the view or the appropriate superview once the block has finished executing. - * If an existing constraint exists then it will be updated instead. - * - * @param block scope within which you can build up the constraints which you wish to apply to the view. - * - * @return Array of created/updated MASConstraints - */ -- (NSArray *)mas_updateConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block; - -/** - * Creates a MASConstraintMaker with the callee view. - * Any constraints defined are added to the view or the appropriate superview once the block has finished executing. - * All constraints previously installed for the view will be removed. - * - * @param block scope within which you can build up the constraints which you wish to apply to the view. - * - * @return Array of created/updated MASConstraints - */ -- (NSArray *)mas_remakeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block; - -@end diff --git a/iOS_Tips/Pods/Masonry/Masonry/View+MASAdditions.m b/iOS_Tips/Pods/Masonry/Masonry/View+MASAdditions.m deleted file mode 100644 index 4fa07b4f..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/View+MASAdditions.m +++ /dev/null @@ -1,186 +0,0 @@ -// -// UIView+MASAdditions.m -// Masonry -// -// Created by Jonas Budelmann on 20/07/13. -// Copyright (c) 2013 cloudling. All rights reserved. -// - -#import "View+MASAdditions.h" -#import - -@implementation MAS_VIEW (MASAdditions) - -- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))block { - self.translatesAutoresizingMaskIntoConstraints = NO; - MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self]; - block(constraintMaker); - return [constraintMaker install]; -} - -- (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *))block { - self.translatesAutoresizingMaskIntoConstraints = NO; - MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self]; - constraintMaker.updateExisting = YES; - block(constraintMaker); - return [constraintMaker install]; -} - -- (NSArray *)mas_remakeConstraints:(void(^)(MASConstraintMaker *make))block { - self.translatesAutoresizingMaskIntoConstraints = NO; - MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self]; - constraintMaker.removeExisting = YES; - block(constraintMaker); - return [constraintMaker install]; -} - -#pragma mark - NSLayoutAttribute properties - -- (MASViewAttribute *)mas_left { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeLeft]; -} - -- (MASViewAttribute *)mas_top { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeTop]; -} - -- (MASViewAttribute *)mas_right { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeRight]; -} - -- (MASViewAttribute *)mas_bottom { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeBottom]; -} - -- (MASViewAttribute *)mas_leading { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeLeading]; -} - -- (MASViewAttribute *)mas_trailing { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeTrailing]; -} - -- (MASViewAttribute *)mas_width { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeWidth]; -} - -- (MASViewAttribute *)mas_height { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeHeight]; -} - -- (MASViewAttribute *)mas_centerX { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeCenterX]; -} - -- (MASViewAttribute *)mas_centerY { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeCenterY]; -} - -- (MASViewAttribute *)mas_baseline { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeBaseline]; -} - -- (MASViewAttribute *(^)(NSLayoutAttribute))mas_attribute -{ - return ^(NSLayoutAttribute attr) { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:attr]; - }; -} - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - -- (MASViewAttribute *)mas_firstBaseline { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeFirstBaseline]; -} -- (MASViewAttribute *)mas_lastBaseline { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeLastBaseline]; -} - -#endif - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - -- (MASViewAttribute *)mas_leftMargin { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeLeftMargin]; -} - -- (MASViewAttribute *)mas_rightMargin { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeRightMargin]; -} - -- (MASViewAttribute *)mas_topMargin { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeTopMargin]; -} - -- (MASViewAttribute *)mas_bottomMargin { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeBottomMargin]; -} - -- (MASViewAttribute *)mas_leadingMargin { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeLeadingMargin]; -} - -- (MASViewAttribute *)mas_trailingMargin { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeTrailingMargin]; -} - -- (MASViewAttribute *)mas_centerXWithinMargins { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeCenterXWithinMargins]; -} - -- (MASViewAttribute *)mas_centerYWithinMargins { - return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeCenterYWithinMargins]; -} - -#endif - -#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000) - -- (MASViewAttribute *)mas_safeAreaLayoutGuide { - return [[MASViewAttribute alloc] initWithView:self item:self.safeAreaLayoutGuide layoutAttribute:NSLayoutAttributeBottom]; -} -- (MASViewAttribute *)mas_safeAreaLayoutGuideTop { - return [[MASViewAttribute alloc] initWithView:self item:self.safeAreaLayoutGuide layoutAttribute:NSLayoutAttributeTop]; -} -- (MASViewAttribute *)mas_safeAreaLayoutGuideBottom { - return [[MASViewAttribute alloc] initWithView:self item:self.safeAreaLayoutGuide layoutAttribute:NSLayoutAttributeBottom]; -} -- (MASViewAttribute *)mas_safeAreaLayoutGuideLeft { - return [[MASViewAttribute alloc] initWithView:self item:self.safeAreaLayoutGuide layoutAttribute:NSLayoutAttributeLeft]; -} -- (MASViewAttribute *)mas_safeAreaLayoutGuideRight { - return [[MASViewAttribute alloc] initWithView:self item:self.safeAreaLayoutGuide layoutAttribute:NSLayoutAttributeRight]; -} - -#endif - -#pragma mark - associated properties - -- (id)mas_key { - return objc_getAssociatedObject(self, @selector(mas_key)); -} - -- (void)setMas_key:(id)key { - objc_setAssociatedObject(self, @selector(mas_key), key, OBJC_ASSOCIATION_RETAIN_NONATOMIC); -} - -#pragma mark - heirachy - -- (instancetype)mas_closestCommonSuperview:(MAS_VIEW *)view { - MAS_VIEW *closestCommonSuperview = nil; - - MAS_VIEW *secondViewSuperview = view; - while (!closestCommonSuperview && secondViewSuperview) { - MAS_VIEW *firstViewSuperview = self; - while (!closestCommonSuperview && firstViewSuperview) { - if (secondViewSuperview == firstViewSuperview) { - closestCommonSuperview = secondViewSuperview; - } - firstViewSuperview = firstViewSuperview.superview; - } - secondViewSuperview = secondViewSuperview.superview; - } - return closestCommonSuperview; -} - -@end diff --git a/iOS_Tips/Pods/Masonry/Masonry/View+MASShorthandAdditions.h b/iOS_Tips/Pods/Masonry/Masonry/View+MASShorthandAdditions.h deleted file mode 100644 index 1c19a942..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/View+MASShorthandAdditions.h +++ /dev/null @@ -1,133 +0,0 @@ -// -// UIView+MASShorthandAdditions.h -// Masonry -// -// Created by Jonas Budelmann on 22/07/13. -// Copyright (c) 2013 Jonas Budelmann. All rights reserved. -// - -#import "View+MASAdditions.h" - -#ifdef MAS_SHORTHAND - -/** - * Shorthand view additions without the 'mas_' prefixes, - * only enabled if MAS_SHORTHAND is defined - */ -@interface MAS_VIEW (MASShorthandAdditions) - -@property (nonatomic, strong, readonly) MASViewAttribute *left; -@property (nonatomic, strong, readonly) MASViewAttribute *top; -@property (nonatomic, strong, readonly) MASViewAttribute *right; -@property (nonatomic, strong, readonly) MASViewAttribute *bottom; -@property (nonatomic, strong, readonly) MASViewAttribute *leading; -@property (nonatomic, strong, readonly) MASViewAttribute *trailing; -@property (nonatomic, strong, readonly) MASViewAttribute *width; -@property (nonatomic, strong, readonly) MASViewAttribute *height; -@property (nonatomic, strong, readonly) MASViewAttribute *centerX; -@property (nonatomic, strong, readonly) MASViewAttribute *centerY; -@property (nonatomic, strong, readonly) MASViewAttribute *baseline; -@property (nonatomic, strong, readonly) MASViewAttribute *(^attribute)(NSLayoutAttribute attr); - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - -@property (nonatomic, strong, readonly) MASViewAttribute *firstBaseline; -@property (nonatomic, strong, readonly) MASViewAttribute *lastBaseline; - -#endif - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - -@property (nonatomic, strong, readonly) MASViewAttribute *leftMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *rightMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *topMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *bottomMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *leadingMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *trailingMargin; -@property (nonatomic, strong, readonly) MASViewAttribute *centerXWithinMargins; -@property (nonatomic, strong, readonly) MASViewAttribute *centerYWithinMargins; - -#endif - -#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000) - -@property (nonatomic, strong, readonly) MASViewAttribute *safeAreaLayoutGuideTop API_AVAILABLE(ios(11.0),tvos(11.0)); -@property (nonatomic, strong, readonly) MASViewAttribute *safeAreaLayoutGuideBottom API_AVAILABLE(ios(11.0),tvos(11.0)); -@property (nonatomic, strong, readonly) MASViewAttribute *safeAreaLayoutGuideLeft API_AVAILABLE(ios(11.0),tvos(11.0)); -@property (nonatomic, strong, readonly) MASViewAttribute *safeAreaLayoutGuideRight API_AVAILABLE(ios(11.0),tvos(11.0)); - -#endif - -- (NSArray *)makeConstraints:(void(^)(MASConstraintMaker *make))block; -- (NSArray *)updateConstraints:(void(^)(MASConstraintMaker *make))block; -- (NSArray *)remakeConstraints:(void(^)(MASConstraintMaker *make))block; - -@end - -#define MAS_ATTR_FORWARD(attr) \ -- (MASViewAttribute *)attr { \ - return [self mas_##attr]; \ -} - -@implementation MAS_VIEW (MASShorthandAdditions) - -MAS_ATTR_FORWARD(top); -MAS_ATTR_FORWARD(left); -MAS_ATTR_FORWARD(bottom); -MAS_ATTR_FORWARD(right); -MAS_ATTR_FORWARD(leading); -MAS_ATTR_FORWARD(trailing); -MAS_ATTR_FORWARD(width); -MAS_ATTR_FORWARD(height); -MAS_ATTR_FORWARD(centerX); -MAS_ATTR_FORWARD(centerY); -MAS_ATTR_FORWARD(baseline); - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) - -MAS_ATTR_FORWARD(firstBaseline); -MAS_ATTR_FORWARD(lastBaseline); - -#endif - -#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) - -MAS_ATTR_FORWARD(leftMargin); -MAS_ATTR_FORWARD(rightMargin); -MAS_ATTR_FORWARD(topMargin); -MAS_ATTR_FORWARD(bottomMargin); -MAS_ATTR_FORWARD(leadingMargin); -MAS_ATTR_FORWARD(trailingMargin); -MAS_ATTR_FORWARD(centerXWithinMargins); -MAS_ATTR_FORWARD(centerYWithinMargins); - -#endif - -#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000) - -MAS_ATTR_FORWARD(safeAreaLayoutGuideTop); -MAS_ATTR_FORWARD(safeAreaLayoutGuideBottom); -MAS_ATTR_FORWARD(safeAreaLayoutGuideLeft); -MAS_ATTR_FORWARD(safeAreaLayoutGuideRight); - -#endif - -- (MASViewAttribute *(^)(NSLayoutAttribute))attribute { - return [self mas_attribute]; -} - -- (NSArray *)makeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *))block { - return [self mas_makeConstraints:block]; -} - -- (NSArray *)updateConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *))block { - return [self mas_updateConstraints:block]; -} - -- (NSArray *)remakeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *))block { - return [self mas_remakeConstraints:block]; -} - -@end - -#endif diff --git a/iOS_Tips/Pods/Masonry/Masonry/ViewController+MASAdditions.h b/iOS_Tips/Pods/Masonry/Masonry/ViewController+MASAdditions.h deleted file mode 100644 index 79fd1fa7..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/ViewController+MASAdditions.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// UIViewController+MASAdditions.h -// Masonry -// -// Created by Craig Siemens on 2015-06-23. -// -// - -#import "MASUtilities.h" -#import "MASConstraintMaker.h" -#import "MASViewAttribute.h" - -#ifdef MAS_VIEW_CONTROLLER - -@interface MAS_VIEW_CONTROLLER (MASAdditions) - -/** - * following properties return a new MASViewAttribute with appropriate UILayoutGuide and NSLayoutAttribute - */ -@property (nonatomic, strong, readonly) MASViewAttribute *mas_topLayoutGuide; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottomLayoutGuide; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_topLayoutGuideTop; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_topLayoutGuideBottom; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottomLayoutGuideTop; -@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottomLayoutGuideBottom; - - -@end - -#endif diff --git a/iOS_Tips/Pods/Masonry/Masonry/ViewController+MASAdditions.m b/iOS_Tips/Pods/Masonry/Masonry/ViewController+MASAdditions.m deleted file mode 100644 index 2f5139fa..00000000 --- a/iOS_Tips/Pods/Masonry/Masonry/ViewController+MASAdditions.m +++ /dev/null @@ -1,39 +0,0 @@ -// -// UIViewController+MASAdditions.m -// Masonry -// -// Created by Craig Siemens on 2015-06-23. -// -// - -#import "ViewController+MASAdditions.h" - -#ifdef MAS_VIEW_CONTROLLER - -@implementation MAS_VIEW_CONTROLLER (MASAdditions) - -- (MASViewAttribute *)mas_topLayoutGuide { - return [[MASViewAttribute alloc] initWithView:self.view item:self.topLayoutGuide layoutAttribute:NSLayoutAttributeBottom]; -} -- (MASViewAttribute *)mas_topLayoutGuideTop { - return [[MASViewAttribute alloc] initWithView:self.view item:self.topLayoutGuide layoutAttribute:NSLayoutAttributeTop]; -} -- (MASViewAttribute *)mas_topLayoutGuideBottom { - return [[MASViewAttribute alloc] initWithView:self.view item:self.topLayoutGuide layoutAttribute:NSLayoutAttributeBottom]; -} - -- (MASViewAttribute *)mas_bottomLayoutGuide { - return [[MASViewAttribute alloc] initWithView:self.view item:self.bottomLayoutGuide layoutAttribute:NSLayoutAttributeTop]; -} -- (MASViewAttribute *)mas_bottomLayoutGuideTop { - return [[MASViewAttribute alloc] initWithView:self.view item:self.bottomLayoutGuide layoutAttribute:NSLayoutAttributeTop]; -} -- (MASViewAttribute *)mas_bottomLayoutGuideBottom { - return [[MASViewAttribute alloc] initWithView:self.view item:self.bottomLayoutGuide layoutAttribute:NSLayoutAttributeBottom]; -} - - - -@end - -#endif diff --git a/iOS_Tips/Pods/Masonry/README.md b/iOS_Tips/Pods/Masonry/README.md deleted file mode 100644 index d4286576..00000000 --- a/iOS_Tips/Pods/Masonry/README.md +++ /dev/null @@ -1,415 +0,0 @@ -# Masonry [![Build Status](https://travis-ci.org/SnapKit/Masonry.svg?branch=master)](https://travis-ci.org/SnapKit/Masonry) [![Coverage Status](https://img.shields.io/coveralls/SnapKit/Masonry.svg?style=flat-square)](https://coveralls.io/r/SnapKit/Masonry) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) ![Pod Version](https://img.shields.io/cocoapods/v/Masonry.svg?style=flat) - -**Masonry is still actively maintained, we are committed to fixing bugs and merging good quality PRs from the wider community. However if you're using Swift in your project, we recommend using [SnapKit](https://github.com/SnapKit/SnapKit) as it provides better type safety with a simpler API.** - -Masonry is a light-weight layout framework which wraps AutoLayout with a nicer syntax. Masonry has its own layout DSL which provides a chainable way of describing your NSLayoutConstraints which results in layout code that is more concise and readable. -Masonry supports iOS and Mac OS X. - -For examples take a look at the **Masonry iOS Examples** project in the Masonry workspace. You will need to run `pod install` after downloading. - -## What's wrong with NSLayoutConstraints? - -Under the hood Auto Layout is a powerful and flexible way of organising and laying out your views. However creating constraints from code is verbose and not very descriptive. -Imagine a simple example in which you want to have a view fill its superview but inset by 10 pixels on every side -```obj-c -UIView *superview = self.view; - -UIView *view1 = [[UIView alloc] init]; -view1.translatesAutoresizingMaskIntoConstraints = NO; -view1.backgroundColor = [UIColor greenColor]; -[superview addSubview:view1]; - -UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10); - -[superview addConstraints:@[ - - //view1 constraints - [NSLayoutConstraint constraintWithItem:view1 - attribute:NSLayoutAttributeTop - relatedBy:NSLayoutRelationEqual - toItem:superview - attribute:NSLayoutAttributeTop - multiplier:1.0 - constant:padding.top], - - [NSLayoutConstraint constraintWithItem:view1 - attribute:NSLayoutAttributeLeft - relatedBy:NSLayoutRelationEqual - toItem:superview - attribute:NSLayoutAttributeLeft - multiplier:1.0 - constant:padding.left], - - [NSLayoutConstraint constraintWithItem:view1 - attribute:NSLayoutAttributeBottom - relatedBy:NSLayoutRelationEqual - toItem:superview - attribute:NSLayoutAttributeBottom - multiplier:1.0 - constant:-padding.bottom], - - [NSLayoutConstraint constraintWithItem:view1 - attribute:NSLayoutAttributeRight - relatedBy:NSLayoutRelationEqual - toItem:superview - attribute:NSLayoutAttributeRight - multiplier:1 - constant:-padding.right], - - ]]; -``` -Even with such a simple example the code needed is quite verbose and quickly becomes unreadable when you have more than 2 or 3 views. -Another option is to use Visual Format Language (VFL), which is a bit less long winded. -However the ASCII type syntax has its own pitfalls and its also a bit harder to animate as `NSLayoutConstraint constraintsWithVisualFormat:` returns an array. - -## Prepare to meet your Maker! - -Heres the same constraints created using MASConstraintMaker - -```obj-c -UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10); - -[view1 mas_makeConstraints:^(MASConstraintMaker *make) { - make.top.equalTo(superview.mas_top).with.offset(padding.top); //with is an optional semantic filler - make.left.equalTo(superview.mas_left).with.offset(padding.left); - make.bottom.equalTo(superview.mas_bottom).with.offset(-padding.bottom); - make.right.equalTo(superview.mas_right).with.offset(-padding.right); -}]; -``` -Or even shorter - -```obj-c -[view1 mas_makeConstraints:^(MASConstraintMaker *make) { - make.edges.equalTo(superview).with.insets(padding); -}]; -``` - -Also note in the first example we had to add the constraints to the superview `[superview addConstraints:...`. -Masonry however will automagically add constraints to the appropriate view. - -Masonry will also call `view1.translatesAutoresizingMaskIntoConstraints = NO;` for you. - -## Not all things are created equal - -> `.equalTo` equivalent to **NSLayoutRelationEqual** - -> `.lessThanOrEqualTo` equivalent to **NSLayoutRelationLessThanOrEqual** - -> `.greaterThanOrEqualTo` equivalent to **NSLayoutRelationGreaterThanOrEqual** - -These three equality constraints accept one argument which can be any of the following: - -#### 1. MASViewAttribute - -```obj-c -make.centerX.lessThanOrEqualTo(view2.mas_left); -``` - -MASViewAttribute | NSLayoutAttribute -------------------------- | -------------------------- -view.mas_left | NSLayoutAttributeLeft -view.mas_right | NSLayoutAttributeRight -view.mas_top | NSLayoutAttributeTop -view.mas_bottom | NSLayoutAttributeBottom -view.mas_leading | NSLayoutAttributeLeading -view.mas_trailing | NSLayoutAttributeTrailing -view.mas_width | NSLayoutAttributeWidth -view.mas_height | NSLayoutAttributeHeight -view.mas_centerX | NSLayoutAttributeCenterX -view.mas_centerY | NSLayoutAttributeCenterY -view.mas_baseline | NSLayoutAttributeBaseline - -#### 2. UIView/NSView - -if you want view.left to be greater than or equal to label.left : -```obj-c -//these two constraints are exactly the same -make.left.greaterThanOrEqualTo(label); -make.left.greaterThanOrEqualTo(label.mas_left); -``` - -#### 3. NSNumber - -Auto Layout allows width and height to be set to constant values. -if you want to set view to have a minimum and maximum width you could pass a number to the equality blocks: -```obj-c -//width >= 200 && width <= 400 -make.width.greaterThanOrEqualTo(@200); -make.width.lessThanOrEqualTo(@400) -``` - -However Auto Layout does not allow alignment attributes such as left, right, centerY etc to be set to constant values. -So if you pass a NSNumber for these attributes Masonry will turn these into constraints relative to the view’s superview ie: -```obj-c -//creates view.left = view.superview.left + 10 -make.left.lessThanOrEqualTo(@10) -``` - -Instead of using NSNumber, you can use primitives and structs to build your constraints, like so: -```obj-c -make.top.mas_equalTo(42); -make.height.mas_equalTo(20); -make.size.mas_equalTo(CGSizeMake(50, 100)); -make.edges.mas_equalTo(UIEdgeInsetsMake(10, 0, 10, 0)); -make.left.mas_equalTo(view).mas_offset(UIEdgeInsetsMake(10, 0, 10, 0)); -``` - -By default, macros which support [autoboxing](https://en.wikipedia.org/wiki/Autoboxing#Autoboxing) are prefixed with `mas_`. Unprefixed versions are available by defining `MAS_SHORTHAND_GLOBALS` before importing Masonry. - -#### 4. NSArray - -An array of a mixture of any of the previous types -```obj-c -make.height.equalTo(@[view1.mas_height, view2.mas_height]); -make.height.equalTo(@[view1, view2]); -make.left.equalTo(@[view1, @100, view3.right]); -```` - -## Learn to prioritize - -> `.priority` allows you to specify an exact priority - -> `.priorityHigh` equivalent to **UILayoutPriorityDefaultHigh** - -> `.priorityMedium` is half way between high and low - -> `.priorityLow` equivalent to **UILayoutPriorityDefaultLow** - -Priorities are can be tacked on to the end of a constraint chain like so: -```obj-c -make.left.greaterThanOrEqualTo(label.mas_left).with.priorityLow(); - -make.top.equalTo(label.mas_top).with.priority(600); -``` - -## Composition, composition, composition - -Masonry also gives you a few convenience methods which create multiple constraints at the same time. These are called MASCompositeConstraints - -#### edges - -```obj-c -// make top, left, bottom, right equal view2 -make.edges.equalTo(view2); - -// make top = superview.top + 5, left = superview.left + 10, -// bottom = superview.bottom - 15, right = superview.right - 20 -make.edges.equalTo(superview).insets(UIEdgeInsetsMake(5, 10, 15, 20)) -``` - -#### size - -```obj-c -// make width and height greater than or equal to titleLabel -make.size.greaterThanOrEqualTo(titleLabel) - -// make width = superview.width + 100, height = superview.height - 50 -make.size.equalTo(superview).sizeOffset(CGSizeMake(100, -50)) -``` - -#### center -```obj-c -// make centerX and centerY = button1 -make.center.equalTo(button1) - -// make centerX = superview.centerX - 5, centerY = superview.centerY + 10 -make.center.equalTo(superview).centerOffset(CGPointMake(-5, 10)) -``` - -You can chain view attributes for increased readability: - -```obj-c -// All edges but the top should equal those of the superview -make.left.right.and.bottom.equalTo(superview); -make.top.equalTo(otherView); -``` - -## Hold on for dear life - -Sometimes you need modify existing constraints in order to animate or remove/replace constraints. -In Masonry there are a few different approaches to updating constraints. - -#### 1. References -You can hold on to a reference of a particular constraint by assigning the result of a constraint make expression to a local variable or a class property. -You could also reference multiple constraints by storing them away in an array. - -```obj-c -// in public/private interface -@property (nonatomic, strong) MASConstraint *topConstraint; - -... - -// when making constraints -[view1 mas_makeConstraints:^(MASConstraintMaker *make) { - self.topConstraint = make.top.equalTo(superview.mas_top).with.offset(padding.top); - make.left.equalTo(superview.mas_left).with.offset(padding.left); -}]; - -... -// then later you can call -[self.topConstraint uninstall]; -``` - -#### 2. mas_updateConstraints -Alternatively if you are only updating the constant value of the constraint you can use the convience method `mas_updateConstraints` instead of `mas_makeConstraints` - -```obj-c -// this is Apple's recommended place for adding/updating constraints -// this method can get called multiple times in response to setNeedsUpdateConstraints -// which can be called by UIKit internally or in your code if you need to trigger an update to your constraints -- (void)updateConstraints { - [self.growingButton mas_updateConstraints:^(MASConstraintMaker *make) { - make.center.equalTo(self); - make.width.equalTo(@(self.buttonSize.width)).priorityLow(); - make.height.equalTo(@(self.buttonSize.height)).priorityLow(); - make.width.lessThanOrEqualTo(self); - make.height.lessThanOrEqualTo(self); - }]; - - //according to apple super should be called at end of method - [super updateConstraints]; -} -``` - -### 3. mas_remakeConstraints -`mas_updateConstraints` is useful for updating a set of constraints, but doing anything beyond updating constant values can get exhausting. That's where `mas_remakeConstraints` comes in. - -`mas_remakeConstraints` is similar to `mas_updateConstraints`, but instead of updating constant values, it will remove all of its constraints before installing them again. This lets you provide different constraints without having to keep around references to ones which you want to remove. - -```obj-c -- (void)changeButtonPosition { - [self.button mas_remakeConstraints:^(MASConstraintMaker *make) { - make.size.equalTo(self.buttonSize); - - if (topLeft) { - make.top.and.left.offset(10); - } else { - make.bottom.and.right.offset(-10); - } - }]; -} -``` - -You can find more detailed examples of all three approaches in the **Masonry iOS Examples** project. - -## When the ^&*!@ hits the fan! - -Laying out your views doesn't always goto plan. So when things literally go pear shaped, you don't want to be looking at console output like this: - -```obj-c -Unable to simultaneously satisfy constraints.....blah blah blah.... -( - "=5000)]>", - "", - "", - "" -) - -Will attempt to recover by breaking constraint -=5000)]> -``` - -Masonry adds a category to NSLayoutConstraint which overrides the default implementation of `- (NSString *)description`. -Now you can give meaningful names to views and constraints, and also easily pick out the constraints created by Masonry. - -which means your console output can now look like this: - -```obj-c -Unable to simultaneously satisfy constraints......blah blah blah.... -( - "", - "= 5000>", - "", - "" -) - -Will attempt to recover by breaking constraint -= 5000> -``` - -For an example of how to set this up take a look at the **Masonry iOS Examples** project in the Masonry workspace. - -## Where should I create my constraints? - -```objc -@implementation DIYCustomView - -- (id)init { - self = [super init]; - if (!self) return nil; - - // --- Create your views here --- - self.button = [[UIButton alloc] init]; - - return self; -} - -// tell UIKit that you are using AutoLayout -+ (BOOL)requiresConstraintBasedLayout { - return YES; -} - -// this is Apple's recommended place for adding/updating constraints -- (void)updateConstraints { - - // --- remake/update constraints here - [self.button remakeConstraints:^(MASConstraintMaker *make) { - make.width.equalTo(@(self.buttonSize.width)); - make.height.equalTo(@(self.buttonSize.height)); - }]; - - //according to apple super should be called at end of method - [super updateConstraints]; -} - -- (void)didTapButton:(UIButton *)button { - // --- Do your changes ie change variables that affect your layout etc --- - self.buttonSize = CGSize(200, 200); - - // tell constraints they need updating - [self setNeedsUpdateConstraints]; -} - -@end -``` - -## Installation -Use the [orsome](http://www.youtube.com/watch?v=YaIZF8uUTtk) [CocoaPods](http://github.com/CocoaPods/CocoaPods). - -In your Podfile ->`pod 'Masonry'` - -If you want to use masonry without all those pesky 'mas_' prefixes. Add #define MAS_SHORTHAND to your prefix.pch before importing Masonry ->`#define MAS_SHORTHAND` - -Get busy Masoning ->`#import "Masonry.h"` - -## Code Snippets - -Copy the included code snippets to ``~/Library/Developer/Xcode/UserData/CodeSnippets`` to write your masonry blocks at lightning speed! - -`mas_make` -> ` [<#view#> mas_makeConstraints:^(MASConstraintMaker *make) { - <#code#> - }];` - -`mas_update` -> ` [<#view#> mas_updateConstraints:^(MASConstraintMaker *make) { - <#code#> - }];` - -`mas_remake` -> ` [<#view#> mas_remakeConstraints:^(MASConstraintMaker *make) { - <#code#> - }];` - -## Features -* Not limited to subset of Auto Layout. Anything NSLayoutConstraint can do, Masonry can do too! -* Great debug support, give your views and constraints meaningful names. -* Constraints read like sentences. -* No crazy macro magic. Masonry won't pollute the global namespace with macros. -* Not string or dictionary based and hence you get compile time checking. - -## TODO -* Eye candy -* Mac example project -* More tests and examples - diff --git a/iOS_Tips/Pods/Pods.xcodeproj/project.pbxproj b/iOS_Tips/Pods/Pods.xcodeproj/project.pbxproj deleted file mode 100644 index b7702e85..00000000 --- a/iOS_Tips/Pods/Pods.xcodeproj/project.pbxproj +++ /dev/null @@ -1,2981 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 51; - objects = { - -/* Begin PBXBuildFile section */ - 0096B5A8BA8E4F2BFD8839D0FE7CD696 /* MASLayoutConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C3AE50C738678F7E82112FDB4A8E70C /* MASLayoutConstraint.m */; }; - 00986AC306A77F203295619535AF853F /* GPUImagePerlinNoiseFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 20BC00B3DDB29110A58176CE51605FD4 /* GPUImagePerlinNoiseFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 00BC50439EB78BC024C8271F5FC50579 /* GPUImageMultiplyBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 61E2A63537B14F7A60668071C08241DE /* GPUImageMultiplyBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 012A87349E85A8CA10E4AD07361E6D86 /* GPUImageExclusionBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E272A947106122CD1F27C631D653DA4 /* GPUImageExclusionBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 0172B10DE456AE5736FD887F0CEB74AF /* YYWebImageOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 48F476DACC4D9202F44C5407ACDA8410 /* YYWebImageOperation.m */; }; - 01C95E537574ABC59799352D0AD70028 /* GPUImageRawDataInput.m in Sources */ = {isa = PBXBuildFile; fileRef = D3B1D10EA9F731D0F5F681A4CAEDE5D6 /* GPUImageRawDataInput.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 01DA5C61D7BA40621EC5460EED38200E /* GPUImageBilateralFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = C6C160D9019636230267BE3289CF1EF8 /* GPUImageBilateralFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 029F819514A66087992EE035796FB9F2 /* GPUImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A1109257C4F91B78B674D3ED606F875 /* GPUImage.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 03182402D9CC511877544D993D1FFA9E /* GPUImageSepiaFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 71669CD78F52A5CA28F626C8A16A194C /* GPUImageSepiaFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 0319334D0B9B8B673C0BAEAC13FFE1FB /* GPUImageMissEtikateFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E01E00886BEDC0765B232733C255C1C /* GPUImageMissEtikateFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 032FBF65C1B7C211B28D54B160B1612D /* GPUImageHarrisCornerDetectionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = FABBE2C4A63D29A135EB2E35769CF66E /* GPUImageHarrisCornerDetectionFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 044D6E9E03CB8ECD6E58801E7C6C527A /* GPUImageHueBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = C080FC8084166668F65F78ED0AA4A69B /* GPUImageHueBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 05C61347A8543E701B094D915BD5C838 /* GPUImageRawDataOutput.m in Sources */ = {isa = PBXBuildFile; fileRef = A1BDF8E1519711BE1634F7B98C1BE5A4 /* GPUImageRawDataOutput.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 06EB7CC11A03D75FD2DA07D284685F73 /* YYModel-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 55DC707CC4179395588164EA0C8D4DF8 /* YYModel-dummy.m */; }; - 076971540B7FE20B66B50A6DBEC80064 /* GPUImageLineGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 3FA9A4C47EC9F4059DAB7AADC578E5AF /* GPUImageLineGenerator.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 089AB5F862A3EF9A0218037D8C73DB9D /* GPUImageColorDodgeBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F83E8DB73761A3F59617E28A1A9351E /* GPUImageColorDodgeBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 097C32010AB76B1FE9C162A2A1876ECE /* GPUImagePolkaDotFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B933CA3EC0B18A8DB363F31A85D1268 /* GPUImagePolkaDotFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 0AAAED8B75B6AD69452465FD9596FD0D /* YYCache-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F066292FE00E22395481D12B85DCF15 /* YYCache-dummy.m */; }; - 0AEA27BF85DB689C14FB34D0FEBDB851 /* GPUImageTextureOutput.m in Sources */ = {isa = PBXBuildFile; fileRef = 621DA413177A46757ACA5C0C17FE0C8C /* GPUImageTextureOutput.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 0B1B3B1DB51A07B13F0A363BC22F59A2 /* GPUImageChromaKeyBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = B11AD2552FDB15FF1C538A2621C8454E /* GPUImageChromaKeyBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 0B6FE241DFB3843F412B6468A8F4D2E2 /* YYKVStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = E17C159C87DA98A853415C410757984D /* YYKVStorage.m */; }; - 0B8E7DAF6EF79317C606AAF3BDF1B166 /* NSObject+YYModel.h in Headers */ = {isa = PBXBuildFile; fileRef = D4336A5672C30CDB1EBF2ABE41670A08 /* NSObject+YYModel.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 0BB1F971030D1518F9CF319E9D4DC1AD /* GPUImageHistogramEqualizationFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = B93FEAD1B3DB233D4B21EB7567E5E3A0 /* GPUImageHistogramEqualizationFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 0BD4E21F29F34FB17265C7BD9887C84D /* YYMemoryCache.h in Headers */ = {isa = PBXBuildFile; fileRef = AFB401E05E9C8DEA8B23609216EB64E5 /* YYMemoryCache.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 0CE8DDB17A7E7660B35605B8139FE3B3 /* GPUImageToneCurveFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = FB638C9B72C7E7F1B16A43E90A8BF20E /* GPUImageToneCurveFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 0D257609B3B75A4CBFFBD05133D61391 /* YYImageCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = ECF46625DB05146F6E98B2E53445EFC8 /* YYImageCoder.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 0DFAF263663A062127902C54C6983A09 /* GPUImageAdaptiveThresholdFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 00D7FBFB94E92C7589C179A64EA9B9E1 /* GPUImageAdaptiveThresholdFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 0E7080397F8B5AE0B8A3D7AF280BB094 /* GPUImageGaussianBlurFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 291AEAB6C085560A71960DDDD62ACD1A /* GPUImageGaussianBlurFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 0F1318DD0AD76D96EB95DA11FE97A2C1 /* GPUImageLightenBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = DFE90665F8A100159773904C5A2F8967 /* GPUImageLightenBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 0F9FB5E7A6BC661FC3F8852F4FC69D86 /* GPUImageFramework.h in Headers */ = {isa = PBXBuildFile; fileRef = 71F455391A9616D714CC8874A51F7EE6 /* GPUImageFramework.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 115ACCE253A886181B55773DDC70D6ED /* MASViewConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = F1A5C4493663A851186ED81654C1C388 /* MASViewConstraint.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 11E619FEA09D4BF81ACE5C2921D00B19 /* GPUImageBoxBlurFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 202D068CFDA5C22DA922D9FD075D1806 /* GPUImageBoxBlurFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 15237712FC9D46A2037F26E70353D2EA /* GPUImageOverlayBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 80F0F94732C9BFC491C85042FF7D14A5 /* GPUImageOverlayBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 1646382FCB4B9AE1130EC8ACEDA90598 /* YYImage.m in Sources */ = {isa = PBXBuildFile; fileRef = AC24421A335214257CD3748289F31E7D /* YYImage.m */; }; - 168FB6A74A76E3979C4E47BBADF7DBFE /* GPUImageVideoCamera.h in Headers */ = {isa = PBXBuildFile; fileRef = 3FE5C658FDFFD20E3BCD7C36D40923A3 /* GPUImageVideoCamera.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 16B07BF8A572D2B926D42CEB9A6491ED /* GPUImageWeakPixelInclusionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 092384ABCABB5474EAF3E9D8F02DF29F /* GPUImageWeakPixelInclusionFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 16BEA757C13C39AF5F5FCDB143AF53A9 /* GPUImagePinchDistortionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 870991E39050AAA48FC751AB989A0CEE /* GPUImagePinchDistortionFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 17EF299F850C9C8628F34469C37013DD /* GPUImageAddBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C250AC091347FFBBF15D1616FB339BA /* GPUImageAddBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 180A83B65E6DDB6EB746870CF41325A1 /* GPUImageDivideBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 40BEB1831EED3C7A7E80C4057D3DA022 /* GPUImageDivideBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 1860650813D77F0191C8979285AEFC40 /* GPUImageChromaKeyFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 3193AAC04525E3412D850A3D7AD99612 /* GPUImageChromaKeyFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 18A409862FE2BD9E7AEB7F8C443A2EEA /* GPUImageAverageLuminanceThresholdFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 722AE0C698ABB0490DECD454A56B78D5 /* GPUImageAverageLuminanceThresholdFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 19436D75D39F5FEC5CFC10989E8D21E7 /* GPUImageRGBClosingFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BBCCF9A4A7C3B7E1D6638E2D15B2B83 /* GPUImageRGBClosingFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 19E2053A876C0F6A156C00BC10116E4B /* GPUImageSobelEdgeDetectionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 38948BFE21048F7C6D91B1281E521F1B /* GPUImageSobelEdgeDetectionFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 1C02510C4D6500A7A376A57169D955DC /* GPUImageVoronoiConsumerFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 83FF0DCFBB0CF862F4E2370485036696 /* GPUImageVoronoiConsumerFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 1E5D56FF58658F9F45723CA2940489EE /* MASConstraintMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = C8E3D2D6BFE3A6A5011A9A78D5041D6B /* MASConstraintMaker.m */; }; - 1EE8655B7099DFDF91AB09854A782014 /* GPUImageParallelCoordinateLineTransformFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = E9AD39DB2F1E55880567989B269FAC3D /* GPUImageParallelCoordinateLineTransformFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 1FDB79E9550E8876B19B618E78F53309 /* GPUImagePixellateFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = D2C5AB16BD22FA6146D9733E98392177 /* GPUImagePixellateFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 203ECB87C9B02B1B8BAAF78D8A62A1DE /* GPUImageMonochromeFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = A21D094A16257D428FAE0B259CD960F5 /* GPUImageMonochromeFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 20E327AE2E71D49D773CD130992DCE16 /* GPUImageRGBOpeningFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = CD17316111B32EDFB414E2DB7107670D /* GPUImageRGBOpeningFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 21D3457D9AA054C835BB17F56A79041D /* GPUImageMissEtikateFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = F448306B3687298FFAD025EB2DDD73EF /* GPUImageMissEtikateFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 2280B1BE277126BD771028C12BD6A59E /* GPUImageLocalBinaryPatternFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = DD88158BB140DD22AAFBE5A81587E42D /* GPUImageLocalBinaryPatternFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 23AE0543B10B548DC5EA894199172600 /* GPUImageHSBFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 3262E2097D957FBD0444889742CB1C80 /* GPUImageHSBFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 23FBD272CA96DCB898B9271EB71F7D51 /* GPUImageRGBDilationFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 31F4DFCE2BAF8205326A79D123842D37 /* GPUImageRGBDilationFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 247F37C5897D9F02668D125EFFB75B59 /* GPUImagePicture+TextureSubimage.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E9095CF9176D72147052B3FD215EF7F /* GPUImagePicture+TextureSubimage.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 24D5BD2976FC932DE4ADAEB93A0479F6 /* GPUImageMaskFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 21B2916276232C456951467038D3E2FF /* GPUImageMaskFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 2516CA9197EA00286EFFAAD3A11402C5 /* GPUImageLookupFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = D5AB4ADA23B1748AB0ED4BB1DB527C69 /* GPUImageLookupFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 2607BC411D43A5440E53234F8AB482C8 /* CALayer+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = C05B47CD66C71D9CAAF1627186D1C6DE /* CALayer+YYWebImage.m */; }; - 26A8C66FE48977B328358F9F2BF641A0 /* GPUImageGaussianBlurFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = E170213BF8AB60A888762910A4745B2B /* GPUImageGaussianBlurFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 2702708CF3F7B8F8C71CD04CE0E0407B /* GPUImageWhiteBalanceFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FEA48B785F73A0492D9D729976FD86B /* GPUImageWhiteBalanceFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 28A79E1849CD533B44B7BEFEB7E23FCD /* GPUImageMosaicFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 9ADFE335A749F6242A5501FC31B4EDB2 /* GPUImageMosaicFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 29065AD49ABF0ECB23CF05B75B448A05 /* GPUImageTwoPassFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = A7E3C6A77B24BBCAF360A95E890B7F76 /* GPUImageTwoPassFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 293D641452CDA50B1DE046BB9B5105B1 /* GPUImageHarrisCornerDetectionFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2CE39347324DF5B3FC2761B6D191DA9C /* GPUImageHarrisCornerDetectionFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 29B8B5BB202D5EAB464A41B22DE1B5BC /* GPUImageSharpenFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = BBB88E5B5C49D8640CAD758ACB9A6965 /* GPUImageSharpenFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 2A056E4E0CB5341CF83B2902850B496C /* GPUImageLowPassFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B86F3F70B22B26EC06C5C412D9B9733 /* GPUImageLowPassFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 2A0981C33E3E8401ECD3482994B3BCBF /* GPUImageTransformFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E48FED45DEF3A3929689CA91C2C802C /* GPUImageTransformFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 2AD9C4FEB3BDBD7AFABEFC1D2D16A04C /* GPUImageSepiaFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DADF97A372B96269C7E574FFD19EA84 /* GPUImageSepiaFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 2B3F38B85111F3D785A806C971FE2F23 /* GPUImageLevelsFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 6460B60CAEB361F43B409D943DD5919E /* GPUImageLevelsFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 2C41DD251C08A607AB0D65FD88E3A066 /* YYCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 160895B89A8B29B177F36E3AF17C2C11 /* YYCache.m */; }; - 2D98C578934FC343F36EE6FE89BFDB11 /* GPUImageHueBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = F53E198F369DD7B29FDFD1E67D7FEF92 /* GPUImageHueBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 2DF0E53968A631FCBDD17A7F6476285E /* GPUImageBilateralFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 77A6428D36533AF050B1E9F92BF82FD8 /* GPUImageBilateralFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 2EEFD3082E5C0D943EB927EE0E18FCB1 /* GPUImageSoftEleganceFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 525E00D440284C93311DF077591CDA15 /* GPUImageSoftEleganceFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 2F701A9E49DDA3C1A240D28CC2285636 /* GPUImageHoughTransformLineDetector.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CA047F4F7C29EBD892E71642C0B6FD0 /* GPUImageHoughTransformLineDetector.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 2F71447BF395AFE0424A0173E1D3941B /* GPUImageColorBurnBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 917747700EB9C26B29A0199F357B3B12 /* GPUImageColorBurnBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 307069FED8CBB5FD30C15FC7C0A62182 /* GPUImageFramebuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = DEC5E896CBBBB4368B3D73E3B6DF98AF /* GPUImageFramebuffer.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 31D6CA90C42E5C93B586480348B000A3 /* GPUImageSoftLightBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AF69C635DEFF07CF03F7EC5C93EECC6 /* GPUImageSoftLightBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 32EE5B60261B8BC36AFE11DF61DF7FE8 /* GPUImageAmatorkaFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 42C7A8AF75309C3CA628C0B8775A0F0B /* GPUImageAmatorkaFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 332F47F53E6998F86527587E29CA5D9E /* NSObject+YYModel.m in Sources */ = {isa = PBXBuildFile; fileRef = B72EC130B00BB80835F63C15885EEB06 /* NSObject+YYModel.m */; }; - 3477F92624D8C9133F3041A79491FA59 /* GPUImageBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 571C0946C15922F37A4FF9DC53636F23 /* GPUImageBuffer.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 3490572882298AE0C0313A3214E36B06 /* GPUImagePerlinNoiseFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = E75C8905888A317693F48FC06029AC84 /* GPUImagePerlinNoiseFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 3506EE5862108B2A8C41A20D99355F18 /* GPUImageDirectionalSobelEdgeDetectionFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5D87CE6703E1941A5580858F307A6D /* GPUImageDirectionalSobelEdgeDetectionFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 3561CB57DDD73F8AFA84BF0E76ABB946 /* GPUImageLanczosResamplingFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 37B3E429270DF855D2663E4BE0DCE666 /* GPUImageLanczosResamplingFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 35CB55CABE07087AB199A17790384536 /* GPUImageStillCamera.m in Sources */ = {isa = PBXBuildFile; fileRef = 8A630DEACFD6C33B16EABFCBA7B10B6B /* GPUImageStillCamera.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 35CBA794B313B0A704877F12F8D1ABFA /* GPUImageMovie.m in Sources */ = {isa = PBXBuildFile; fileRef = 68CD24B140838D08A6E5DD6A70FD8923 /* GPUImageMovie.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 36C40AACF03A24A362EB39C429249959 /* GPUImagePicture+TextureSubimage.m in Sources */ = {isa = PBXBuildFile; fileRef = C1703B1CC3A8EF46F7E0BC97EF312B15 /* GPUImagePicture+TextureSubimage.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 3726AB2B00A42F73A0124907B9ACC3A9 /* GPUImageTwoInputCrossTextureSamplingFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 59C6E40234EEDDD4087F2CFFF63582D0 /* GPUImageTwoInputCrossTextureSamplingFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 37CE879D95C30445360AD6D0C1FA7CC4 /* GPUImageSourceOverBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 074228E092340DEFE657CAF4F22AF822 /* GPUImageSourceOverBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 394A129E507245FF105966F376AB1C41 /* GPUImageTiltShiftFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = C0C8CE6B752A1D6DC908E8EBC379636C /* GPUImageTiltShiftFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 39A315F02A4702D5670CB93A5C9BEEEA /* GPUImageZoomBlurFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 0274C1DACB9A0794CFD00841FAE59E3D /* GPUImageZoomBlurFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 3A87E2458C94D01EEEC9538DB032AC9D /* GPUImageHistogramGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 8CEEEBC4B26A07F17E3509809AE7C514 /* GPUImageHistogramGenerator.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 3A8C1A0178B01AD26430FC5B130F5E0D /* GPUImageGrayscaleFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 751129785F65D4A3EA3332CE56D280DD /* GPUImageGrayscaleFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 3AA724CDE56C03778D0D8C6C614C28E5 /* GPUImageCrosshatchFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 8897A494B1993654654BD96F0352C036 /* GPUImageCrosshatchFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 3B055578547C840E193F2BCB94BF4C02 /* YYSpriteSheetImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D9580A4EE8AFE8DD3E68A776F88E557B /* YYSpriteSheetImage.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 3B7BB04082AF2620E265A3088B2B4D0D /* GPUImageAlphaBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 462A9647EF473D7371FF63E7DF5E9FB1 /* GPUImageAlphaBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 3BF8C851F81EBF3411E82F9E1C793DAE /* GPUImageLanczosResamplingFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = B015E5C22E17335E3A77DFA9908BB606 /* GPUImageLanczosResamplingFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 3E31203B357CAE0A15DB0850091BB79B /* GPUImagePicture.h in Headers */ = {isa = PBXBuildFile; fileRef = B8113E2BE805826C2206219087AF2FEB /* GPUImagePicture.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 3E63B4119CD44378A1093476E54E2474 /* GPUImageBulgeDistortionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = B600C9B478F0D9AD34362F46737F82C5 /* GPUImageBulgeDistortionFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 40B61558F93F007E0435D240EBA4A5E4 /* GPUImageKuwaharaFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 82C6F83D1D031E0F313B5E11137E072B /* GPUImageKuwaharaFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 410F226804ABA48DDADFB2C40CDBDF90 /* UIImageView+YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = B4080351977D02914F701E5AF2820E28 /* UIImageView+YYWebImage.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 41CC5477C7CC1FCAFA0486B4710DB563 /* GPUImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 295A7F01A1F9CE9A049C72379F8EC892 /* GPUImageView.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 42947699890A199B08A896144A878D80 /* MASViewAttribute.h in Headers */ = {isa = PBXBuildFile; fileRef = 3E7EB13B2D474F8DE4852C033BF689FB /* MASViewAttribute.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 42EF3318A12DEA2D31B64DA77EFE2FB3 /* GPUImageHistogramFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 8472059D35BC092DEF41EC2604D795FB /* GPUImageHistogramFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 43392130FF1BA22BCD40F201F94DF7C0 /* GPUImageExposureFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = EA2A44D6FF0F9ACEE1DADC1A14F2854D /* GPUImageExposureFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 436BC7F553DA755100A82BA0F05483D5 /* GPUImageHighlightShadowFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 10015A94BC5970A447441E41EFA84CC4 /* GPUImageHighlightShadowFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 441A09967A85ABE244200F5B5E6EC9A3 /* GPUImageHighlightShadowFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2988FF2F5DA771E11045F136F9BD4F0A /* GPUImageHighlightShadowFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 443DCC9EACB122059801B326E959DD2D /* YYImageCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E5E02B856C988A000B10E5E5512B56A /* YYImageCoder.m */; }; - 4478C2AC2D38DD361F0F23A0C5B79C41 /* GPUImageVignetteFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 9FE18CDF175FE55AE74C18EF88123854 /* GPUImageVignetteFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 44ABF3A14712E8B399B82DF3A2967A0A /* GPUImageMosaicFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = D24C3AB3AE7CD24FB83746C901F281BA /* GPUImageMosaicFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 44B2A991A256252267B769DAE2328918 /* GPUImageFilterPipeline.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EAC8FE75CB608768A2CEA2F31EDF290 /* GPUImageFilterPipeline.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 463C05A520F9F187AA59A4532ED2DC98 /* GPUImageSmoothToonFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = B81F4796AC0D72D4F1B2047D5A0E8AC0 /* GPUImageSmoothToonFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 46692A2E77157B00827182C8DC686F72 /* View+MASAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = C4193CD804FDADD82E3B8FE1883F6D29 /* View+MASAdditions.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 468E8582953579A3237E9B07A4290809 /* GPUImageSphereRefractionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = B8043D2AA30371284EF62F7AE00669A6 /* GPUImageSphereRefractionFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 46FBEAFB68F195DBF93DEE185B5B821E /* GPUImageToneCurveFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D6604B45B92B4410C171D7E0C6B4939 /* GPUImageToneCurveFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 4720A768E07B694895699C1A455D433B /* YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 8DEFD1186E4AE1006B42EF52538073A3 /* YYWebImage.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 472C8A534A872D0B6D85286483E6D753 /* YYDiskCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B515D86A399467A37FA4BA15B8B0887 /* YYDiskCache.m */; }; - 47699E5E05076562ACB35B1C71C13347 /* GPUImageLinearBurnBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AF1FBA24B5573418B3316CD3B2CAF8B /* GPUImageLinearBurnBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 47AD0E032FC7AA3EEB930742976CB88D /* GPUImageLineGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 2276B332FA8EDDC35FE32348D3EB368C /* GPUImageLineGenerator.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 47DDAD3895F510382B2D81B70B620529 /* GPUImageXYDerivativeFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = C8EFB486F7011880B250BD588AF6B03A /* GPUImageXYDerivativeFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 4B1D960FF8280CC54413CABB5D2F2A2E /* GPUImageiOSBlurFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 79F32CA2AC9383860E5A101F3891F01F /* GPUImageiOSBlurFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 4B29282458432763173D54C2F5B21719 /* GPUImageThresholdedNonMaximumSuppressionFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 99007670CCD9C91A8F619B9CEA906413 /* GPUImageThresholdedNonMaximumSuppressionFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 4B3E8A322CC1A802C18F4D2BC353D07B /* GPUImageSobelEdgeDetectionFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = E16FF3BBD2E461C6B31F4D28293DEC1F /* GPUImageSobelEdgeDetectionFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 4BA1A0406DD78FE4D11CF77A531CF5C3 /* GPUImageMovieComposition.m in Sources */ = {isa = PBXBuildFile; fileRef = E9BE79BD70E8A2BBB669B77DE76E87B2 /* GPUImageMovieComposition.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 4CE091F886EC6324673EFE0AEBBEA0FE /* MASConstraint+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = F73A13F286165F4836D8D7D4AAC5C284 /* MASConstraint+Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 4D71EEBCF009BD38CDBDCB7FF48E9D3D /* YYMemoryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = D6DEC4D0701355737F042ABE9389A98E /* YYMemoryCache.m */; }; - 4EC8896E34902FB81D8ECE3CBCE43F22 /* GPUImageLaplacianFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = B49CFF15CC2A8F9BE7A7F6E9858CF4A9 /* GPUImageLaplacianFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 4F9FCCD41B5DB358F6471868A7AF0FF8 /* GPUImageDifferenceBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DF64883F152558549C53B4951455B9B /* GPUImageDifferenceBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 4FCB792F4D09A7A6EC830F3F09E57E3E /* GPUImageHistogramGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 49E415F2BA5768C469A662DF8C823B3C /* GPUImageHistogramGenerator.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 4FF8537039C6FB3E87DCC9F4A0390D2F /* GPUImageErosionFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F2C1EF174D0C89A1ECD8D871814D3C5 /* GPUImageErosionFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 501A410F165BE59627833296C733AD55 /* GPUImageCannyEdgeDetectionFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = A0B5C9037C5004A4E5533B5FE12C1BE7 /* GPUImageCannyEdgeDetectionFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 50C2B02BB91270A6EB35F60571F06E54 /* GPUImageThresholdSketchFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = BBE357EF73F92D80EB2A32F6C9ADC813 /* GPUImageThresholdSketchFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 5107E16FCC65F65EC492836E724F0BFE /* GPUImageFramebufferCache.m in Sources */ = {isa = PBXBuildFile; fileRef = EE42EB7F34AB1582A3A5744A834BD119 /* GPUImageFramebufferCache.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 527FC696CFE9E79296FAE22B581EDF93 /* GPUImageOutput.h in Headers */ = {isa = PBXBuildFile; fileRef = 43471FC538F7533EBC5AA010B09E0958 /* GPUImageOutput.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 52914E62535E485DD3712D4563197A4E /* GPUImageFASTCornerDetectionFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 71D502A5B132B8E2D515B9A975C85309 /* GPUImageFASTCornerDetectionFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 531132F9F82136C7E0089691EF9D1836 /* GPUImagePrewittEdgeDetectionFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 5021D951EBE0EE5ACBFF0A1D5BF60EC2 /* GPUImagePrewittEdgeDetectionFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 53C1EE743E9410FE7276FA94A236289F /* GPUImagePrewittEdgeDetectionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 414E85F24E79E32F8EA8031796253C7F /* GPUImagePrewittEdgeDetectionFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 54A44219E060C802B200A9A82B8F403C /* YYImage-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6641303C0E807B1DB7DE0B014814E30A /* YYImage-dummy.m */; }; - 54AC6004FE0F928E06D79A88364B08C2 /* GPUImageThresholdEdgeDetectionFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 240C513A27F958A5DE57B92A02EA4229 /* GPUImageThresholdEdgeDetectionFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 54C308204D830A23ADC5E7E77F11FAD9 /* GPUImageAverageColor.m in Sources */ = {isa = PBXBuildFile; fileRef = F3FB9DB94CA9285178C40FCA640755A3 /* GPUImageAverageColor.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 55E840167C4D134B42027183FE12AA5F /* GPUImageMotionBlurFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 488651029866527C3B2644FD81E92587 /* GPUImageMotionBlurFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 572D05B146EAA3EF5530A0D0E34904A0 /* MASViewConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = E48C3FA68C009689F44837B466401AA1 /* MASViewConstraint.m */; }; - 57AE9C0FF97670789648FCFFCF23A28F /* YYCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E5AC46F45E4451E72AC537BB70B1812 /* YYCache.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 5934E71FD7CE977980F1F3E0FBB0589D /* GPUImageRGBErosionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 080F15FCC36CE02B5AA7B6A38D2A6F1C /* GPUImageRGBErosionFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 596D6C47B56C81DAAF4AEFD6EBE90E4E /* YYAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = BAA4F2B29058FE252D949D0C32390318 /* YYAnimatedImageView.m */; }; - 59EA578EED8BAC126FDC60C32AE11521 /* NSLayoutConstraint+MASDebugAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D6496F72C325C292BB59F2D94A654A2 /* NSLayoutConstraint+MASDebugAdditions.m */; }; - 5C176EB69346C558230FA62C8FF9445C /* GPUImageSoftEleganceFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = AB5B9F20F2CC4E7B1E64873C8F4C7DEB /* GPUImageSoftEleganceFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 5D6023B887E0BCB76115B617532A5390 /* YYWebImageOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 019AEDB1F84B03733946BD4BAABB969C /* YYWebImageOperation.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 5E8E7BB740E167DE322057CBF4E4ACFF /* GPUImageLuminanceRangeFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = A22790AD2F8E9488E3E272090ACDE88B /* GPUImageLuminanceRangeFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 5EAB582B3DAE152158E656DDCD462408 /* GPUImageGrayscaleFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C138582918D37CF364E6D3C9898D68F /* GPUImageGrayscaleFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 5ECA6D4026DE7F909DD178B2DBF665FB /* GPUImageTwoPassTextureSamplingFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = F4CCD104A376890D8A12507C5239B8B1 /* GPUImageTwoPassTextureSamplingFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 5F285812B5CDF5D9FD0533372DA93B36 /* GPUImageRawDataInput.h in Headers */ = {isa = PBXBuildFile; fileRef = F8F996C485D25C0141065FF489D1BA53 /* GPUImageRawDataInput.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 5F7E38F771E8D6181B8C72C5D8C10C14 /* GPUImageFramebuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 838B4FE7CBA73D00A0885739EF9AA694 /* GPUImageFramebuffer.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 608A35BC3D8DA3484591875607E5D90C /* GPUImageColorBurnBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 73B8731A5CF568F198781C8412733FB0 /* GPUImageColorBurnBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 60CBB436C809283781907EA30C935F35 /* GPUImageContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 69BEFC89CA92FA91FB606E547079BABE /* GPUImageContext.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 63546D4E91CCFC991D704AA7E55D3EF4 /* GPUImageRGBClosingFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 56D2D8153149A60C61AB14238CE5A721 /* GPUImageRGBClosingFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 639230154DADB35273109F737BA51C7D /* UIButton+YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = F38E818E85AFE98DD31A606DB69D79D5 /* UIButton+YYWebImage.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 63F87C318437740E8202E4D3DD0826FA /* MASCompositeConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = AF50E9AAD19F008B707D7D8F7EACA2D3 /* MASCompositeConstraint.m */; }; - 64000452C59702057A087C4A76CFE687 /* GPUImagePosterizeFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 69E5EB77E2A5E329FE60A250611BF2FC /* GPUImagePosterizeFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 647A2EAB797A3D68176CC3AC101F2F1A /* GPUImageFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = DCDB8D6607C77835C1EC75EB9F36E5C5 /* GPUImageFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 6480781DB47D05BF915975DC8A7B61BE /* GPUImageKuwaharaRadius3Filter.h in Headers */ = {isa = PBXBuildFile; fileRef = 29114F4BF994DD99DA8B15BD714B5488 /* GPUImageKuwaharaRadius3Filter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 65E88072A2BDC576BFC85E67EF9FBBC6 /* MASUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = CE8B3FE478847A7AAD2B21BC40809B56 /* MASUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 66ED1E95B81405D02E043A58017D95F0 /* GPUImageMotionBlurFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 34804E531C9635A205640CD71C357B77 /* GPUImageMotionBlurFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 67EE0DDBEB2517F5B04D04B93226A9BC /* GPUImagePicture.m in Sources */ = {isa = PBXBuildFile; fileRef = B4F3FFA58FE342F21294920E38929E3F /* GPUImagePicture.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 686489D54A6EA62779A0F4C34D29934F /* GPUImageMovieComposition.h in Headers */ = {isa = PBXBuildFile; fileRef = 00BAF7C4E2492F63C9589A48B9A174F5 /* GPUImageMovieComposition.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 68BCD2A517C5CB6DF61FE1187DD63266 /* GPUImageColorDodgeBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F6459CEEE271680736FA479FD981BD4 /* GPUImageColorDodgeBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 694F36DE0A2C6B75B53CA842A09C450C /* GPUImageDissolveBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 27A2C6937109C3C8643FB3E370CDBE29 /* GPUImageDissolveBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 69FC4C251095ED7B8667F599EE032BF9 /* GPUImageHardLightBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 784B2008FD82B473DC377FEEC4B7EFD4 /* GPUImageHardLightBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 6A92349242C40DAA199A7FB7C7ACDCC1 /* GPUImageHalftoneFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B3AB6691A881BF883BB176FDAB07FBA /* GPUImageHalftoneFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 6AABC70C8EF035909F5A2D3DC6B5FA4A /* GPUImageTwoInputFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 30A8C055AB3C18A2E3FE4F47E4F66E5A /* GPUImageTwoInputFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 6B18BAD834E408DE82E33DB82DD63168 /* YYImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 094F16B0BD56037708312F6A3D1774F3 /* YYImage.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 6B40D4EB83F51507D03ACD5FDBBEF888 /* GPUImageDifferenceBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 64B98E97EBB4B89FF8C0A73B4905060A /* GPUImageDifferenceBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 6BA2489921F50583559CC1BB13DB8B42 /* MKAnnotationView+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9680F05DBD64586E9AB59F33EA7E289F /* MKAnnotationView+YYWebImage.m */; }; - 6CD33B44569EC746123A3B3684E2CE91 /* GPUImageTwoInputCrossTextureSamplingFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CA0BA0CC8335A694D5350A133298DB3 /* GPUImageTwoInputCrossTextureSamplingFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 6D8EBA9E4E1129A31580B8B4D7345A8F /* GPUImageDissolveBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 63157528C8EC3BBA57A086A9E876519F /* GPUImageDissolveBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 6D957B3608267293F263AC16C250F6FD /* GPUImageMovie.h in Headers */ = {isa = PBXBuildFile; fileRef = 3918FDF9EBD2B1FA91FD529E6E34785A /* GPUImageMovie.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 6DA9CE75744CD9CAD2A497743A002CB3 /* _YYWebImageSetter.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D59E89941BC318DF7FC1D5BC49895CD /* _YYWebImageSetter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 6F1483002AE6E1A074656FE296A380DC /* GPUImageLuminosity.m in Sources */ = {isa = PBXBuildFile; fileRef = CFC1905D68B43955A7ECC39E228564DC /* GPUImageLuminosity.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 6FA721F4651B626AD252155EAC6BF7F4 /* GPUImageNonMaximumSuppressionFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = BDD3B32644BC93C7355A1C520C495A48 /* GPUImageNonMaximumSuppressionFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 6FFCB41E003AD80298DCDC27CBD24248 /* GPUImagePolarPixellateFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 7CD5AC12DA2322B95DFCB7F7D42FBD49 /* GPUImagePolarPixellateFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 701EB7C0B4375EE2BF4F17FDDA91C3D7 /* GPUImageAmatorkaFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 15E496E703C5AD87E7989377C681D73B /* GPUImageAmatorkaFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 703D0714CF1905012533BA95ECFFF425 /* GPUImageRawDataOutput.h in Headers */ = {isa = PBXBuildFile; fileRef = 08FB776087C19D638AA775DF1EA2E6A6 /* GPUImageRawDataOutput.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 70E9D98EAD51C5A686AAD7DCDF267C0A /* GPUImage3x3TextureSamplingFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 115B979659F12A2946B4CE9FB629FC55 /* GPUImage3x3TextureSamplingFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 70F45CBA5AE0D7F59DDD9340AB3BD317 /* GPUImagePolkaDotFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = CA5BC3210A0DC9C52CF983E3FBA33D3D /* GPUImagePolkaDotFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 715144603B1E95E5FD199B6A820F3FC8 /* GPUImageLuminosity.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F06970C1605988B31A04FC0D429E908 /* GPUImageLuminosity.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 71F48775913C25AC156501B0EC59BFEA /* GPUImageClosingFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 6FE16BE5263EBF1D2F9145482FAE76E3 /* GPUImageClosingFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 72492130AA1799D5BE6B9446C7836BD7 /* YYImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 372EFFE9AC19817C164303970B18F910 /* YYImageCache.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 72DDDD2224AE6BE60BA942D9CF3856DF /* GPUImageErosionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 48C35BCA747620F3BF149953BFDC422D /* GPUImageErosionFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 7385628E7B625A9614D3044DE5AC3385 /* GPUImageTwoPassFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 84948E8F3C90A486BDED1DDC42DD9B6D /* GPUImageTwoPassFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 749A8557351FDA52225E717CA8D80719 /* GPUImageColorPackingFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E3174DCAC3A1A90A069C1EFAE99859F /* GPUImageColorPackingFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 74BEC30868283F25D6D5F8ABFF0BE76B /* GLProgram.h in Headers */ = {isa = PBXBuildFile; fileRef = 36A3F94120C780455E9F79C31D756DEC /* GLProgram.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 75345833F7677B391F6B3AA4468CEA21 /* GPUImageSwirlFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = B1CF0307FA26395C0EBDD879BF40EE7F /* GPUImageSwirlFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 75F2628186AF80E8B6B39E6A27F104A6 /* GPUImageRGBDilationFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 87611103457106E50CE6DF1459C428CF /* GPUImageRGBDilationFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 76429EB123F7CB8020EB29A82765DFDB /* GPUImageWhiteBalanceFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = E9EBE53088D96916DD20443C82AFBDE7 /* GPUImageWhiteBalanceFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 76C328BA20BD9A30ECE8FC13577088CC /* GPUImageOpeningFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 250D4D5BDE79FE3FB3D8E6BDF13C6F79 /* GPUImageOpeningFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 7706E5C445117A81B0442E5C19F7AF84 /* GPUImageExposureFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 985698BFE05D67C00294DF094B379513 /* GPUImageExposureFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 7A4F580731F192D5E8C6AF86AB44FBF3 /* GPUImageGaussianSelectiveBlurFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = AF4FAC2BFB19ABFAB2B98973CF3F2F19 /* GPUImageGaussianSelectiveBlurFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 7A67C46F6E32AA2E17FC8CC92649971D /* YYSpriteSheetImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 86B55374AABE32E7869673D68D81265B /* YYSpriteSheetImage.m */; }; - 7B6553286815200C94E24B0AD34C3E42 /* GPUImageRGBErosionFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 96B10DB742FBE734F2EE564DC1808399 /* GPUImageRGBErosionFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 7BBADDA4A51EDD4DB7B9178A2AD9B6F0 /* GPUImage3x3TextureSamplingFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = D41C9CF88307CC423AE666B56182E5B9 /* GPUImage3x3TextureSamplingFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 7CAD51A1A08B950CEBA05C4DBA95DDA4 /* GPUImageHighPassFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 30871DDE7586CFF91A2ACC7F23FF6105 /* GPUImageHighPassFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 7CCCD7A77FF08770AD9EB67866E33E57 /* GPUImageLinearBurnBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = A3CD8B04FB70BC53E721DA44020D04B1 /* GPUImageLinearBurnBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 7CF2AC7A3B3ED03B30C1E4ED662B0551 /* MASLayoutConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D5623738ABFF1744B71396958D31566 /* MASLayoutConstraint.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 7D9CEFE99BDDDF6D1AD696E3A8E3C349 /* GPUImageDivideBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 47104284B40E3FE25D823BBBF6BBD751 /* GPUImageDivideBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 7DC9EA1A80CD849FA3A67BB8813C16F1 /* MKAnnotationView+YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 01B971D8030BF11EC3D14181720444C4 /* MKAnnotationView+YYWebImage.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 7F421D9C31DC0525924101675B8EE24E /* GPUImageDarkenBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = BE4970CD6356FFFAA48E1613FE580EB0 /* GPUImageDarkenBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 7F4CA66F56ECEC45306530ABA32178DD /* GPUImageLocalBinaryPatternFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = E8B488F92B9569C2D4E2C544410035E4 /* GPUImageLocalBinaryPatternFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 7F834C5C649E322048D41F16488A8520 /* GPUImage-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A0042D79436E9C952B47D4763A1C4AE /* GPUImage-dummy.m */; }; - 7FA724745C6C17A6466F449C11EC81E9 /* GPUImageSharpenFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 20C5BE19C1459E39FC196D7A94B0CBE9 /* GPUImageSharpenFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 7FB5C3196DB87FB6E92DABE225494BDC /* GPUImageCannyEdgeDetectionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 048641897F1CF7D044ACD0D40581C549 /* GPUImageCannyEdgeDetectionFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 8087873FCF7C582C567FBC9E7866FC00 /* GPUImageOutput.m in Sources */ = {isa = PBXBuildFile; fileRef = FD794A0352171C16DFE53E0AB396C398 /* GPUImageOutput.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 8194C101551A2584D8E3344E0FABD8F7 /* GPUImageToonFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 80DCA9ABD24683C3D8FAE083D96F58E5 /* GPUImageToonFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 81F811A56B6724F7E8E2D25364E595E3 /* NSArray+MASShorthandAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = E11AAC1475379E882BBED87C93CA898B /* NSArray+MASShorthandAdditions.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 8230F51E5396B2EA356525E246B13E65 /* GPUImageDarkenBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 6872FC509316C9B4DCA67FFA969849E6 /* GPUImageDarkenBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 82844D6EFDF6891200BBCD3A4C9C54AB /* GPUImageFASTCornerDetectionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 50E15C340F7D31DE893B684AFF6EC189 /* GPUImageFASTCornerDetectionFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 832DE22BB0C9275FF031A74E88D0BFD6 /* GPUImageContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 6679F37F751FAB9174C4595A35CF4822 /* GPUImageContext.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 8372234603432285BBF01ED1A21DCF08 /* GPUImageMotionDetector.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CE0EB4E232A38B13CACAA200001C7D9 /* GPUImageMotionDetector.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 83788DC3CB98DF8D12BB87500570D4FC /* GPUImageLevelsFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = EEF00EBDB95094FD4257D5613DD330E0 /* GPUImageLevelsFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 83A1B04E0BA640C7FB29FAA7A629B328 /* GPUImageSingleComponentGaussianBlurFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C8EF79EE8E13A7229E1AF925AEC3BC4 /* GPUImageSingleComponentGaussianBlurFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 83A21AF2AA24EC617540C8FBDADA56CF /* YYFrameImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D1011A9244B271E11F082989E181A6D /* YYFrameImage.m */; }; - 858B891B75D0F43A511C03E9CCEA9E8C /* GPUImageParallelCoordinateLineTransformFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = F412634986B6427C47BFE33290B76D0C /* GPUImageParallelCoordinateLineTransformFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 8620831289FD8F3A3595EAF6DAE7138F /* GPUImageRGBOpeningFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A8E625D6539753D6AC67978B97C5D7C /* GPUImageRGBOpeningFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 86BA3E6F0F738FB8D5FA5E4F469C8694 /* GLProgram.m in Sources */ = {isa = PBXBuildFile; fileRef = B938A512490439A79E04F0C9697CD365 /* GLProgram.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 87AF8CBBDCBB0C50612AB69D6D742742 /* GPUImageKuwaharaRadius3Filter.m in Sources */ = {isa = PBXBuildFile; fileRef = 453BE721D27626D4753B1F021A0126F4 /* GPUImageKuwaharaRadius3Filter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 8845BDFA0653F4E71762578DB183BCDB /* GPUImageLightenBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = ECEA2E9EE22767E7510CE7AA87771919 /* GPUImageLightenBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 89215341FB58A6E29005197E676AC1FC /* GPUImageSwirlFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = BEFFA1F44D79B03904E27FC68BA02324 /* GPUImageSwirlFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 89360CB1E03A04FD4E4E35444535B5CB /* GPUImageXYDerivativeFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 2BB60AA6A277030CEA93B362B1061701 /* GPUImageXYDerivativeFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 8A5D33655584772DCD0CF3C4EECCE0BA /* GPUImageSubtractBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = B841981319C7EF7EE2877086FCA683E5 /* GPUImageSubtractBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 8BFFBA9AD7ADDBA5B802F107161884F1 /* GPUImageHoughTransformLineDetector.m in Sources */ = {isa = PBXBuildFile; fileRef = CF2F73298D0AAD1A41B6CB86926D9317 /* GPUImageHoughTransformLineDetector.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 8CE29353E6184B70D568D3B99E94D149 /* GPUImageLookupFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E5657C2668E3B4C728034FA1EA9A0A4 /* GPUImageLookupFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 8DF2798CBFBF2B27970A065636E5350C /* GPUImageColorInvertFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = B63E6AF28713967F264112F9450B3F8C /* GPUImageColorInvertFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 8E64B342157226991EE54B8F6152A1A4 /* GPUImageFalseColorFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = ED7087E1AAD6DCA511A73A2D2B30D6B4 /* GPUImageFalseColorFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 8E75885AC38F2FD27A93B5365669B7D1 /* GPUImageCrosshairGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 795CA168A9604FBD8784D73FA8C9DE4A /* GPUImageCrosshairGenerator.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 8E76ED19F995FA81CFA03FF86BF480D8 /* GPUImageAverageLuminanceThresholdFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F1724BCB76C8A64AA536BCED3D812D4 /* GPUImageAverageLuminanceThresholdFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 8F136A8285B1AA9501C02EBE717D9749 /* YYDiskCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 926120A3C10BB72D3539005BC5D12636 /* YYDiskCache.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 8F2F540C8BCC922C80CB0EEC85AE2CB6 /* GPUImageAddBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 5002004ECCBA2AFB115693A8FF292F8D /* GPUImageAddBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 8F87A31C7C5DCF2BFC9E7A9A9831DE3F /* GPUImageStretchDistortionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 22245274C4F286C6221A887D6CD7F1AE /* GPUImageStretchDistortionFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 8FA19489C4BAAB00154C1E14F0692F3E /* GPUImageMultiplyBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = CF78B4B80A067EF3C1E69807978B0212 /* GPUImageMultiplyBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 90A044FA9883FAB9D1BC675A7BCCAD39 /* GPUImageDilationFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = DF18464EBC41D32FBD924D4FBD3DCF7D /* GPUImageDilationFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 9194B58ACE900ED6BAE6AD92E24A2CFF /* MASConstraintMaker.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E64875CACD9293F8463A7DEB77900AF /* MASConstraintMaker.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 92AE518A0FBE98A0DF863B8DF7AC1FF3 /* GPUImageLuminosityBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = A827A26F6AFD11185014B81B1EDDC257 /* GPUImageLuminosityBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 92BF70E9D3285561EB404A7C4A4A6DEE /* MASCompositeConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 1601092CB8E312022FDE49393A610FA4 /* MASCompositeConstraint.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 93A3C001CF21FF9A011DBE76D08E6FD9 /* GPUImageContrastFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 78FB8998E490B19D8A2CFE9E092F2132 /* GPUImageContrastFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 940FA559831E8663F4C3C2CFAB214B86 /* GPUImageSolidColorGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = B43D8D3315443CDCAF2566D64DDEE04B /* GPUImageSolidColorGenerator.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 942B26BBAD3D8D03EE64EADAA91984F4 /* GPUImageThresholdSketchFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = EB47C074A601454370424E7CFB464BCF /* GPUImageThresholdSketchFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 958FD4275823EA710C09035D28BC5BB6 /* GPUImageNormalBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 49B9B7911201EAA735B877B4E99D31D9 /* GPUImageNormalBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 9679F252AD137F1DC4749381E3238620 /* GPUImageMovieWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = 21CD080746E9E7BC9C0BA1E1A2EDF8F0 /* GPUImageMovieWriter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 969CB0062DE1F74E8011E8AD2A79DD6A /* GPUImageHazeFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CAC7D39500D3FC8B5E4380E69FFBCCA /* GPUImageHazeFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - 9AE51F7A10F7D2A41DB5AE00A230DEA2 /* YYKVStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 41E7FFB3E5D0BA8ABC62E1A89D3063A8 /* YYKVStorage.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 9AF58F81BAD92835CEEDBB31C74435DB /* GPUImageTextureInput.h in Headers */ = {isa = PBXBuildFile; fileRef = 2428E8C70A2E6595B6031EC3C1851FEF /* GPUImageTextureInput.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 9B2FF85F49CFCBFD69ABF044B8AF17CA /* GPUImagePinchDistortionFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 4272FC95B847753C0B6BA23100C3957E /* GPUImagePinchDistortionFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 9B3F3992A312CBF772A509E737CD7230 /* GPUImageThreeInputFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A14EDB5BB818BEE5CEE11AB9273F285 /* GPUImageThreeInputFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 9B8A55EA1B0232CA9B99B1F3B67595F4 /* GPUImageSubtractBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A0251929026FA746DAF38200C6045F2 /* GPUImageSubtractBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 9F1608BD340BF4B02A5B88CA03707AA1 /* GPUImageFramebufferCache.h in Headers */ = {isa = PBXBuildFile; fileRef = D17E8A9196C94BC7F7B14D0D08A31A90 /* GPUImageFramebufferCache.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 9F1EDF344FCF17EE6EF5A072D727E3A7 /* GPUImageToonFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = CE8390129A638BE0F4AE19C96CACE467 /* GPUImageToonFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 9FA8C873F74D9C40A96BE74F017385CB /* GPUImageCropFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 69E7B0C997A3206F5C0D10C360A6D957 /* GPUImageCropFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - A07E94BD19655E823533CEFB4DBDD203 /* GPUImageStretchDistortionFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A94921FCB9C25F627D3B1EB025EB097 /* GPUImageStretchDistortionFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - A10B6F1BD9FC2A0A3BD16B0CA7951F83 /* GPUImageUnsharpMaskFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F0C80FAC0118D3106441EE7BCBCFF00 /* GPUImageUnsharpMaskFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - A1CB7B78C1D3374BAEA9A2BCC3A25656 /* GPUImageRGBFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E747934866906927486DC94DEC4581B /* GPUImageRGBFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - A25BA1791E1B279225964FA5CB18271B /* GPUImagePosterizeFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A18B72D843666583E43734D2462B4F /* GPUImagePosterizeFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - A2EA584895A489FC00301707BF956355 /* YYWebImage-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 68619D6BC015E7B9AD2E0EF3660EC99B /* YYWebImage-dummy.m */; }; - A3307B8FB6EE0A049DBAE3AA4D2C6DA0 /* View+MASShorthandAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 82945F15766B165DCCA8DA4BC2C4BD87 /* View+MASShorthandAdditions.h */; settings = {ATTRIBUTES = (Project, ); }; }; - A407D6E4E7732ABCAB9C121D415AF3E6 /* GPUImageHistogramEqualizationFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = F478792CD6750762D653D4B974565731 /* GPUImageHistogramEqualizationFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - A5ECEA60FC0AADF57283128443C642E7 /* GPUImagePixellatePositionFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 6DA0D34140F270C03A5A2D7F4CC54517 /* GPUImagePixellatePositionFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - A6D788652DBBA97BB929B66E8FABF5FC /* GPUImageOpeningFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = F2F67F28D47899C70E83AA9305D4E341 /* GPUImageOpeningFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - A7208F4AAB19736637ED7314D63F7D2E /* GPUImageGaussianSelectiveBlurFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B2CFE441A1614F51B47AA982B4E448B /* GPUImageGaussianSelectiveBlurFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - A722D1944A6F15819EA75CAC4A65CD8D /* GPUImageMedianFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 34284363F58BE296025C3C9CBD8F317C /* GPUImageMedianFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - A834995186E9FE7D0150677B989DDD8B /* GPUImageLuminanceThresholdFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 7C17752936CF711DF066A5BA091BFA81 /* GPUImageLuminanceThresholdFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - A853401FDAA9E7088AD5028D09787374 /* GPUImageKuwaharaFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = AC97F32440360E91D0907B1696EFA925 /* GPUImageKuwaharaFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - A893FFB0F9137E298D6752729850D1D6 /* MASViewAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B4EE9ADF2AF51D5C395568406645F72 /* MASViewAttribute.m */; }; - AA3AEE471C21B1B2381CAAEA54557674 /* GPUImageSourceOverBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = FD17D6790093A05DE5D3FEA809D11BAA /* GPUImageSourceOverBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - AA6F89A3BB414439A39AD2FE6C4B6C5A /* GPUImageAlphaBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B03CEF081AF2EB3E5F9FF382D2515F8 /* GPUImageAlphaBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - AAD0F39A4AA032B8C0C0B40EA7441E94 /* GPUImageBulgeDistortionFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = FB24E4E098F3B7DE3B8F4ACF2BC28A28 /* GPUImageBulgeDistortionFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - AB11AF112E43D1FF1522A8844564CD74 /* GPUImageMovieWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = A17B47159361544A9A5041BCADFB2DA3 /* GPUImageMovieWriter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - AC6FF619E5FDA1335F97C3C9E4C4276B /* GPUImageFalseColorFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 34E2DEEB4F0ADF11F9C9E23D43C1A3B6 /* GPUImageFalseColorFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - AD8503BD62763B8ACD0D4FFF1E8C56A2 /* GPUImageSaturationBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 3F37E42BC4BE8E0517824BABC9869273 /* GPUImageSaturationBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - AFB6AFAD5CDE82433B7EF710AEABFFEC /* GPUImageGlassSphereFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 169DF30CA515684B51A770DE262AC808 /* GPUImageGlassSphereFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - AFD895639FCE8E367E47C39C13807509 /* GPUImageWeakPixelInclusionFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 894067B7B8B143B196F909226A542245 /* GPUImageWeakPixelInclusionFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - B129AF9904B49BDEBFA2CBE15CD8C832 /* GPUImageColorPackingFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B231C196006B4B6C3DD281978E5EB74 /* GPUImageColorPackingFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - B16B792802266C47B1C05A7938DB2FDD /* GPUImageEmbossFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 6E126A469B8B4CA1D5708D0C66DBCB45 /* GPUImageEmbossFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - B1E3E64D5F9CBBA0AC445152F0502EAA /* GPUImageCrosshairGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 611CC398C3A952328326F836188CEC88 /* GPUImageCrosshairGenerator.h */; settings = {ATTRIBUTES = (Project, ); }; }; - B20A0E5D8F9BCED1A82793C4BE9E7258 /* Masonry.h in Headers */ = {isa = PBXBuildFile; fileRef = CAD1753F08C939B747A9310D6E2C7CCD /* Masonry.h */; settings = {ATTRIBUTES = (Project, ); }; }; - B631B16F2CBE7157B23476CBDCE715E5 /* GPUImageContrastFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = D66E3D513B5531F7F4B074A1AEC523B8 /* GPUImageContrastFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - B78DB212BF2C1ADB6DCF09953314CABD /* GPUImageMaskFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = FF5ACE2C67EA5C6E02ED4D4FBD28FBA7 /* GPUImageMaskFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - B79E092F5B29C5C8B7359493C043A4DE /* GPUImageSoftLightBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = A0D905911F4E966E46571AE6336725F8 /* GPUImageSoftLightBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - B80DB3332DCA3B96D6208277A30E39F1 /* YYWebImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F3286B04ABC750B2DA6269CDAB9A3B0 /* YYWebImageManager.m */; }; - B82BCA913A74C5C17CF67BB48430A6E9 /* GPUImageFilterGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 10AF522841E0BF1975899E1F731DDF5D /* GPUImageFilterGroup.h */; settings = {ATTRIBUTES = (Project, ); }; }; - B8835F0715C5DCFFDB7FED7098B47596 /* GPUImageHalftoneFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = E82866E758AEDE0697B2D6542D52887E /* GPUImageHalftoneFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - B893623350B4E001365E48E0AC5D1F91 /* UIButton+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 0920AF97BC9AA2C404C3E60972978562 /* UIButton+YYWebImage.m */; }; - B8DBBA903BF381C26A07E80FB3B673F2 /* GPUImageCrosshatchFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = B5497DA96594CCECE8E15AC43C9A2C6B /* GPUImageCrosshatchFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - B946AFB1A725D85E07F645A7EF086383 /* NSArray+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 05C8A3D41E95FB4EF796E14A592986C7 /* NSArray+MASAdditions.m */; }; - B9A2408D5950F5547F7D82E84217F63E /* GPUImageAverageColor.h in Headers */ = {isa = PBXBuildFile; fileRef = D4A60FDE318E3C0F278D020D96060453 /* GPUImageAverageColor.h */; settings = {ATTRIBUTES = (Project, ); }; }; - BB2A9B9161E5F0AECC9F3CC31F6D85F6 /* GPUImageSaturationFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 219E2548D3FF4C96F4ED257B47311123 /* GPUImageSaturationFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - BBD0DCB580B12F696F7240575892FAA2 /* GPUImageGammaFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 43F07509067BACE67AB5E9CE46DBB3EE /* GPUImageGammaFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - BC130E24128D66199EF316BA62B7FE30 /* GPUImageLuminanceRangeFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 94F2208CD8400EF9A4FE9B63DAC5E6E0 /* GPUImageLuminanceRangeFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - BD451674A244E95543E0CE56FEB2DDD4 /* GPUImageDilationFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 856409B61D04B0A9D91A67DFFB1C680D /* GPUImageDilationFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - BE93BA2DA12D718619AAA3F8216D29F4 /* GPUImageThreeInputFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 8736944B2594030670245A252F39B7FA /* GPUImageThreeInputFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - BF4117E228B603963206D603A99B6CB0 /* GPUImageBrightnessFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = FA45E049B5B5153FBD3529680C70E520 /* GPUImageBrightnessFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - BFBF5806B8FB170749BF71FCFA77096D /* GPUImageMonochromeFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = C3415B253778A17AB9D9E9539C59982E /* GPUImageMonochromeFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - C05FC6699632FE712174ED875A605410 /* ViewController+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 6EEB662CC37ABBC8474275EEA42AB477 /* ViewController+MASAdditions.m */; }; - C0CE23B393799A65CB7626FED30D8B87 /* GPUImageDirectionalNonMaximumSuppressionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 1495EAEF4EC6B8FB6E18881881B3573B /* GPUImageDirectionalNonMaximumSuppressionFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - C0F421E2359654EEC935728ECFE098C8 /* GPUImageOpacityFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = A0A98FEBD19728184776073D5B656C40 /* GPUImageOpacityFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - C1819B0277FEA363D59F734D9AD8AA4B /* GPUImageColorMatrixFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = F56DBD12B11C3994DFB4255B1D7CC1D8 /* GPUImageColorMatrixFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - C2480784B8731B3505C36BEC36F43F77 /* GPUImageHardLightBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 94E26D38916B6B7C099A974F7D4801BB /* GPUImageHardLightBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - C249EDF7D50D5A7BEA1C40AABCE51E7D /* YYFrameImage.h in Headers */ = {isa = PBXBuildFile; fileRef = BD8A6D912B9DADCD91A8CECBE8D365BF /* YYFrameImage.h */; settings = {ATTRIBUTES = (Project, ); }; }; - C3215C21113B7017773F61D8E2C0F05C /* GPUImageNobleCornerDetectionFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = E5AE2B148F45F4E8B8FB0225084DEE18 /* GPUImageNobleCornerDetectionFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - C33E9361A533400A28DEE54586144691 /* Pods-DarkMode-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B166651BD2944A773F9537AEC00AF13 /* Pods-DarkMode-dummy.m */; }; - C36D1358DE52DDFE9561872046B15CDA /* GPUImageClosingFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = BD9B919D49630BD01C44E78237FBD863 /* GPUImageClosingFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - C38CB6D5CA3A24003E2314F3ED91BBA8 /* GPUImagePixellateFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D99E942362A4061252F3303E92A955A /* GPUImagePixellateFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - C3D1B9C0AB90607D224B2440ADDDBF7D /* GPUImageChromaKeyBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 76CEE856E426B01553F3D79A1347C109 /* GPUImageChromaKeyBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - C465BDCDDAD3B3CD57F1C64294A1533A /* GPUImageNonMaximumSuppressionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A7B42C55528946ABE27DCA7F4A86E7A /* GPUImageNonMaximumSuppressionFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - C4E5DEC7DF514A359AA062C7F13C95A4 /* GPUImageSketchFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = F167A2004301C4034FFB0D96A262B99D /* GPUImageSketchFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - C564C8D042998164475E13AD54B0A294 /* MBProgressHUD.h in Headers */ = {isa = PBXBuildFile; fileRef = 768B4BE6A62741EA37180E7EC67437C1 /* MBProgressHUD.h */; settings = {ATTRIBUTES = (Project, ); }; }; - C74D2E856ADC8139CD00DBD184061B23 /* NSLayoutConstraint+MASDebugAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 36454A100B7DDEDEA1E782EF2E9E27AC /* NSLayoutConstraint+MASDebugAdditions.h */; settings = {ATTRIBUTES = (Project, ); }; }; - C7710525EC84D4EB1FAF4D571DB64D90 /* GPUImage3x3ConvolutionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B209441C9B2647C1E347736EE8FC64A /* GPUImage3x3ConvolutionFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - C7920681F0164686C56327ED3C6AAC58 /* View+MASAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7EBD52032DCAFDAEC06FD991BB8695A8 /* View+MASAdditions.m */; }; - C7FD66D3D320095B45AD9D39EF1B858B /* MBProgressHUD-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C7EBDF59E4597071BF464EFAC596030 /* MBProgressHUD-dummy.m */; }; - C8533435ED95323AD49B5ABA46309592 /* GPUImageColorBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = DC785C323CE09EC09CDC2F8014081C38 /* GPUImageColorBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - C90957CDE1F88C80D792F3CCBBBD86E7 /* GPUImagePoissonBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = D54971E35D67E4E2B0A20F8CD8BDB2D4 /* GPUImagePoissonBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - CA07E0D65A9F569E68A647D3A422C028 /* _YYWebImageSetter.m in Sources */ = {isa = PBXBuildFile; fileRef = 216F8CFBA824F61AE51F0BE1FB37998B /* _YYWebImageSetter.m */; }; - CBC2808292742C287F16EC38D82C57EB /* GPUImageVideoCamera.m in Sources */ = {isa = PBXBuildFile; fileRef = DDB88636BCAA89B17531BEAC2B7677B4 /* GPUImageVideoCamera.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - CC46255DAABC498A35F70078C1A566BD /* YYModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 31214193F010827DB7A59D7F34A65AF0 /* YYModel.h */; settings = {ATTRIBUTES = (Project, ); }; }; - CC997265C47D1D37F34774F5E59DFCA2 /* GPUImageThresholdEdgeDetectionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 36B4A09ADA586EFD92A79ECD4C0E35A8 /* GPUImageThresholdEdgeDetectionFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - CCC7F68CE9545A177EC9EA20AA2AE9C5 /* GPUImageCGAColorspaceFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2119B781CCC19BD3D0A42F303D2E7812 /* GPUImageCGAColorspaceFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - CDCBBC093C8294D84332E954BD1A80E4 /* GPUImageSketchFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F81E2DA24707028F902CA5D2165F3AF /* GPUImageSketchFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - CDE62540A3FD2D838E06A3FCAB1EE58E /* GPUImageiOSBlurFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 864D6DEE6397881CD3F0FCBC2443BB60 /* GPUImageiOSBlurFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - CDF22D54534615D38B7CB2ECF4C15367 /* GPUImageColorBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 16D91E4D58A94C5524A115536224EA76 /* GPUImageColorBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - CE8EAEC4550BF203A6D4A25FB8FF772F /* GPUImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = FC2B794A56EF9D2701B9021759093037 /* GPUImageView.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - D0AA94BD089FEAD90D37D172CE9803B5 /* GPUImageMotionDetector.h in Headers */ = {isa = PBXBuildFile; fileRef = 2715DCC6112CFACF55C762832D38626D /* GPUImageMotionDetector.h */; settings = {ATTRIBUTES = (Project, ); }; }; - D0C48086A9D1C8721C57BC59E3ABC9B4 /* GPUImageLowPassFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = BA371A875E27E7EE7D0FCD1007D94CF2 /* GPUImageLowPassFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - D0D36AA4AD8C0D0B5D667B37FE3F9EF2 /* GPUImageUIElement.m in Sources */ = {isa = PBXBuildFile; fileRef = F11B4258E3FA4A8841B1604E377E7F3D /* GPUImageUIElement.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - D29C5C66C8885349266175C1D749F02F /* GPUImageHazeFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = E63C05F85CF505C1F4F6C1F2A5264989 /* GPUImageHazeFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - D379D3AECD4C3EDBD261235D63E260FF /* GPUImageScreenBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = F1C3D508DA7E563DEA7799B00D9E2113 /* GPUImageScreenBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - D3AF12B25881D1AAF4DE417F1D5407B9 /* GPUImageLuminosityBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BA72D587A6A6B053532804FF36E8E46 /* GPUImageLuminosityBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - D3E0F67215B94615E748A1D2C98439AD /* GPUImage3x3ConvolutionFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = BE0B9D8C884083422794279D51378D71 /* GPUImage3x3ConvolutionFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - D5193E9E46629B96BDEB10DAEF57582D /* GPUImageHSBFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 6DC692CA9FD5C1A42113F450FA649F67 /* GPUImageHSBFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - D5A4349BFFC852AA31E14DFB14A47976 /* GPUImageTwoPassTextureSamplingFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 53D16559576FCC95A4CD46C46C5DE443 /* GPUImageTwoPassTextureSamplingFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - D5FC0D8E4622A03DA9AD9C7D2FD993E1 /* YYAnimatedImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 87B89822E64C2B0270C48FB5310A947F /* YYAnimatedImageView.h */; settings = {ATTRIBUTES = (Project, ); }; }; - D6438BA4F863AE0A7891F212EE3C06D0 /* MBProgressHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = B5319E1423AA1E35ADBA7A3B04DF598E /* MBProgressHUD.m */; }; - D72EE0E749232B2C899702FC1C9402BB /* Masonry-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = E5C1184106339F84D7D501170074B1B4 /* Masonry-dummy.m */; }; - D73DFCB550FD90D81582D87DEC5FBFBB /* GPUImageTextureOutput.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E198F28897BDB4F191CE84351A84102 /* GPUImageTextureOutput.h */; settings = {ATTRIBUTES = (Project, ); }; }; - D8AC3A3A9FC2C585805D8130985DFA64 /* GPUImageAdaptiveThresholdFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 129DAE9BAABDCB922089CE7D3BDF76EC /* GPUImageAdaptiveThresholdFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - D90E1DB2985F031A249C1CD1D7A48AF6 /* GPUImageNormalBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 35D609B903920B4F5B05401FBC7E489D /* GPUImageNormalBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - D90E2B61D12B3135282EC3264A4B6699 /* GPUImageSaturationFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 1577D323A093A5E9B341C97A2C56FDFF /* GPUImageSaturationFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - D945A64F6CF78BE653585C4ACE0E24EF /* GPUImageBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 527337E5AE7218053824FE826DE95FB6 /* GPUImageBuffer.h */; settings = {ATTRIBUTES = (Project, ); }; }; - D9742F495FB317A0EDED886CDEC37049 /* GPUImageVoronoiConsumerFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = E7ED5325591277156B4BB5CC580E9723 /* GPUImageVoronoiConsumerFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - D9760E3346290F95407D7DC02CE7CBCC /* GPUImageColorMatrixFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = A040C6DAEB250520DDAB80B89F5BDE6B /* GPUImageColorMatrixFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - D98126521560BEA4D6CB57439643C89E /* CALayer+YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = B9A029945B47FB73CDE3CC37104F813F /* CALayer+YYWebImage.h */; settings = {ATTRIBUTES = (Project, ); }; }; - D983E144A1EAF9EF20BFD31AEBD9BEBF /* GPUImageColorInvertFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 467740B1EE1788F570B996D82E451066 /* GPUImageColorInvertFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - D9EBD120B2572956219EB5E69C9987DB /* GPUImageTransformFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 25B452C9C925DADC958E77C39081288F /* GPUImageTransformFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - DA13233E99DAD01F4F1CF918A1828173 /* GPUImageFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 6FAE5EFDF6BAE35B5464066D6F82F34E /* GPUImageFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - DA49D1C675F5679D26CB9069A7269185 /* GPUImageSmoothToonFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CF95A800A5428B6D2C82CDC82A21CD5 /* GPUImageSmoothToonFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - DB5CD837D88F4C0A6E260922756085EB /* GPUImageGaussianBlurPositionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 404551280AEA0058459B3385F82AFBBA /* GPUImageGaussianBlurPositionFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - DC4A074004FA5271EA709589DFCBEB15 /* GPUImageHueFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = C7E61395FE8E961D58658EFC5FE914A3 /* GPUImageHueFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - DCDB85FBCE034BD943E4CAD37FE90B79 /* GPUImagePixellatePositionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = AB79E1A4A66A6C04AB9D9EBE73E0A218 /* GPUImagePixellatePositionFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - DF95FC4FF9019EEB2C9717A8BE4F2EFE /* GPUImageShiTomasiFeatureDetectionFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 254E957A25195EAAC2658009BDAEEBBD /* GPUImageShiTomasiFeatureDetectionFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - E0D741EB912B03FB998FF163F941827A /* GPUImageBoxBlurFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 03A0D571B1A527AB8B7B3CA882F4D673 /* GPUImageBoxBlurFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - E275F7BF40EC2FB17B2ED9029FF06BCA /* GPUImageTiltShiftFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 05AE57422D69487A72FEC0CB766E61D0 /* GPUImageTiltShiftFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - E2F119888DA6312834DB6A2E84FF5906 /* YYClassInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = D65307FDE17DBA7A0B3A73E64332F870 /* YYClassInfo.m */; }; - E3FDBC252DF4EE97EF2A47F9FD299138 /* GPUImageFilterGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 675DA2B87C4D3A22040B4457A6387B04 /* GPUImageFilterGroup.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - E584CF8B9CA73334B373D6AEC20870CF /* GPUImageDirectionalSobelEdgeDetectionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = ECFEB2E93FCE91E7C240F7A5418610E8 /* GPUImageDirectionalSobelEdgeDetectionFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - E5C0807D620C0E07706C6C00F87B7D7D /* GPUImageSphereRefractionFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 844471BB500349B7E35E4D0A96389D2F /* GPUImageSphereRefractionFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - E611F7A8E5966E6E2E68224A3F4F42EB /* GPUImagePolarPixellateFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 228003B3476B41761F56C932AA1DE129 /* GPUImagePolarPixellateFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - E692F6CB653BDF7FCCE2A253E019F409 /* GPUImageMedianFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = AB9AABEFA3783A1EFB3AF263028EA22E /* GPUImageMedianFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - E73E4ED481B67985D7794448CA5DE53A /* GPUImageThresholdedNonMaximumSuppressionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 07C2E5E0DB6558AF1D582E8DD0D244EB /* GPUImageThresholdedNonMaximumSuppressionFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - E76935CFF4AF327F8D9A7C1935F7D900 /* ViewController+MASAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C0B54E85F3F7357A3084FAC6447AFF1 /* ViewController+MASAdditions.h */; settings = {ATTRIBUTES = (Project, ); }; }; - E7AF1651C307635FC4A9E52F6911B3B3 /* GPUImageChromaKeyFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 12F2B7D58256DFE9C2869DEE816D2FDD /* GPUImageChromaKeyFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - E84C5D01F33A6C9AFFFA1B009D4BD25E /* GPUImageStillCamera.h in Headers */ = {isa = PBXBuildFile; fileRef = 77F4D03A5C3A7B3755BD05C6BC87D853 /* GPUImageStillCamera.h */; settings = {ATTRIBUTES = (Project, ); }; }; - E8D139B563E36F0BA0C9F5B2B20C75B1 /* GPUImageGlassSphereFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EB243D1C497784152C266E096C23C6C /* GPUImageGlassSphereFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - E9129B8F2C4716BB0E04A8AA7DF489ED /* GPUImageRGBFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 97BB1E9D14B5C9A8E04954127CF899DD /* GPUImageRGBFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - EA2FCF7789C782BE597B4A462E5AC8D7 /* GPUImageSaturationBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = B76EEE6CDA11AED2C0DF42954264E2E4 /* GPUImageSaturationBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - EA5E2729A6E87C922CDF98A3ACB985BC /* GPUImageHighPassFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A6F1BA241429526CAA01D945FD69E28 /* GPUImageHighPassFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - EAAE5E8238A63B075863D7007624DA43 /* GPUImageHistogramFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D6101DA1E24CEAF212864D149AAA311 /* GPUImageHistogramFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - EB0DC31314035D14CF7D560816C5820A /* GPUImageNobleCornerDetectionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F4D069CFC80E40C0955894061DC5082 /* GPUImageNobleCornerDetectionFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - EB663E3E1EB4BB670DC29B77DB330135 /* MASConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 13093D7BD9574A7D40FB42A21DB87F15 /* MASConstraint.h */; settings = {ATTRIBUTES = (Project, ); }; }; - EB76EA09E1FC065CB6203F5F602D76F0 /* GPUImageGammaFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = FC8FF675218469A34772983792A93F7D /* GPUImageGammaFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - EB847D328F7F2D583D63181D9829991A /* GPUImageHueFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 04EED508463C74DA6E7C59026CB90BE8 /* GPUImageHueFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - ED1F02433F3A912D677F43E1FF11A86D /* GPUImageCropFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = BA29045FFD62C4F2F08018346E53B773 /* GPUImageCropFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - ED6CA2C4FFF084A9C6BC0C3058F2FC0E /* GPUImageCGAColorspaceFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = B748550FB21BB7C03E6327054546AAD9 /* GPUImageCGAColorspaceFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - EE936A6838005A5ED1BC5F74BE37B7BD /* MASConstraint.m in Sources */ = {isa = PBXBuildFile; fileRef = B31F1147C4556865B64D707FEE8CCC97 /* MASConstraint.m */; }; - EEF7E74667C5176B5F1554D7184F2A6A /* GPUImageEmbossFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 83180B57DF37B3555ED1B68472C45C2C /* GPUImageEmbossFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - EFD2E46C54A13C1D9D72DE9F8531AD92 /* GPUImageZoomBlurFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 8A10226B00432CC14F57C84CDA29A0B6 /* GPUImageZoomBlurFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - F0088DAB471D5A3F2924964CD410BE41 /* GPUImageOpacityFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = D20E7200664BDC1CA23F83B69DB2AF00 /* GPUImageOpacityFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - F06B38D5B6F52BE9B44E382F020D6B31 /* GPUImageShiTomasiFeatureDetectionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5388C8B9509AE2A725C77FB08EAB1262 /* GPUImageShiTomasiFeatureDetectionFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - F1750C9B60511FA4C2FFA9326C53194F /* GPUImageTwoInputFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 537E9A1D3C9B19E06AD252A90F35F4FC /* GPUImageTwoInputFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - F1B75048874B8773E5568E6D3ACA12E4 /* NSArray+MASAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = BE81F8031495E743E805E3F1ABB005EE /* NSArray+MASAdditions.h */; settings = {ATTRIBUTES = (Project, ); }; }; - F240CA1217BACD2BA4C0B0EB15F62EF8 /* GPUImageExclusionBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4B2BBB528CEAFC918860127115B034 /* GPUImageExclusionBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - F2FD414ADEF65434E578A08DF0676F0D /* GPUImageJFAVoronoiFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5AB2E9FBA9B5DC6C3B50148EBA2EB69C /* GPUImageJFAVoronoiFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - F3E6FD4C3F7B20EDF489236C6EC945DF /* GPUImageFilterPipeline.h in Headers */ = {isa = PBXBuildFile; fileRef = 11CCBC30AD14409191CFABD8D074A58D /* GPUImageFilterPipeline.h */; settings = {ATTRIBUTES = (Project, ); }; }; - F4026D5FBB3EB246FEF59DA6B805FDAD /* GPUImagePoissonBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = F776E442B4C1CDFEF257F6134CBE90D0 /* GPUImagePoissonBlendFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - F40E6B5DD24C45C5E16A11F8CB40482C /* GPUImageSingleComponentGaussianBlurFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4284D70C7F26D1B5D00CB148C3E562E1 /* GPUImageSingleComponentGaussianBlurFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - F4147D4455B06FAC3BF47FD552C69DDA /* GPUImageUnsharpMaskFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = A02D900146C224595943A9226D2DCAD8 /* GPUImageUnsharpMaskFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - F4BA7E7FFAF565B29CC82D54B793EF78 /* GPUImageBrightnessFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 89911F978F34916A355191709CBB5802 /* GPUImageBrightnessFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - F654313B55A14132792476E2B2FA2AE2 /* YYClassInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 970BB19E23C4B9B7AA3309F224CC0E71 /* YYClassInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; - F7DDEDD5401FF5E6458969FA7EC518F5 /* GPUImageLaplacianFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 533CF0E1A935E0C8D6084DE984AA9A48 /* GPUImageLaplacianFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - F82C2A26F6554330AF6E40C05326362A /* GPUImageJFAVoronoiFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = DA29E62F007F394173C5A6E96F4EA3A1 /* GPUImageJFAVoronoiFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - F8357854AE9106751D53AB8C32932F46 /* GPUImageGaussianBlurPositionFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = C48D8B50088748FC4BC5FC2E0C491663 /* GPUImageGaussianBlurPositionFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - F8A9EC123F285CCB4262D7419CB2F813 /* GPUImageScreenBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = D4C994A6E8F57B6828552CA504C66D58 /* GPUImageScreenBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - F961EFDD9E3144F2F28EF4702C201F0A /* UIImageView+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = DD2430725CE2EF7139ADE4BBC1C7CBA8 /* UIImageView+YYWebImage.m */; }; - F96CD4E0A91280398E5A1874D2B3A5D0 /* GPUImageLuminanceThresholdFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = E26335B2F22D282C8B7582834BD0A07E /* GPUImageLuminanceThresholdFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - FA0845E169D8DC9A8096C6DB7BD71C75 /* YYWebImageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C40FD404F6B8A2300E4B45AA2B6F9A8 /* YYWebImageManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; - FA31F4C6D96B604EEB4BF55DEF7087C8 /* UIImage+YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = F02B616DA404DA9F64E1EB8DD4C522B1 /* UIImage+YYWebImage.h */; settings = {ATTRIBUTES = (Project, ); }; }; - FB62EF85A3768A158924A4FB8D21E7E4 /* UIImage+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = E578EF7302261D7D50382800254764B6 /* UIImage+YYWebImage.m */; }; - FC39728CECE4A700D8315298E8649507 /* GPUImageUIElement.h in Headers */ = {isa = PBXBuildFile; fileRef = ABEA5E282030B2AACB13107445796E9B /* GPUImageUIElement.h */; settings = {ATTRIBUTES = (Project, ); }; }; - FC4B8B12DE32CC742444EC57C78E43BB /* GPUImageOverlayBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = D784A6CD68E1A5D8D6580987562CE66F /* GPUImageOverlayBlendFilter.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - FC910491DAAFF857945049B0434F398D /* GPUImageDirectionalNonMaximumSuppressionFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 08FD869A4FD865D449B925CD47230E72 /* GPUImageDirectionalNonMaximumSuppressionFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - FD06FC7B591A78FD113F2D10FC51592E /* GPUImageSolidColorGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 42D084FF6A05E8F634B9ECC121BB2F70 /* GPUImageSolidColorGenerator.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - FD3EAC5E0A791E73E27E422A197381BE /* GPUImageTextureInput.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CCD41C6BD2C0E9ABB3148B70C4BC918 /* GPUImageTextureInput.m */; settings = {COMPILER_FLAGS = "-DOS_OBJECT_USE_OBJC=0"; }; }; - FF641038FDDC7E524267A555915BBA70 /* GPUImageVignetteFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = FC35CED2A95AFEA26980C9D4ABC06D40 /* GPUImageVignetteFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; - FFB553681052A094EA7516D46F2A8C9C /* YYImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = CB5A0BE4A5245E286AF7E6814CDD1436 /* YYImageCache.m */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 0E525382322D144157FE54A2F8279ED0 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = CFDAE6EB02F58B9A37CADCF439AE6082; - remoteInfo = YYCache; - }; - 11065683D1DF6005F9525BBA539466D7 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 488E8C830C5A5694EE916251B9ADAADA; - remoteInfo = YYWebImage; - }; - 41577B33D18B0277BCC25CF6A140DEDD /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = CFDAE6EB02F58B9A37CADCF439AE6082; - remoteInfo = YYCache; - }; - 5BB5B7F8294D2A559BA5BED33BAE2C7B /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DB13B1641D72A72D8C9AE53FF81C8950; - remoteInfo = GPUImage; - }; - 65906679C3DF4C10CE5279E1C83FA340 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 822E44240F2922DAB12018A6B649BD19; - remoteInfo = YYImage; - }; - 6E7A69E1F8BD32917A845DD8C233CA82 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 822E44240F2922DAB12018A6B649BD19; - remoteInfo = YYImage; - }; - 817CD8DC71FA3B7C4B131536ECA0F1D0 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 55AF53E6C77A10ED4985E04D74A8878E; - remoteInfo = Masonry; - }; - AAC877F66336AAF9D915F41F63451BF2 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 84B44807A12996D487A4A591A481D6A0; - remoteInfo = YYModel; - }; - E2F7E2998162B148B91D328B73DF9F38 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 82B0A41D3031FF27D78E17B0A9A46FB0; - remoteInfo = MBProgressHUD; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 00BAF7C4E2492F63C9589A48B9A174F5 /* GPUImageMovieComposition.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageMovieComposition.h; path = framework/Source/GPUImageMovieComposition.h; sourceTree = ""; }; - 00D7FBFB94E92C7589C179A64EA9B9E1 /* GPUImageAdaptiveThresholdFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageAdaptiveThresholdFilter.m; path = framework/Source/GPUImageAdaptiveThresholdFilter.m; sourceTree = ""; }; - 019AEDB1F84B03733946BD4BAABB969C /* YYWebImageOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YYWebImageOperation.h; path = YYWebImage/YYWebImageOperation.h; sourceTree = ""; }; - 01B971D8030BF11EC3D14181720444C4 /* MKAnnotationView+YYWebImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MKAnnotationView+YYWebImage.h"; path = "YYWebImage/Categories/MKAnnotationView+YYWebImage.h"; sourceTree = ""; }; - 0274C1DACB9A0794CFD00841FAE59E3D /* GPUImageZoomBlurFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageZoomBlurFilter.m; path = framework/Source/GPUImageZoomBlurFilter.m; sourceTree = ""; }; - 03A0D571B1A527AB8B7B3CA882F4D673 /* GPUImageBoxBlurFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageBoxBlurFilter.h; path = framework/Source/GPUImageBoxBlurFilter.h; sourceTree = ""; }; - 048641897F1CF7D044ACD0D40581C549 /* GPUImageCannyEdgeDetectionFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageCannyEdgeDetectionFilter.m; path = framework/Source/GPUImageCannyEdgeDetectionFilter.m; sourceTree = ""; }; - 04EED508463C74DA6E7C59026CB90BE8 /* GPUImageHueFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageHueFilter.h; path = framework/Source/GPUImageHueFilter.h; sourceTree = ""; }; - 05AE57422D69487A72FEC0CB766E61D0 /* GPUImageTiltShiftFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageTiltShiftFilter.h; path = framework/Source/GPUImageTiltShiftFilter.h; sourceTree = ""; }; - 05C8A3D41E95FB4EF796E14A592986C7 /* NSArray+MASAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSArray+MASAdditions.m"; path = "Masonry/NSArray+MASAdditions.m"; sourceTree = ""; }; - 074228E092340DEFE657CAF4F22AF822 /* GPUImageSourceOverBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageSourceOverBlendFilter.h; path = framework/Source/GPUImageSourceOverBlendFilter.h; sourceTree = ""; }; - 07C2E5E0DB6558AF1D582E8DD0D244EB /* GPUImageThresholdedNonMaximumSuppressionFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageThresholdedNonMaximumSuppressionFilter.m; path = framework/Source/GPUImageThresholdedNonMaximumSuppressionFilter.m; sourceTree = ""; }; - 080F15FCC36CE02B5AA7B6A38D2A6F1C /* GPUImageRGBErosionFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageRGBErosionFilter.m; path = framework/Source/GPUImageRGBErosionFilter.m; sourceTree = ""; }; - 08FB776087C19D638AA775DF1EA2E6A6 /* GPUImageRawDataOutput.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageRawDataOutput.h; path = framework/Source/GPUImageRawDataOutput.h; sourceTree = ""; }; - 08FD869A4FD865D449B925CD47230E72 /* GPUImageDirectionalNonMaximumSuppressionFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageDirectionalNonMaximumSuppressionFilter.h; path = framework/Source/GPUImageDirectionalNonMaximumSuppressionFilter.h; sourceTree = ""; }; - 0920AF97BC9AA2C404C3E60972978562 /* UIButton+YYWebImage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIButton+YYWebImage.m"; path = "YYWebImage/Categories/UIButton+YYWebImage.m"; sourceTree = ""; }; - 092384ABCABB5474EAF3E9D8F02DF29F /* GPUImageWeakPixelInclusionFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageWeakPixelInclusionFilter.m; path = framework/Source/GPUImageWeakPixelInclusionFilter.m; sourceTree = ""; }; - 094F16B0BD56037708312F6A3D1774F3 /* YYImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YYImage.h; path = YYImage/YYImage.h; sourceTree = ""; }; - 0B4A1372A24E73913DC7C605E4BD9472 /* libPods-DarkMode.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = "libPods-DarkMode.a"; path = "libPods-DarkMode.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 0C250AC091347FFBBF15D1616FB339BA /* GPUImageAddBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageAddBlendFilter.m; path = framework/Source/GPUImageAddBlendFilter.m; sourceTree = ""; }; - 0C6F4829D47D1826F47CDC4264F9F6A8 /* libYYImage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = libYYImage.a; path = libYYImage.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 0CA0BA0CC8335A694D5350A133298DB3 /* GPUImageTwoInputCrossTextureSamplingFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageTwoInputCrossTextureSamplingFilter.h; path = framework/Source/GPUImageTwoInputCrossTextureSamplingFilter.h; sourceTree = ""; }; - 0D0402BAF334A2BDC1E4932E93A77CFD /* YYModel-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "YYModel-prefix.pch"; sourceTree = ""; }; - 0D5623738ABFF1744B71396958D31566 /* MASLayoutConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASLayoutConstraint.h; path = Masonry/MASLayoutConstraint.h; sourceTree = ""; }; - 0E198F28897BDB4F191CE84351A84102 /* GPUImageTextureOutput.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageTextureOutput.h; path = framework/Source/GPUImageTextureOutput.h; sourceTree = ""; }; - 0E3174DCAC3A1A90A069C1EFAE99859F /* GPUImageColorPackingFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageColorPackingFilter.h; path = framework/Source/GPUImageColorPackingFilter.h; sourceTree = ""; }; - 0E48FED45DEF3A3929689CA91C2C802C /* GPUImageTransformFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageTransformFilter.h; path = framework/Source/GPUImageTransformFilter.h; sourceTree = ""; }; - 0F5D87CE6703E1941A5580858F307A6D /* GPUImageDirectionalSobelEdgeDetectionFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageDirectionalSobelEdgeDetectionFilter.h; path = framework/Source/GPUImageDirectionalSobelEdgeDetectionFilter.h; sourceTree = ""; }; - 0F6459CEEE271680736FA479FD981BD4 /* GPUImageColorDodgeBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageColorDodgeBlendFilter.m; path = framework/Source/GPUImageColorDodgeBlendFilter.m; sourceTree = ""; }; - 10015A94BC5970A447441E41EFA84CC4 /* GPUImageHighlightShadowFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageHighlightShadowFilter.m; path = framework/Source/GPUImageHighlightShadowFilter.m; sourceTree = ""; }; - 10AF522841E0BF1975899E1F731DDF5D /* GPUImageFilterGroup.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageFilterGroup.h; path = framework/Source/GPUImageFilterGroup.h; sourceTree = ""; }; - 115B979659F12A2946B4CE9FB629FC55 /* GPUImage3x3TextureSamplingFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImage3x3TextureSamplingFilter.h; path = framework/Source/GPUImage3x3TextureSamplingFilter.h; sourceTree = ""; }; - 11CCBC30AD14409191CFABD8D074A58D /* GPUImageFilterPipeline.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageFilterPipeline.h; path = framework/Source/GPUImageFilterPipeline.h; sourceTree = ""; }; - 129DAE9BAABDCB922089CE7D3BDF76EC /* GPUImageAdaptiveThresholdFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageAdaptiveThresholdFilter.h; path = framework/Source/GPUImageAdaptiveThresholdFilter.h; sourceTree = ""; }; - 12F2B7D58256DFE9C2869DEE816D2FDD /* GPUImageChromaKeyFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageChromaKeyFilter.h; path = framework/Source/GPUImageChromaKeyFilter.h; sourceTree = ""; }; - 13093D7BD9574A7D40FB42A21DB87F15 /* MASConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASConstraint.h; path = Masonry/MASConstraint.h; sourceTree = ""; }; - 1495EAEF4EC6B8FB6E18881881B3573B /* GPUImageDirectionalNonMaximumSuppressionFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageDirectionalNonMaximumSuppressionFilter.m; path = framework/Source/GPUImageDirectionalNonMaximumSuppressionFilter.m; sourceTree = ""; }; - 1577D323A093A5E9B341C97A2C56FDFF /* GPUImageSaturationFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageSaturationFilter.m; path = framework/Source/GPUImageSaturationFilter.m; sourceTree = ""; }; - 15E496E703C5AD87E7989377C681D73B /* GPUImageAmatorkaFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageAmatorkaFilter.m; path = framework/Source/GPUImageAmatorkaFilter.m; sourceTree = ""; }; - 1601092CB8E312022FDE49393A610FA4 /* MASCompositeConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASCompositeConstraint.h; path = Masonry/MASCompositeConstraint.h; sourceTree = ""; }; - 160895B89A8B29B177F36E3AF17C2C11 /* YYCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YYCache.m; path = YYCache/YYCache.m; sourceTree = ""; }; - 169DF30CA515684B51A770DE262AC808 /* GPUImageGlassSphereFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageGlassSphereFilter.h; path = framework/Source/GPUImageGlassSphereFilter.h; sourceTree = ""; }; - 16C4DC343FBAC71D13FF4FA9BCE10709 /* Pods-DarkMode.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-DarkMode.debug.xcconfig"; sourceTree = ""; }; - 16D91E4D58A94C5524A115536224EA76 /* GPUImageColorBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageColorBlendFilter.h; path = framework/Source/GPUImageColorBlendFilter.h; sourceTree = ""; }; - 1A8E625D6539753D6AC67978B97C5D7C /* GPUImageRGBOpeningFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageRGBOpeningFilter.h; path = framework/Source/GPUImageRGBOpeningFilter.h; sourceTree = ""; }; - 1AF1FBA24B5573418B3316CD3B2CAF8B /* GPUImageLinearBurnBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageLinearBurnBlendFilter.h; path = framework/Source/GPUImageLinearBurnBlendFilter.h; sourceTree = ""; }; - 1B209441C9B2647C1E347736EE8FC64A /* GPUImage3x3ConvolutionFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImage3x3ConvolutionFilter.m; path = framework/Source/GPUImage3x3ConvolutionFilter.m; sourceTree = ""; }; - 1E01E00886BEDC0765B232733C255C1C /* GPUImageMissEtikateFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageMissEtikateFilter.m; path = framework/Source/GPUImageMissEtikateFilter.m; sourceTree = ""; }; - 1E272A947106122CD1F27C631D653DA4 /* GPUImageExclusionBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageExclusionBlendFilter.h; path = framework/Source/GPUImageExclusionBlendFilter.h; sourceTree = ""; }; - 1E9095CF9176D72147052B3FD215EF7F /* GPUImagePicture+TextureSubimage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "GPUImagePicture+TextureSubimage.h"; path = "framework/Source/iOS/GPUImagePicture+TextureSubimage.h"; sourceTree = ""; }; - 1F0C80FAC0118D3106441EE7BCBCFF00 /* GPUImageUnsharpMaskFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageUnsharpMaskFilter.m; path = framework/Source/GPUImageUnsharpMaskFilter.m; sourceTree = ""; }; - 1F2C1EF174D0C89A1ECD8D871814D3C5 /* GPUImageErosionFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageErosionFilter.h; path = framework/Source/GPUImageErosionFilter.h; sourceTree = ""; }; - 1FFED36A657123030ABB700256D73F15 /* libMasonry.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = libMasonry.a; path = libMasonry.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 202D068CFDA5C22DA922D9FD075D1806 /* GPUImageBoxBlurFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageBoxBlurFilter.m; path = framework/Source/GPUImageBoxBlurFilter.m; sourceTree = ""; }; - 20BC00B3DDB29110A58176CE51605FD4 /* GPUImagePerlinNoiseFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImagePerlinNoiseFilter.m; path = framework/Source/GPUImagePerlinNoiseFilter.m; sourceTree = ""; }; - 20C5BE19C1459E39FC196D7A94B0CBE9 /* GPUImageSharpenFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageSharpenFilter.m; path = framework/Source/GPUImageSharpenFilter.m; sourceTree = ""; }; - 2119B781CCC19BD3D0A42F303D2E7812 /* GPUImageCGAColorspaceFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageCGAColorspaceFilter.h; path = framework/Source/GPUImageCGAColorspaceFilter.h; sourceTree = ""; }; - 216F8CFBA824F61AE51F0BE1FB37998B /* _YYWebImageSetter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = _YYWebImageSetter.m; path = YYWebImage/Categories/_YYWebImageSetter.m; sourceTree = ""; }; - 219E2548D3FF4C96F4ED257B47311123 /* GPUImageSaturationFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageSaturationFilter.h; path = framework/Source/GPUImageSaturationFilter.h; sourceTree = ""; }; - 21B2916276232C456951467038D3E2FF /* GPUImageMaskFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageMaskFilter.m; path = framework/Source/GPUImageMaskFilter.m; sourceTree = ""; }; - 21CD080746E9E7BC9C0BA1E1A2EDF8F0 /* GPUImageMovieWriter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageMovieWriter.h; path = framework/Source/iOS/GPUImageMovieWriter.h; sourceTree = ""; }; - 22245274C4F286C6221A887D6CD7F1AE /* GPUImageStretchDistortionFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageStretchDistortionFilter.m; path = framework/Source/GPUImageStretchDistortionFilter.m; sourceTree = ""; }; - 2276B332FA8EDDC35FE32348D3EB368C /* GPUImageLineGenerator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageLineGenerator.m; path = framework/Source/GPUImageLineGenerator.m; sourceTree = ""; }; - 228003B3476B41761F56C932AA1DE129 /* GPUImagePolarPixellateFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImagePolarPixellateFilter.h; path = framework/Source/GPUImagePolarPixellateFilter.h; sourceTree = ""; }; - 240C513A27F958A5DE57B92A02EA4229 /* GPUImageThresholdEdgeDetectionFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageThresholdEdgeDetectionFilter.h; path = framework/Source/GPUImageThresholdEdgeDetectionFilter.h; sourceTree = ""; }; - 2428E8C70A2E6595B6031EC3C1851FEF /* GPUImageTextureInput.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageTextureInput.h; path = framework/Source/GPUImageTextureInput.h; sourceTree = ""; }; - 250D4D5BDE79FE3FB3D8E6BDF13C6F79 /* GPUImageOpeningFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageOpeningFilter.m; path = framework/Source/GPUImageOpeningFilter.m; sourceTree = ""; }; - 254E957A25195EAAC2658009BDAEEBBD /* GPUImageShiTomasiFeatureDetectionFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageShiTomasiFeatureDetectionFilter.h; path = framework/Source/GPUImageShiTomasiFeatureDetectionFilter.h; sourceTree = ""; }; - 25B452C9C925DADC958E77C39081288F /* GPUImageTransformFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageTransformFilter.m; path = framework/Source/GPUImageTransformFilter.m; sourceTree = ""; }; - 2715DCC6112CFACF55C762832D38626D /* GPUImageMotionDetector.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageMotionDetector.h; path = framework/Source/GPUImageMotionDetector.h; sourceTree = ""; }; - 27A2C6937109C3C8643FB3E370CDBE29 /* GPUImageDissolveBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageDissolveBlendFilter.m; path = framework/Source/GPUImageDissolveBlendFilter.m; sourceTree = ""; }; - 29114F4BF994DD99DA8B15BD714B5488 /* GPUImageKuwaharaRadius3Filter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageKuwaharaRadius3Filter.h; path = framework/Source/GPUImageKuwaharaRadius3Filter.h; sourceTree = ""; }; - 291AEAB6C085560A71960DDDD62ACD1A /* GPUImageGaussianBlurFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageGaussianBlurFilter.m; path = framework/Source/GPUImageGaussianBlurFilter.m; sourceTree = ""; }; - 295A7F01A1F9CE9A049C72379F8EC892 /* GPUImageView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageView.h; path = framework/Source/iOS/GPUImageView.h; sourceTree = ""; }; - 2988FF2F5DA771E11045F136F9BD4F0A /* GPUImageHighlightShadowFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageHighlightShadowFilter.h; path = framework/Source/GPUImageHighlightShadowFilter.h; sourceTree = ""; }; - 2A0042D79436E9C952B47D4763A1C4AE /* GPUImage-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "GPUImage-dummy.m"; sourceTree = ""; }; - 2B166651BD2944A773F9537AEC00AF13 /* Pods-DarkMode-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-DarkMode-dummy.m"; sourceTree = ""; }; - 2B2CFE441A1614F51B47AA982B4E448B /* GPUImageGaussianSelectiveBlurFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageGaussianSelectiveBlurFilter.m; path = framework/Source/GPUImageGaussianSelectiveBlurFilter.m; sourceTree = ""; }; - 2B3AB6691A881BF883BB176FDAB07FBA /* GPUImageHalftoneFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageHalftoneFilter.m; path = framework/Source/GPUImageHalftoneFilter.m; sourceTree = ""; }; - 2BB60AA6A277030CEA93B362B1061701 /* GPUImageXYDerivativeFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageXYDerivativeFilter.m; path = framework/Source/GPUImageXYDerivativeFilter.m; sourceTree = ""; }; - 2CE39347324DF5B3FC2761B6D191DA9C /* GPUImageHarrisCornerDetectionFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageHarrisCornerDetectionFilter.h; path = framework/Source/GPUImageHarrisCornerDetectionFilter.h; sourceTree = ""; }; - 2E5AC46F45E4451E72AC537BB70B1812 /* YYCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YYCache.h; path = YYCache/YYCache.h; sourceTree = ""; }; - 2EAC8FE75CB608768A2CEA2F31EDF290 /* GPUImageFilterPipeline.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageFilterPipeline.m; path = framework/Source/GPUImageFilterPipeline.m; sourceTree = ""; }; - 30871DDE7586CFF91A2ACC7F23FF6105 /* GPUImageHighPassFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageHighPassFilter.m; path = framework/Source/GPUImageHighPassFilter.m; sourceTree = ""; }; - 30A8C055AB3C18A2E3FE4F47E4F66E5A /* GPUImageTwoInputFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageTwoInputFilter.m; path = framework/Source/GPUImageTwoInputFilter.m; sourceTree = ""; }; - 31214193F010827DB7A59D7F34A65AF0 /* YYModel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YYModel.h; path = YYModel/YYModel.h; sourceTree = ""; }; - 3193AAC04525E3412D850A3D7AD99612 /* GPUImageChromaKeyFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageChromaKeyFilter.m; path = framework/Source/GPUImageChromaKeyFilter.m; sourceTree = ""; }; - 31F4DFCE2BAF8205326A79D123842D37 /* GPUImageRGBDilationFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageRGBDilationFilter.h; path = framework/Source/GPUImageRGBDilationFilter.h; sourceTree = ""; }; - 3262E2097D957FBD0444889742CB1C80 /* GPUImageHSBFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageHSBFilter.m; path = framework/Source/GPUImageHSBFilter.m; sourceTree = ""; }; - 34284363F58BE296025C3C9CBD8F317C /* GPUImageMedianFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageMedianFilter.m; path = framework/Source/GPUImageMedianFilter.m; sourceTree = ""; }; - 34804E531C9635A205640CD71C357B77 /* GPUImageMotionBlurFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageMotionBlurFilter.h; path = framework/Source/GPUImageMotionBlurFilter.h; sourceTree = ""; }; - 34E2DEEB4F0ADF11F9C9E23D43C1A3B6 /* GPUImageFalseColorFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageFalseColorFilter.m; path = framework/Source/GPUImageFalseColorFilter.m; sourceTree = ""; }; - 35D609B903920B4F5B05401FBC7E489D /* GPUImageNormalBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageNormalBlendFilter.h; path = framework/Source/GPUImageNormalBlendFilter.h; sourceTree = ""; }; - 36454A100B7DDEDEA1E782EF2E9E27AC /* NSLayoutConstraint+MASDebugAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSLayoutConstraint+MASDebugAdditions.h"; path = "Masonry/NSLayoutConstraint+MASDebugAdditions.h"; sourceTree = ""; }; - 36A3F94120C780455E9F79C31D756DEC /* GLProgram.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GLProgram.h; path = framework/Source/GLProgram.h; sourceTree = ""; }; - 36B4A09ADA586EFD92A79ECD4C0E35A8 /* GPUImageThresholdEdgeDetectionFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageThresholdEdgeDetectionFilter.m; path = framework/Source/GPUImageThresholdEdgeDetectionFilter.m; sourceTree = ""; }; - 372EFFE9AC19817C164303970B18F910 /* YYImageCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YYImageCache.h; path = YYWebImage/YYImageCache.h; sourceTree = ""; }; - 375E8723E93DD1BD999307185560F30B /* Pods-DarkMode-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-DarkMode-resources.sh"; sourceTree = ""; }; - 37B3E429270DF855D2663E4BE0DCE666 /* GPUImageLanczosResamplingFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageLanczosResamplingFilter.m; path = framework/Source/GPUImageLanczosResamplingFilter.m; sourceTree = ""; }; - 38948BFE21048F7C6D91B1281E521F1B /* GPUImageSobelEdgeDetectionFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageSobelEdgeDetectionFilter.m; path = framework/Source/GPUImageSobelEdgeDetectionFilter.m; sourceTree = ""; }; - 3918FDF9EBD2B1FA91FD529E6E34785A /* GPUImageMovie.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageMovie.h; path = framework/Source/GPUImageMovie.h; sourceTree = ""; }; - 3C138582918D37CF364E6D3C9898D68F /* GPUImageGrayscaleFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageGrayscaleFilter.h; path = framework/Source/GPUImageGrayscaleFilter.h; sourceTree = ""; }; - 3C8EF79EE8E13A7229E1AF925AEC3BC4 /* GPUImageSingleComponentGaussianBlurFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageSingleComponentGaussianBlurFilter.h; path = framework/Source/GPUImageSingleComponentGaussianBlurFilter.h; sourceTree = ""; }; - 3CF95A800A5428B6D2C82CDC82A21CD5 /* GPUImageSmoothToonFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageSmoothToonFilter.h; path = framework/Source/GPUImageSmoothToonFilter.h; sourceTree = ""; }; - 3D59E89941BC318DF7FC1D5BC49895CD /* _YYWebImageSetter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = _YYWebImageSetter.h; path = YYWebImage/Categories/_YYWebImageSetter.h; sourceTree = ""; }; - 3E5E02B856C988A000B10E5E5512B56A /* YYImageCoder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YYImageCoder.m; path = YYImage/YYImageCoder.m; sourceTree = ""; }; - 3E7EB13B2D474F8DE4852C033BF689FB /* MASViewAttribute.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASViewAttribute.h; path = Masonry/MASViewAttribute.h; sourceTree = ""; }; - 3F37E42BC4BE8E0517824BABC9869273 /* GPUImageSaturationBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageSaturationBlendFilter.h; path = framework/Source/GPUImageSaturationBlendFilter.h; sourceTree = ""; }; - 3FA9A4C47EC9F4059DAB7AADC578E5AF /* GPUImageLineGenerator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageLineGenerator.h; path = framework/Source/GPUImageLineGenerator.h; sourceTree = ""; }; - 3FE5C658FDFFD20E3BCD7C36D40923A3 /* GPUImageVideoCamera.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageVideoCamera.h; path = framework/Source/GPUImageVideoCamera.h; sourceTree = ""; }; - 3FFF18D3BD6B92729084311D3FD98998 /* Masonry.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Masonry.release.xcconfig; sourceTree = ""; }; - 404551280AEA0058459B3385F82AFBBA /* GPUImageGaussianBlurPositionFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageGaussianBlurPositionFilter.m; path = framework/Source/GPUImageGaussianBlurPositionFilter.m; sourceTree = ""; }; - 40BEB1831EED3C7A7E80C4057D3DA022 /* GPUImageDivideBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageDivideBlendFilter.m; path = framework/Source/GPUImageDivideBlendFilter.m; sourceTree = ""; }; - 414E85F24E79E32F8EA8031796253C7F /* GPUImagePrewittEdgeDetectionFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImagePrewittEdgeDetectionFilter.m; path = framework/Source/GPUImagePrewittEdgeDetectionFilter.m; sourceTree = ""; }; - 41E7FFB3E5D0BA8ABC62E1A89D3063A8 /* YYKVStorage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YYKVStorage.h; path = YYCache/YYKVStorage.h; sourceTree = ""; }; - 4272FC95B847753C0B6BA23100C3957E /* GPUImagePinchDistortionFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImagePinchDistortionFilter.h; path = framework/Source/GPUImagePinchDistortionFilter.h; sourceTree = ""; }; - 4284D70C7F26D1B5D00CB148C3E562E1 /* GPUImageSingleComponentGaussianBlurFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageSingleComponentGaussianBlurFilter.m; path = framework/Source/GPUImageSingleComponentGaussianBlurFilter.m; sourceTree = ""; }; - 42C7A8AF75309C3CA628C0B8775A0F0B /* GPUImageAmatorkaFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageAmatorkaFilter.h; path = framework/Source/GPUImageAmatorkaFilter.h; sourceTree = ""; }; - 42D084FF6A05E8F634B9ECC121BB2F70 /* GPUImageSolidColorGenerator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageSolidColorGenerator.m; path = framework/Source/GPUImageSolidColorGenerator.m; sourceTree = ""; }; - 43471FC538F7533EBC5AA010B09E0958 /* GPUImageOutput.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageOutput.h; path = framework/Source/GPUImageOutput.h; sourceTree = ""; }; - 43A18B72D843666583E43734D2462B4F /* GPUImagePosterizeFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImagePosterizeFilter.m; path = framework/Source/GPUImagePosterizeFilter.m; sourceTree = ""; }; - 43F07509067BACE67AB5E9CE46DBB3EE /* GPUImageGammaFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageGammaFilter.m; path = framework/Source/GPUImageGammaFilter.m; sourceTree = ""; }; - 446D6F21C19F21359994D8C61A378A84 /* YYImage.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = YYImage.release.xcconfig; sourceTree = ""; }; - 453BE721D27626D4753B1F021A0126F4 /* GPUImageKuwaharaRadius3Filter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageKuwaharaRadius3Filter.m; path = framework/Source/GPUImageKuwaharaRadius3Filter.m; sourceTree = ""; }; - 462A9647EF473D7371FF63E7DF5E9FB1 /* GPUImageAlphaBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageAlphaBlendFilter.m; path = framework/Source/GPUImageAlphaBlendFilter.m; sourceTree = ""; }; - 467740B1EE1788F570B996D82E451066 /* GPUImageColorInvertFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageColorInvertFilter.h; path = framework/Source/GPUImageColorInvertFilter.h; sourceTree = ""; }; - 47104284B40E3FE25D823BBBF6BBD751 /* GPUImageDivideBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageDivideBlendFilter.h; path = framework/Source/GPUImageDivideBlendFilter.h; sourceTree = ""; }; - 4713F7EF42A07902267E6A57EBC07D50 /* YYCache.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = YYCache.release.xcconfig; sourceTree = ""; }; - 488651029866527C3B2644FD81E92587 /* GPUImageMotionBlurFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageMotionBlurFilter.m; path = framework/Source/GPUImageMotionBlurFilter.m; sourceTree = ""; }; - 48ACF38225AF5129416A1F090F6D3286 /* libYYCache.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = libYYCache.a; path = libYYCache.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 48BC391B2B9B8DF60B1BC90CF239FC80 /* lookup_miss_etikate.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = lookup_miss_etikate.png; path = framework/Resources/lookup_miss_etikate.png; sourceTree = ""; }; - 48C35BCA747620F3BF149953BFDC422D /* GPUImageErosionFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageErosionFilter.m; path = framework/Source/GPUImageErosionFilter.m; sourceTree = ""; }; - 48F476DACC4D9202F44C5407ACDA8410 /* YYWebImageOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YYWebImageOperation.m; path = YYWebImage/YYWebImageOperation.m; sourceTree = ""; }; - 49B9B7911201EAA735B877B4E99D31D9 /* GPUImageNormalBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageNormalBlendFilter.m; path = framework/Source/GPUImageNormalBlendFilter.m; sourceTree = ""; }; - 49E415F2BA5768C469A662DF8C823B3C /* GPUImageHistogramGenerator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageHistogramGenerator.m; path = framework/Source/GPUImageHistogramGenerator.m; sourceTree = ""; }; - 4A0251929026FA746DAF38200C6045F2 /* GPUImageSubtractBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageSubtractBlendFilter.h; path = framework/Source/GPUImageSubtractBlendFilter.h; sourceTree = ""; }; - 4A1109257C4F91B78B674D3ED606F875 /* GPUImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImage.h; path = framework/Source/GPUImage.h; sourceTree = ""; }; - 4A6F1BA241429526CAA01D945FD69E28 /* GPUImageHighPassFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageHighPassFilter.h; path = framework/Source/GPUImageHighPassFilter.h; sourceTree = ""; }; - 4A7B42C55528946ABE27DCA7F4A86E7A /* GPUImageNonMaximumSuppressionFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageNonMaximumSuppressionFilter.m; path = framework/Source/GPUImageNonMaximumSuppressionFilter.m; sourceTree = ""; }; - 4A94921FCB9C25F627D3B1EB025EB097 /* GPUImageStretchDistortionFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageStretchDistortionFilter.h; path = framework/Source/GPUImageStretchDistortionFilter.h; sourceTree = ""; }; - 4CE0EB4E232A38B13CACAA200001C7D9 /* GPUImageMotionDetector.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageMotionDetector.m; path = framework/Source/GPUImageMotionDetector.m; sourceTree = ""; }; - 4EB243D1C497784152C266E096C23C6C /* GPUImageGlassSphereFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageGlassSphereFilter.m; path = framework/Source/GPUImageGlassSphereFilter.m; sourceTree = ""; }; - 4FC1978206616CE319648B302B05AA8A /* libYYWebImage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = libYYWebImage.a; path = libYYWebImage.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 5002004ECCBA2AFB115693A8FF292F8D /* GPUImageAddBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageAddBlendFilter.h; path = framework/Source/GPUImageAddBlendFilter.h; sourceTree = ""; }; - 5021D951EBE0EE5ACBFF0A1D5BF60EC2 /* GPUImagePrewittEdgeDetectionFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImagePrewittEdgeDetectionFilter.h; path = framework/Source/GPUImagePrewittEdgeDetectionFilter.h; sourceTree = ""; }; - 504C0F55ECD0EE366A432BE3CAF79E1F /* GPUImage.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GPUImage.release.xcconfig; sourceTree = ""; }; - 50E15C340F7D31DE893B684AFF6EC189 /* GPUImageFASTCornerDetectionFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageFASTCornerDetectionFilter.m; path = framework/Source/GPUImageFASTCornerDetectionFilter.m; sourceTree = ""; }; - 525E00D440284C93311DF077591CDA15 /* GPUImageSoftEleganceFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageSoftEleganceFilter.h; path = framework/Source/GPUImageSoftEleganceFilter.h; sourceTree = ""; }; - 527337E5AE7218053824FE826DE95FB6 /* GPUImageBuffer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageBuffer.h; path = framework/Source/GPUImageBuffer.h; sourceTree = ""; }; - 5278FBF2D16D0E9492F81D50E1B4E389 /* GPUImage.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GPUImage.debug.xcconfig; sourceTree = ""; }; - 533CF0E1A935E0C8D6084DE984AA9A48 /* GPUImageLaplacianFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageLaplacianFilter.m; path = framework/Source/GPUImageLaplacianFilter.m; sourceTree = ""; }; - 537E9A1D3C9B19E06AD252A90F35F4FC /* GPUImageTwoInputFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageTwoInputFilter.h; path = framework/Source/GPUImageTwoInputFilter.h; sourceTree = ""; }; - 5388C8B9509AE2A725C77FB08EAB1262 /* GPUImageShiTomasiFeatureDetectionFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageShiTomasiFeatureDetectionFilter.m; path = framework/Source/GPUImageShiTomasiFeatureDetectionFilter.m; sourceTree = ""; }; - 53D16559576FCC95A4CD46C46C5DE443 /* GPUImageTwoPassTextureSamplingFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageTwoPassTextureSamplingFilter.m; path = framework/Source/GPUImageTwoPassTextureSamplingFilter.m; sourceTree = ""; }; - 55DC707CC4179395588164EA0C8D4DF8 /* YYModel-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "YYModel-dummy.m"; sourceTree = ""; }; - 56D2D8153149A60C61AB14238CE5A721 /* GPUImageRGBClosingFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageRGBClosingFilter.h; path = framework/Source/GPUImageRGBClosingFilter.h; sourceTree = ""; }; - 571C0946C15922F37A4FF9DC53636F23 /* GPUImageBuffer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageBuffer.m; path = framework/Source/GPUImageBuffer.m; sourceTree = ""; }; - 59C6E40234EEDDD4087F2CFFF63582D0 /* GPUImageTwoInputCrossTextureSamplingFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageTwoInputCrossTextureSamplingFilter.m; path = framework/Source/GPUImageTwoInputCrossTextureSamplingFilter.m; sourceTree = ""; }; - 5A14EDB5BB818BEE5CEE11AB9273F285 /* GPUImageThreeInputFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageThreeInputFilter.h; path = framework/Source/GPUImageThreeInputFilter.h; sourceTree = ""; }; - 5AB2E9FBA9B5DC6C3B50148EBA2EB69C /* GPUImageJFAVoronoiFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageJFAVoronoiFilter.m; path = framework/Source/GPUImageJFAVoronoiFilter.m; sourceTree = ""; }; - 5AF9D53BF78794179DA5A171FD200059 /* YYWebImage.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = YYWebImage.debug.xcconfig; sourceTree = ""; }; - 5B231C196006B4B6C3DD281978E5EB74 /* GPUImageColorPackingFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageColorPackingFilter.m; path = framework/Source/GPUImageColorPackingFilter.m; sourceTree = ""; }; - 5B86F3F70B22B26EC06C5C412D9B9733 /* GPUImageLowPassFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageLowPassFilter.m; path = framework/Source/GPUImageLowPassFilter.m; sourceTree = ""; }; - 5B933CA3EC0B18A8DB363F31A85D1268 /* GPUImagePolkaDotFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImagePolkaDotFilter.m; path = framework/Source/GPUImagePolkaDotFilter.m; sourceTree = ""; }; - 5C0B54E85F3F7357A3084FAC6447AFF1 /* ViewController+MASAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "ViewController+MASAdditions.h"; path = "Masonry/ViewController+MASAdditions.h"; sourceTree = ""; }; - 5C40FD404F6B8A2300E4B45AA2B6F9A8 /* YYWebImageManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YYWebImageManager.h; path = YYWebImage/YYWebImageManager.h; sourceTree = ""; }; - 5D6101DA1E24CEAF212864D149AAA311 /* GPUImageHistogramFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageHistogramFilter.m; path = framework/Source/GPUImageHistogramFilter.m; sourceTree = ""; }; - 5D6604B45B92B4410C171D7E0C6B4939 /* GPUImageToneCurveFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageToneCurveFilter.h; path = framework/Source/GPUImageToneCurveFilter.h; sourceTree = ""; }; - 5D7C1EBCB0F669526CC10ADAA17FB565 /* MBProgressHUD-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MBProgressHUD-prefix.pch"; sourceTree = ""; }; - 5DA7010E9B001189E58C1D4FAF928DF7 /* YYCache.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = YYCache.debug.xcconfig; sourceTree = ""; }; - 5DADF97A372B96269C7E574FFD19EA84 /* GPUImageSepiaFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageSepiaFilter.m; path = framework/Source/GPUImageSepiaFilter.m; sourceTree = ""; }; - 5E64875CACD9293F8463A7DEB77900AF /* MASConstraintMaker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASConstraintMaker.h; path = Masonry/MASConstraintMaker.h; sourceTree = ""; }; - 5F066292FE00E22395481D12B85DCF15 /* YYCache-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "YYCache-dummy.m"; sourceTree = ""; }; - 5F8F677D95958C9F3D7EA1F6761CD291 /* YYImage.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = YYImage.debug.xcconfig; sourceTree = ""; }; - 611CC398C3A952328326F836188CEC88 /* GPUImageCrosshairGenerator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageCrosshairGenerator.h; path = framework/Source/GPUImageCrosshairGenerator.h; sourceTree = ""; }; - 61E2A63537B14F7A60668071C08241DE /* GPUImageMultiplyBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageMultiplyBlendFilter.h; path = framework/Source/GPUImageMultiplyBlendFilter.h; sourceTree = ""; }; - 621DA413177A46757ACA5C0C17FE0C8C /* GPUImageTextureOutput.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageTextureOutput.m; path = framework/Source/GPUImageTextureOutput.m; sourceTree = ""; }; - 63157528C8EC3BBA57A086A9E876519F /* GPUImageDissolveBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageDissolveBlendFilter.h; path = framework/Source/GPUImageDissolveBlendFilter.h; sourceTree = ""; }; - 6460B60CAEB361F43B409D943DD5919E /* GPUImageLevelsFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageLevelsFilter.h; path = framework/Source/GPUImageLevelsFilter.h; sourceTree = ""; }; - 64B98E97EBB4B89FF8C0A73B4905060A /* GPUImageDifferenceBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageDifferenceBlendFilter.h; path = framework/Source/GPUImageDifferenceBlendFilter.h; sourceTree = ""; }; - 6641303C0E807B1DB7DE0B014814E30A /* YYImage-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "YYImage-dummy.m"; sourceTree = ""; }; - 6679F37F751FAB9174C4595A35CF4822 /* GPUImageContext.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageContext.h; path = framework/Source/iOS/GPUImageContext.h; sourceTree = ""; }; - 675DA2B87C4D3A22040B4457A6387B04 /* GPUImageFilterGroup.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageFilterGroup.m; path = framework/Source/GPUImageFilterGroup.m; sourceTree = ""; }; - 68619D6BC015E7B9AD2E0EF3660EC99B /* YYWebImage-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "YYWebImage-dummy.m"; sourceTree = ""; }; - 6872FC509316C9B4DCA67FFA969849E6 /* GPUImageDarkenBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageDarkenBlendFilter.m; path = framework/Source/GPUImageDarkenBlendFilter.m; sourceTree = ""; }; - 68CD24B140838D08A6E5DD6A70FD8923 /* GPUImageMovie.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageMovie.m; path = framework/Source/GPUImageMovie.m; sourceTree = ""; }; - 69BEFC89CA92FA91FB606E547079BABE /* GPUImageContext.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageContext.m; path = framework/Source/iOS/GPUImageContext.m; sourceTree = ""; }; - 69E5EB77E2A5E329FE60A250611BF2FC /* GPUImagePosterizeFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImagePosterizeFilter.h; path = framework/Source/GPUImagePosterizeFilter.h; sourceTree = ""; }; - 69E7B0C997A3206F5C0D10C360A6D957 /* GPUImageCropFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageCropFilter.h; path = framework/Source/GPUImageCropFilter.h; sourceTree = ""; }; - 6CA047F4F7C29EBD892E71642C0B6FD0 /* GPUImageHoughTransformLineDetector.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageHoughTransformLineDetector.h; path = framework/Source/GPUImageHoughTransformLineDetector.h; sourceTree = ""; }; - 6CCD41C6BD2C0E9ABB3148B70C4BC918 /* GPUImageTextureInput.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageTextureInput.m; path = framework/Source/GPUImageTextureInput.m; sourceTree = ""; }; - 6DA0D34140F270C03A5A2D7F4CC54517 /* GPUImagePixellatePositionFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImagePixellatePositionFilter.h; path = framework/Source/GPUImagePixellatePositionFilter.h; sourceTree = ""; }; - 6DC692CA9FD5C1A42113F450FA649F67 /* GPUImageHSBFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageHSBFilter.h; path = framework/Source/GPUImageHSBFilter.h; sourceTree = ""; }; - 6E126A469B8B4CA1D5708D0C66DBCB45 /* GPUImageEmbossFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageEmbossFilter.m; path = framework/Source/GPUImageEmbossFilter.m; sourceTree = ""; }; - 6E747934866906927486DC94DEC4581B /* GPUImageRGBFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageRGBFilter.h; path = framework/Source/GPUImageRGBFilter.h; sourceTree = ""; }; - 6EEB662CC37ABBC8474275EEA42AB477 /* ViewController+MASAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "ViewController+MASAdditions.m"; path = "Masonry/ViewController+MASAdditions.m"; sourceTree = ""; }; - 6FAE5EFDF6BAE35B5464066D6F82F34E /* GPUImageFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageFilter.m; path = framework/Source/GPUImageFilter.m; sourceTree = ""; }; - 6FE16BE5263EBF1D2F9145482FAE76E3 /* GPUImageClosingFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageClosingFilter.h; path = framework/Source/GPUImageClosingFilter.h; sourceTree = ""; }; - 71669CD78F52A5CA28F626C8A16A194C /* GPUImageSepiaFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageSepiaFilter.h; path = framework/Source/GPUImageSepiaFilter.h; sourceTree = ""; }; - 71D502A5B132B8E2D515B9A975C85309 /* GPUImageFASTCornerDetectionFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageFASTCornerDetectionFilter.h; path = framework/Source/GPUImageFASTCornerDetectionFilter.h; sourceTree = ""; }; - 71F455391A9616D714CC8874A51F7EE6 /* GPUImageFramework.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageFramework.h; path = framework/Source/iOS/Framework/GPUImageFramework.h; sourceTree = ""; }; - 722AE0C698ABB0490DECD454A56B78D5 /* GPUImageAverageLuminanceThresholdFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageAverageLuminanceThresholdFilter.m; path = framework/Source/GPUImageAverageLuminanceThresholdFilter.m; sourceTree = ""; }; - 73B8731A5CF568F198781C8412733FB0 /* GPUImageColorBurnBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageColorBurnBlendFilter.h; path = framework/Source/GPUImageColorBurnBlendFilter.h; sourceTree = ""; }; - 751129785F65D4A3EA3332CE56D280DD /* GPUImageGrayscaleFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageGrayscaleFilter.m; path = framework/Source/GPUImageGrayscaleFilter.m; sourceTree = ""; }; - 768B4BE6A62741EA37180E7EC67437C1 /* MBProgressHUD.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = MBProgressHUD.h; sourceTree = ""; }; - 76CEE856E426B01553F3D79A1347C109 /* GPUImageChromaKeyBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageChromaKeyBlendFilter.m; path = framework/Source/GPUImageChromaKeyBlendFilter.m; sourceTree = ""; }; - 77A6428D36533AF050B1E9F92BF82FD8 /* GPUImageBilateralFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageBilateralFilter.h; path = framework/Source/GPUImageBilateralFilter.h; sourceTree = ""; }; - 77F4D03A5C3A7B3755BD05C6BC87D853 /* GPUImageStillCamera.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageStillCamera.h; path = framework/Source/GPUImageStillCamera.h; sourceTree = ""; }; - 784B2008FD82B473DC377FEEC4B7EFD4 /* GPUImageHardLightBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageHardLightBlendFilter.m; path = framework/Source/GPUImageHardLightBlendFilter.m; sourceTree = ""; }; - 78FB8998E490B19D8A2CFE9E092F2132 /* GPUImageContrastFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageContrastFilter.m; path = framework/Source/GPUImageContrastFilter.m; sourceTree = ""; }; - 795CA168A9604FBD8784D73FA8C9DE4A /* GPUImageCrosshairGenerator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageCrosshairGenerator.m; path = framework/Source/GPUImageCrosshairGenerator.m; sourceTree = ""; }; - 79E8CB24F46AA9A51F87BBDF2D0AC238 /* libGPUImage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = libGPUImage.a; path = libGPUImage.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 79F32CA2AC9383860E5A101F3891F01F /* GPUImageiOSBlurFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageiOSBlurFilter.h; path = framework/Source/GPUImageiOSBlurFilter.h; sourceTree = ""; }; - 7AF69C635DEFF07CF03F7EC5C93EECC6 /* GPUImageSoftLightBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageSoftLightBlendFilter.m; path = framework/Source/GPUImageSoftLightBlendFilter.m; sourceTree = ""; }; - 7B03CEF081AF2EB3E5F9FF382D2515F8 /* GPUImageAlphaBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageAlphaBlendFilter.h; path = framework/Source/GPUImageAlphaBlendFilter.h; sourceTree = ""; }; - 7B515D86A399467A37FA4BA15B8B0887 /* YYDiskCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YYDiskCache.m; path = YYCache/YYDiskCache.m; sourceTree = ""; }; - 7C17752936CF711DF066A5BA091BFA81 /* GPUImageLuminanceThresholdFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageLuminanceThresholdFilter.m; path = framework/Source/GPUImageLuminanceThresholdFilter.m; sourceTree = ""; }; - 7CD5AC12DA2322B95DFCB7F7D42FBD49 /* GPUImagePolarPixellateFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImagePolarPixellateFilter.m; path = framework/Source/GPUImagePolarPixellateFilter.m; sourceTree = ""; }; - 7D1011A9244B271E11F082989E181A6D /* YYFrameImage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YYFrameImage.m; path = YYImage/YYFrameImage.m; sourceTree = ""; }; - 7EBD52032DCAFDAEC06FD991BB8695A8 /* View+MASAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "View+MASAdditions.m"; path = "Masonry/View+MASAdditions.m"; sourceTree = ""; }; - 7FEA48B785F73A0492D9D729976FD86B /* GPUImageWhiteBalanceFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageWhiteBalanceFilter.m; path = framework/Source/GPUImageWhiteBalanceFilter.m; sourceTree = ""; }; - 80DCA9ABD24683C3D8FAE083D96F58E5 /* GPUImageToonFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageToonFilter.m; path = framework/Source/GPUImageToonFilter.m; sourceTree = ""; }; - 80F0F94732C9BFC491C85042FF7D14A5 /* GPUImageOverlayBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageOverlayBlendFilter.h; path = framework/Source/GPUImageOverlayBlendFilter.h; sourceTree = ""; }; - 82945F15766B165DCCA8DA4BC2C4BD87 /* View+MASShorthandAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "View+MASShorthandAdditions.h"; path = "Masonry/View+MASShorthandAdditions.h"; sourceTree = ""; }; - 82C6F83D1D031E0F313B5E11137E072B /* GPUImageKuwaharaFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageKuwaharaFilter.h; path = framework/Source/GPUImageKuwaharaFilter.h; sourceTree = ""; }; - 82F4ACE9BAABD111264FD788EF74546D /* YYWebImage-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "YYWebImage-prefix.pch"; sourceTree = ""; }; - 83180B57DF37B3555ED1B68472C45C2C /* GPUImageEmbossFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageEmbossFilter.h; path = framework/Source/GPUImageEmbossFilter.h; sourceTree = ""; }; - 838B4FE7CBA73D00A0885739EF9AA694 /* GPUImageFramebuffer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageFramebuffer.m; path = framework/Source/GPUImageFramebuffer.m; sourceTree = ""; }; - 83FF0DCFBB0CF862F4E2370485036696 /* GPUImageVoronoiConsumerFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageVoronoiConsumerFilter.h; path = framework/Source/GPUImageVoronoiConsumerFilter.h; sourceTree = ""; }; - 844471BB500349B7E35E4D0A96389D2F /* GPUImageSphereRefractionFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageSphereRefractionFilter.h; path = framework/Source/GPUImageSphereRefractionFilter.h; sourceTree = ""; }; - 8472059D35BC092DEF41EC2604D795FB /* GPUImageHistogramFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageHistogramFilter.h; path = framework/Source/GPUImageHistogramFilter.h; sourceTree = ""; }; - 84948E8F3C90A486BDED1DDC42DD9B6D /* GPUImageTwoPassFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageTwoPassFilter.m; path = framework/Source/GPUImageTwoPassFilter.m; sourceTree = ""; }; - 856409B61D04B0A9D91A67DFFB1C680D /* GPUImageDilationFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageDilationFilter.h; path = framework/Source/GPUImageDilationFilter.h; sourceTree = ""; }; - 85B8CD154BD93A91C3B231B46DFA42BC /* lookup_soft_elegance_2.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = lookup_soft_elegance_2.png; path = framework/Resources/lookup_soft_elegance_2.png; sourceTree = ""; }; - 864D6DEE6397881CD3F0FCBC2443BB60 /* GPUImageiOSBlurFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageiOSBlurFilter.m; path = framework/Source/GPUImageiOSBlurFilter.m; sourceTree = ""; }; - 86B55374AABE32E7869673D68D81265B /* YYSpriteSheetImage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YYSpriteSheetImage.m; path = YYImage/YYSpriteSheetImage.m; sourceTree = ""; }; - 870991E39050AAA48FC751AB989A0CEE /* GPUImagePinchDistortionFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImagePinchDistortionFilter.m; path = framework/Source/GPUImagePinchDistortionFilter.m; sourceTree = ""; }; - 8736944B2594030670245A252F39B7FA /* GPUImageThreeInputFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageThreeInputFilter.m; path = framework/Source/GPUImageThreeInputFilter.m; sourceTree = ""; }; - 87611103457106E50CE6DF1459C428CF /* GPUImageRGBDilationFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageRGBDilationFilter.m; path = framework/Source/GPUImageRGBDilationFilter.m; sourceTree = ""; }; - 87B89822E64C2B0270C48FB5310A947F /* YYAnimatedImageView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YYAnimatedImageView.h; path = YYImage/YYAnimatedImageView.h; sourceTree = ""; }; - 8897A494B1993654654BD96F0352C036 /* GPUImageCrosshatchFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageCrosshatchFilter.h; path = framework/Source/GPUImageCrosshatchFilter.h; sourceTree = ""; }; - 894067B7B8B143B196F909226A542245 /* GPUImageWeakPixelInclusionFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageWeakPixelInclusionFilter.h; path = framework/Source/GPUImageWeakPixelInclusionFilter.h; sourceTree = ""; }; - 89911F978F34916A355191709CBB5802 /* GPUImageBrightnessFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageBrightnessFilter.h; path = framework/Source/GPUImageBrightnessFilter.h; sourceTree = ""; }; - 8A10226B00432CC14F57C84CDA29A0B6 /* GPUImageZoomBlurFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageZoomBlurFilter.h; path = framework/Source/GPUImageZoomBlurFilter.h; sourceTree = ""; }; - 8A630DEACFD6C33B16EABFCBA7B10B6B /* GPUImageStillCamera.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageStillCamera.m; path = framework/Source/GPUImageStillCamera.m; sourceTree = ""; }; - 8AC2A96E79A66C63B15134B252A9BD15 /* lookup.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = lookup.png; path = framework/Resources/lookup.png; sourceTree = ""; }; - 8B8FAB0D627B17EDE1366984278705D9 /* libMBProgressHUD.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = libMBProgressHUD.a; path = libMBProgressHUD.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 8BA72D587A6A6B053532804FF36E8E46 /* GPUImageLuminosityBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageLuminosityBlendFilter.m; path = framework/Source/GPUImageLuminosityBlendFilter.m; sourceTree = ""; }; - 8BBCCF9A4A7C3B7E1D6638E2D15B2B83 /* GPUImageRGBClosingFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageRGBClosingFilter.m; path = framework/Source/GPUImageRGBClosingFilter.m; sourceTree = ""; }; - 8C3AE50C738678F7E82112FDB4A8E70C /* MASLayoutConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASLayoutConstraint.m; path = Masonry/MASLayoutConstraint.m; sourceTree = ""; }; - 8C7EBDF59E4597071BF464EFAC596030 /* MBProgressHUD-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "MBProgressHUD-dummy.m"; sourceTree = ""; }; - 8CAC7D39500D3FC8B5E4380E69FFBCCA /* GPUImageHazeFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageHazeFilter.m; path = framework/Source/GPUImageHazeFilter.m; sourceTree = ""; }; - 8CEEEBC4B26A07F17E3509809AE7C514 /* GPUImageHistogramGenerator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageHistogramGenerator.h; path = framework/Source/GPUImageHistogramGenerator.h; sourceTree = ""; }; - 8D6496F72C325C292BB59F2D94A654A2 /* NSLayoutConstraint+MASDebugAdditions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSLayoutConstraint+MASDebugAdditions.m"; path = "Masonry/NSLayoutConstraint+MASDebugAdditions.m"; sourceTree = ""; }; - 8DEFD1186E4AE1006B42EF52538073A3 /* YYWebImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YYWebImage.h; path = YYWebImage/YYWebImage.h; sourceTree = ""; }; - 8F06970C1605988B31A04FC0D429E908 /* GPUImageLuminosity.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageLuminosity.h; path = framework/Source/GPUImageLuminosity.h; sourceTree = ""; }; - 8F3286B04ABC750B2DA6269CDAB9A3B0 /* YYWebImageManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YYWebImageManager.m; path = YYWebImage/YYWebImageManager.m; sourceTree = ""; }; - 8F3589B845F9E0998764CC082B4636FE /* YYImage-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "YYImage-prefix.pch"; sourceTree = ""; }; - 8F4D069CFC80E40C0955894061DC5082 /* GPUImageNobleCornerDetectionFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageNobleCornerDetectionFilter.m; path = framework/Source/GPUImageNobleCornerDetectionFilter.m; sourceTree = ""; }; - 8F83E8DB73761A3F59617E28A1A9351E /* GPUImageColorDodgeBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageColorDodgeBlendFilter.h; path = framework/Source/GPUImageColorDodgeBlendFilter.h; sourceTree = ""; }; - 917747700EB9C26B29A0199F357B3B12 /* GPUImageColorBurnBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageColorBurnBlendFilter.m; path = framework/Source/GPUImageColorBurnBlendFilter.m; sourceTree = ""; }; - 926120A3C10BB72D3539005BC5D12636 /* YYDiskCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YYDiskCache.h; path = YYCache/YYDiskCache.h; sourceTree = ""; }; - 94E26D38916B6B7C099A974F7D4801BB /* GPUImageHardLightBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageHardLightBlendFilter.h; path = framework/Source/GPUImageHardLightBlendFilter.h; sourceTree = ""; }; - 94F2208CD8400EF9A4FE9B63DAC5E6E0 /* GPUImageLuminanceRangeFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageLuminanceRangeFilter.m; path = framework/Source/GPUImageLuminanceRangeFilter.m; sourceTree = ""; }; - 9680F05DBD64586E9AB59F33EA7E289F /* MKAnnotationView+YYWebImage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "MKAnnotationView+YYWebImage.m"; path = "YYWebImage/Categories/MKAnnotationView+YYWebImage.m"; sourceTree = ""; }; - 96B10DB742FBE734F2EE564DC1808399 /* GPUImageRGBErosionFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageRGBErosionFilter.h; path = framework/Source/GPUImageRGBErosionFilter.h; sourceTree = ""; }; - 970BB19E23C4B9B7AA3309F224CC0E71 /* YYClassInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YYClassInfo.h; path = YYModel/YYClassInfo.h; sourceTree = ""; }; - 97BB1E9D14B5C9A8E04954127CF899DD /* GPUImageRGBFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageRGBFilter.m; path = framework/Source/GPUImageRGBFilter.m; sourceTree = ""; }; - 985698BFE05D67C00294DF094B379513 /* GPUImageExposureFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageExposureFilter.h; path = framework/Source/GPUImageExposureFilter.h; sourceTree = ""; }; - 99007670CCD9C91A8F619B9CEA906413 /* GPUImageThresholdedNonMaximumSuppressionFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageThresholdedNonMaximumSuppressionFilter.h; path = framework/Source/GPUImageThresholdedNonMaximumSuppressionFilter.h; sourceTree = ""; }; - 9ADFE335A749F6242A5501FC31B4EDB2 /* GPUImageMosaicFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageMosaicFilter.m; path = framework/Source/GPUImageMosaicFilter.m; sourceTree = ""; }; - 9B4EE9ADF2AF51D5C395568406645F72 /* MASViewAttribute.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASViewAttribute.m; path = Masonry/MASViewAttribute.m; sourceTree = ""; }; - 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 9D99E942362A4061252F3303E92A955A /* GPUImagePixellateFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImagePixellateFilter.m; path = framework/Source/GPUImagePixellateFilter.m; sourceTree = ""; }; - 9DF64883F152558549C53B4951455B9B /* GPUImageDifferenceBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageDifferenceBlendFilter.m; path = framework/Source/GPUImageDifferenceBlendFilter.m; sourceTree = ""; }; - 9E5657C2668E3B4C728034FA1EA9A0A4 /* GPUImageLookupFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageLookupFilter.m; path = framework/Source/GPUImageLookupFilter.m; sourceTree = ""; }; - 9F1724BCB76C8A64AA536BCED3D812D4 /* GPUImageAverageLuminanceThresholdFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageAverageLuminanceThresholdFilter.h; path = framework/Source/GPUImageAverageLuminanceThresholdFilter.h; sourceTree = ""; }; - 9F81E2DA24707028F902CA5D2165F3AF /* GPUImageSketchFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageSketchFilter.m; path = framework/Source/GPUImageSketchFilter.m; sourceTree = ""; }; - 9FE18CDF175FE55AE74C18EF88123854 /* GPUImageVignetteFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageVignetteFilter.m; path = framework/Source/GPUImageVignetteFilter.m; sourceTree = ""; }; - A02D900146C224595943A9226D2DCAD8 /* GPUImageUnsharpMaskFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageUnsharpMaskFilter.h; path = framework/Source/GPUImageUnsharpMaskFilter.h; sourceTree = ""; }; - A040C6DAEB250520DDAB80B89F5BDE6B /* GPUImageColorMatrixFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageColorMatrixFilter.h; path = framework/Source/GPUImageColorMatrixFilter.h; sourceTree = ""; }; - A0A98FEBD19728184776073D5B656C40 /* GPUImageOpacityFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageOpacityFilter.m; path = framework/Source/GPUImageOpacityFilter.m; sourceTree = ""; }; - A0B5C9037C5004A4E5533B5FE12C1BE7 /* GPUImageCannyEdgeDetectionFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageCannyEdgeDetectionFilter.h; path = framework/Source/GPUImageCannyEdgeDetectionFilter.h; sourceTree = ""; }; - A0D905911F4E966E46571AE6336725F8 /* GPUImageSoftLightBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageSoftLightBlendFilter.h; path = framework/Source/GPUImageSoftLightBlendFilter.h; sourceTree = ""; }; - A17B47159361544A9A5041BCADFB2DA3 /* GPUImageMovieWriter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageMovieWriter.m; path = framework/Source/iOS/GPUImageMovieWriter.m; sourceTree = ""; }; - A1BDF8E1519711BE1634F7B98C1BE5A4 /* GPUImageRawDataOutput.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageRawDataOutput.m; path = framework/Source/GPUImageRawDataOutput.m; sourceTree = ""; }; - A21D094A16257D428FAE0B259CD960F5 /* GPUImageMonochromeFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageMonochromeFilter.m; path = framework/Source/GPUImageMonochromeFilter.m; sourceTree = ""; }; - A22790AD2F8E9488E3E272090ACDE88B /* GPUImageLuminanceRangeFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageLuminanceRangeFilter.h; path = framework/Source/GPUImageLuminanceRangeFilter.h; sourceTree = ""; }; - A3CD8B04FB70BC53E721DA44020D04B1 /* GPUImageLinearBurnBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageLinearBurnBlendFilter.m; path = framework/Source/GPUImageLinearBurnBlendFilter.m; sourceTree = ""; }; - A7E3C6A77B24BBCAF360A95E890B7F76 /* GPUImageTwoPassFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageTwoPassFilter.h; path = framework/Source/GPUImageTwoPassFilter.h; sourceTree = ""; }; - A827A26F6AFD11185014B81B1EDDC257 /* GPUImageLuminosityBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageLuminosityBlendFilter.h; path = framework/Source/GPUImageLuminosityBlendFilter.h; sourceTree = ""; }; - AB5B9F20F2CC4E7B1E64873C8F4C7DEB /* GPUImageSoftEleganceFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageSoftEleganceFilter.m; path = framework/Source/GPUImageSoftEleganceFilter.m; sourceTree = ""; }; - AB79E1A4A66A6C04AB9D9EBE73E0A218 /* GPUImagePixellatePositionFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImagePixellatePositionFilter.m; path = framework/Source/GPUImagePixellatePositionFilter.m; sourceTree = ""; }; - AB9AABEFA3783A1EFB3AF263028EA22E /* GPUImageMedianFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageMedianFilter.h; path = framework/Source/GPUImageMedianFilter.h; sourceTree = ""; }; - ABEA5E282030B2AACB13107445796E9B /* GPUImageUIElement.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageUIElement.h; path = framework/Source/GPUImageUIElement.h; sourceTree = ""; }; - AC24421A335214257CD3748289F31E7D /* YYImage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YYImage.m; path = YYImage/YYImage.m; sourceTree = ""; }; - AC973EBC40064F309FCCDDEC38ED1151 /* lookup_amatorka.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = lookup_amatorka.png; path = framework/Resources/lookup_amatorka.png; sourceTree = ""; }; - AC97F32440360E91D0907B1696EFA925 /* GPUImageKuwaharaFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageKuwaharaFilter.m; path = framework/Source/GPUImageKuwaharaFilter.m; sourceTree = ""; }; - AF05AFD8796F688202D7D60A24EE4B36 /* YYCache-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "YYCache-prefix.pch"; sourceTree = ""; }; - AF4FAC2BFB19ABFAB2B98973CF3F2F19 /* GPUImageGaussianSelectiveBlurFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageGaussianSelectiveBlurFilter.h; path = framework/Source/GPUImageGaussianSelectiveBlurFilter.h; sourceTree = ""; }; - AF50E9AAD19F008B707D7D8F7EACA2D3 /* MASCompositeConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASCompositeConstraint.m; path = Masonry/MASCompositeConstraint.m; sourceTree = ""; }; - AFB401E05E9C8DEA8B23609216EB64E5 /* YYMemoryCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YYMemoryCache.h; path = YYCache/YYMemoryCache.h; sourceTree = ""; }; - B015E5C22E17335E3A77DFA9908BB606 /* GPUImageLanczosResamplingFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageLanczosResamplingFilter.h; path = framework/Source/GPUImageLanczosResamplingFilter.h; sourceTree = ""; }; - B11AD2552FDB15FF1C538A2621C8454E /* GPUImageChromaKeyBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageChromaKeyBlendFilter.h; path = framework/Source/GPUImageChromaKeyBlendFilter.h; sourceTree = ""; }; - B1CF0307FA26395C0EBDD879BF40EE7F /* GPUImageSwirlFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageSwirlFilter.m; path = framework/Source/GPUImageSwirlFilter.m; sourceTree = ""; }; - B31F1147C4556865B64D707FEE8CCC97 /* MASConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASConstraint.m; path = Masonry/MASConstraint.m; sourceTree = ""; }; - B4080351977D02914F701E5AF2820E28 /* UIImageView+YYWebImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImageView+YYWebImage.h"; path = "YYWebImage/Categories/UIImageView+YYWebImage.h"; sourceTree = ""; }; - B43D8D3315443CDCAF2566D64DDEE04B /* GPUImageSolidColorGenerator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageSolidColorGenerator.h; path = framework/Source/GPUImageSolidColorGenerator.h; sourceTree = ""; }; - B49CFF15CC2A8F9BE7A7F6E9858CF4A9 /* GPUImageLaplacianFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageLaplacianFilter.h; path = framework/Source/GPUImageLaplacianFilter.h; sourceTree = ""; }; - B4F3FFA58FE342F21294920E38929E3F /* GPUImagePicture.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImagePicture.m; path = framework/Source/iOS/GPUImagePicture.m; sourceTree = ""; }; - B5319E1423AA1E35ADBA7A3B04DF598E /* MBProgressHUD.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = MBProgressHUD.m; sourceTree = ""; }; - B5497DA96594CCECE8E15AC43C9A2C6B /* GPUImageCrosshatchFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageCrosshatchFilter.m; path = framework/Source/GPUImageCrosshatchFilter.m; sourceTree = ""; }; - B600C9B478F0D9AD34362F46737F82C5 /* GPUImageBulgeDistortionFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageBulgeDistortionFilter.m; path = framework/Source/GPUImageBulgeDistortionFilter.m; sourceTree = ""; }; - B63E6AF28713967F264112F9450B3F8C /* GPUImageColorInvertFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageColorInvertFilter.m; path = framework/Source/GPUImageColorInvertFilter.m; sourceTree = ""; }; - B72EC130B00BB80835F63C15885EEB06 /* NSObject+YYModel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSObject+YYModel.m"; path = "YYModel/NSObject+YYModel.m"; sourceTree = ""; }; - B748550FB21BB7C03E6327054546AAD9 /* GPUImageCGAColorspaceFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageCGAColorspaceFilter.m; path = framework/Source/GPUImageCGAColorspaceFilter.m; sourceTree = ""; }; - B76EEE6CDA11AED2C0DF42954264E2E4 /* GPUImageSaturationBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageSaturationBlendFilter.m; path = framework/Source/GPUImageSaturationBlendFilter.m; sourceTree = ""; }; - B8043D2AA30371284EF62F7AE00669A6 /* GPUImageSphereRefractionFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageSphereRefractionFilter.m; path = framework/Source/GPUImageSphereRefractionFilter.m; sourceTree = ""; }; - B8113E2BE805826C2206219087AF2FEB /* GPUImagePicture.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImagePicture.h; path = framework/Source/iOS/GPUImagePicture.h; sourceTree = ""; }; - B81F4796AC0D72D4F1B2047D5A0E8AC0 /* GPUImageSmoothToonFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageSmoothToonFilter.m; path = framework/Source/GPUImageSmoothToonFilter.m; sourceTree = ""; }; - B841981319C7EF7EE2877086FCA683E5 /* GPUImageSubtractBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageSubtractBlendFilter.m; path = framework/Source/GPUImageSubtractBlendFilter.m; sourceTree = ""; }; - B938A512490439A79E04F0C9697CD365 /* GLProgram.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GLProgram.m; path = framework/Source/GLProgram.m; sourceTree = ""; }; - B93FEAD1B3DB233D4B21EB7567E5E3A0 /* GPUImageHistogramEqualizationFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageHistogramEqualizationFilter.m; path = framework/Source/GPUImageHistogramEqualizationFilter.m; sourceTree = ""; }; - B9A029945B47FB73CDE3CC37104F813F /* CALayer+YYWebImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "CALayer+YYWebImage.h"; path = "YYWebImage/Categories/CALayer+YYWebImage.h"; sourceTree = ""; }; - BA29045FFD62C4F2F08018346E53B773 /* GPUImageCropFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageCropFilter.m; path = framework/Source/GPUImageCropFilter.m; sourceTree = ""; }; - BA371A875E27E7EE7D0FCD1007D94CF2 /* GPUImageLowPassFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageLowPassFilter.h; path = framework/Source/GPUImageLowPassFilter.h; sourceTree = ""; }; - BAA4F2B29058FE252D949D0C32390318 /* YYAnimatedImageView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YYAnimatedImageView.m; path = YYImage/YYAnimatedImageView.m; sourceTree = ""; }; - BBB88E5B5C49D8640CAD758ACB9A6965 /* GPUImageSharpenFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageSharpenFilter.h; path = framework/Source/GPUImageSharpenFilter.h; sourceTree = ""; }; - BBE357EF73F92D80EB2A32F6C9ADC813 /* GPUImageThresholdSketchFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageThresholdSketchFilter.h; path = framework/Source/GPUImageThresholdSketchFilter.h; sourceTree = ""; }; - BD8A6D912B9DADCD91A8CECBE8D365BF /* YYFrameImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YYFrameImage.h; path = YYImage/YYFrameImage.h; sourceTree = ""; }; - BD9B919D49630BD01C44E78237FBD863 /* GPUImageClosingFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageClosingFilter.m; path = framework/Source/GPUImageClosingFilter.m; sourceTree = ""; }; - BDD3B32644BC93C7355A1C520C495A48 /* GPUImageNonMaximumSuppressionFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageNonMaximumSuppressionFilter.h; path = framework/Source/GPUImageNonMaximumSuppressionFilter.h; sourceTree = ""; }; - BE0B9D8C884083422794279D51378D71 /* GPUImage3x3ConvolutionFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImage3x3ConvolutionFilter.h; path = framework/Source/GPUImage3x3ConvolutionFilter.h; sourceTree = ""; }; - BE1BD7513325F0024AB5F0B2AA5B5308 /* YYModel.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = YYModel.debug.xcconfig; sourceTree = ""; }; - BE4970CD6356FFFAA48E1613FE580EB0 /* GPUImageDarkenBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageDarkenBlendFilter.h; path = framework/Source/GPUImageDarkenBlendFilter.h; sourceTree = ""; }; - BE81F8031495E743E805E3F1ABB005EE /* NSArray+MASAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+MASAdditions.h"; path = "Masonry/NSArray+MASAdditions.h"; sourceTree = ""; }; - BEFFA1F44D79B03904E27FC68BA02324 /* GPUImageSwirlFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageSwirlFilter.h; path = framework/Source/GPUImageSwirlFilter.h; sourceTree = ""; }; - BF320EFBDD4F9B7040C07E0E3056F74E /* lookup_soft_elegance_1.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = lookup_soft_elegance_1.png; path = framework/Resources/lookup_soft_elegance_1.png; sourceTree = ""; }; - C05B47CD66C71D9CAAF1627186D1C6DE /* CALayer+YYWebImage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "CALayer+YYWebImage.m"; path = "YYWebImage/Categories/CALayer+YYWebImage.m"; sourceTree = ""; }; - C080FC8084166668F65F78ED0AA4A69B /* GPUImageHueBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageHueBlendFilter.h; path = framework/Source/GPUImageHueBlendFilter.h; sourceTree = ""; }; - C0C8CE6B752A1D6DC908E8EBC379636C /* GPUImageTiltShiftFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageTiltShiftFilter.m; path = framework/Source/GPUImageTiltShiftFilter.m; sourceTree = ""; }; - C1703B1CC3A8EF46F7E0BC97EF312B15 /* GPUImagePicture+TextureSubimage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "GPUImagePicture+TextureSubimage.m"; path = "framework/Source/iOS/GPUImagePicture+TextureSubimage.m"; sourceTree = ""; }; - C3415B253778A17AB9D9E9539C59982E /* GPUImageMonochromeFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageMonochromeFilter.h; path = framework/Source/GPUImageMonochromeFilter.h; sourceTree = ""; }; - C4193CD804FDADD82E3B8FE1883F6D29 /* View+MASAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "View+MASAdditions.h"; path = "Masonry/View+MASAdditions.h"; sourceTree = ""; }; - C48D8B50088748FC4BC5FC2E0C491663 /* GPUImageGaussianBlurPositionFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageGaussianBlurPositionFilter.h; path = framework/Source/GPUImageGaussianBlurPositionFilter.h; sourceTree = ""; }; - C6C160D9019636230267BE3289CF1EF8 /* GPUImageBilateralFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageBilateralFilter.m; path = framework/Source/GPUImageBilateralFilter.m; sourceTree = ""; }; - C7E61395FE8E961D58658EFC5FE914A3 /* GPUImageHueFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageHueFilter.m; path = framework/Source/GPUImageHueFilter.m; sourceTree = ""; }; - C8E3D2D6BFE3A6A5011A9A78D5041D6B /* MASConstraintMaker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASConstraintMaker.m; path = Masonry/MASConstraintMaker.m; sourceTree = ""; }; - C8EFB486F7011880B250BD588AF6B03A /* GPUImageXYDerivativeFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageXYDerivativeFilter.h; path = framework/Source/GPUImageXYDerivativeFilter.h; sourceTree = ""; }; - CA5BC3210A0DC9C52CF983E3FBA33D3D /* GPUImagePolkaDotFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImagePolkaDotFilter.h; path = framework/Source/GPUImagePolkaDotFilter.h; sourceTree = ""; }; - CA6014EF6AE8930707D68E71ECA55D13 /* Pods-DarkMode.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-DarkMode.release.xcconfig"; sourceTree = ""; }; - CAD1753F08C939B747A9310D6E2C7CCD /* Masonry.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Masonry.h; path = Masonry/Masonry.h; sourceTree = ""; }; - CB5A0BE4A5245E286AF7E6814CDD1436 /* YYImageCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YYImageCache.m; path = YYWebImage/YYImageCache.m; sourceTree = ""; }; - CC511945A3B6F15907655303FBD595CC /* YYWebImage.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = YYWebImage.release.xcconfig; sourceTree = ""; }; - CD17316111B32EDFB414E2DB7107670D /* GPUImageRGBOpeningFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageRGBOpeningFilter.m; path = framework/Source/GPUImageRGBOpeningFilter.m; sourceTree = ""; }; - CE8390129A638BE0F4AE19C96CACE467 /* GPUImageToonFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageToonFilter.h; path = framework/Source/GPUImageToonFilter.h; sourceTree = ""; }; - CE8B3FE478847A7AAD2B21BC40809B56 /* MASUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASUtilities.h; path = Masonry/MASUtilities.h; sourceTree = ""; }; - CF2F73298D0AAD1A41B6CB86926D9317 /* GPUImageHoughTransformLineDetector.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageHoughTransformLineDetector.m; path = framework/Source/GPUImageHoughTransformLineDetector.m; sourceTree = ""; }; - CF78B4B80A067EF3C1E69807978B0212 /* GPUImageMultiplyBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageMultiplyBlendFilter.m; path = framework/Source/GPUImageMultiplyBlendFilter.m; sourceTree = ""; }; - CFC1905D68B43955A7ECC39E228564DC /* GPUImageLuminosity.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageLuminosity.m; path = framework/Source/GPUImageLuminosity.m; sourceTree = ""; }; - D17E8A9196C94BC7F7B14D0D08A31A90 /* GPUImageFramebufferCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageFramebufferCache.h; path = framework/Source/GPUImageFramebufferCache.h; sourceTree = ""; }; - D20E7200664BDC1CA23F83B69DB2AF00 /* GPUImageOpacityFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageOpacityFilter.h; path = framework/Source/GPUImageOpacityFilter.h; sourceTree = ""; }; - D24C3AB3AE7CD24FB83746C901F281BA /* GPUImageMosaicFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageMosaicFilter.h; path = framework/Source/GPUImageMosaicFilter.h; sourceTree = ""; }; - D2C5AB16BD22FA6146D9733E98392177 /* GPUImagePixellateFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImagePixellateFilter.h; path = framework/Source/GPUImagePixellateFilter.h; sourceTree = ""; }; - D3B1D10EA9F731D0F5F681A4CAEDE5D6 /* GPUImageRawDataInput.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageRawDataInput.m; path = framework/Source/GPUImageRawDataInput.m; sourceTree = ""; }; - D41C9CF88307CC423AE666B56182E5B9 /* GPUImage3x3TextureSamplingFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImage3x3TextureSamplingFilter.m; path = framework/Source/GPUImage3x3TextureSamplingFilter.m; sourceTree = ""; }; - D4336A5672C30CDB1EBF2ABE41670A08 /* NSObject+YYModel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSObject+YYModel.h"; path = "YYModel/NSObject+YYModel.h"; sourceTree = ""; }; - D4A60FDE318E3C0F278D020D96060453 /* GPUImageAverageColor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageAverageColor.h; path = framework/Source/GPUImageAverageColor.h; sourceTree = ""; }; - D4C994A6E8F57B6828552CA504C66D58 /* GPUImageScreenBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageScreenBlendFilter.m; path = framework/Source/GPUImageScreenBlendFilter.m; sourceTree = ""; }; - D54971E35D67E4E2B0A20F8CD8BDB2D4 /* GPUImagePoissonBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImagePoissonBlendFilter.m; path = framework/Source/GPUImagePoissonBlendFilter.m; sourceTree = ""; }; - D5AB4ADA23B1748AB0ED4BB1DB527C69 /* GPUImageLookupFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageLookupFilter.h; path = framework/Source/GPUImageLookupFilter.h; sourceTree = ""; }; - D65307FDE17DBA7A0B3A73E64332F870 /* YYClassInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YYClassInfo.m; path = YYModel/YYClassInfo.m; sourceTree = ""; }; - D66E3D513B5531F7F4B074A1AEC523B8 /* GPUImageContrastFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageContrastFilter.h; path = framework/Source/GPUImageContrastFilter.h; sourceTree = ""; }; - D6DEC4D0701355737F042ABE9389A98E /* YYMemoryCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YYMemoryCache.m; path = YYCache/YYMemoryCache.m; sourceTree = ""; }; - D784A6CD68E1A5D8D6580987562CE66F /* GPUImageOverlayBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageOverlayBlendFilter.m; path = framework/Source/GPUImageOverlayBlendFilter.m; sourceTree = ""; }; - D78C9DBE522A045B8E50F88417BA309E /* Pods-DarkMode-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-DarkMode-acknowledgements.markdown"; sourceTree = ""; }; - D91BF331AAA5E77D9BEDA9C6D40DD41E /* MBProgressHUD.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MBProgressHUD.release.xcconfig; sourceTree = ""; }; - D9580A4EE8AFE8DD3E68A776F88E557B /* YYSpriteSheetImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YYSpriteSheetImage.h; path = YYImage/YYSpriteSheetImage.h; sourceTree = ""; }; - DA29E62F007F394173C5A6E96F4EA3A1 /* GPUImageJFAVoronoiFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageJFAVoronoiFilter.h; path = framework/Source/GPUImageJFAVoronoiFilter.h; sourceTree = ""; }; - DA4B2BBB528CEAFC918860127115B034 /* GPUImageExclusionBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageExclusionBlendFilter.m; path = framework/Source/GPUImageExclusionBlendFilter.m; sourceTree = ""; }; - DC785C323CE09EC09CDC2F8014081C38 /* GPUImageColorBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageColorBlendFilter.m; path = framework/Source/GPUImageColorBlendFilter.m; sourceTree = ""; }; - DCDB8D6607C77835C1EC75EB9F36E5C5 /* GPUImageFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageFilter.h; path = framework/Source/GPUImageFilter.h; sourceTree = ""; }; - DD2430725CE2EF7139ADE4BBC1C7CBA8 /* UIImageView+YYWebImage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+YYWebImage.m"; path = "YYWebImage/Categories/UIImageView+YYWebImage.m"; sourceTree = ""; }; - DD88158BB140DD22AAFBE5A81587E42D /* GPUImageLocalBinaryPatternFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageLocalBinaryPatternFilter.m; path = framework/Source/GPUImageLocalBinaryPatternFilter.m; sourceTree = ""; }; - DDB88636BCAA89B17531BEAC2B7677B4 /* GPUImageVideoCamera.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageVideoCamera.m; path = framework/Source/GPUImageVideoCamera.m; sourceTree = ""; }; - DEC5E896CBBBB4368B3D73E3B6DF98AF /* GPUImageFramebuffer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageFramebuffer.h; path = framework/Source/GPUImageFramebuffer.h; sourceTree = ""; }; - DF18464EBC41D32FBD924D4FBD3DCF7D /* GPUImageDilationFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageDilationFilter.m; path = framework/Source/GPUImageDilationFilter.m; sourceTree = ""; }; - DFE90665F8A100159773904C5A2F8967 /* GPUImageLightenBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageLightenBlendFilter.h; path = framework/Source/GPUImageLightenBlendFilter.h; sourceTree = ""; }; - E11AAC1475379E882BBED87C93CA898B /* NSArray+MASShorthandAdditions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+MASShorthandAdditions.h"; path = "Masonry/NSArray+MASShorthandAdditions.h"; sourceTree = ""; }; - E16FF3BBD2E461C6B31F4D28293DEC1F /* GPUImageSobelEdgeDetectionFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageSobelEdgeDetectionFilter.h; path = framework/Source/GPUImageSobelEdgeDetectionFilter.h; sourceTree = ""; }; - E170213BF8AB60A888762910A4745B2B /* GPUImageGaussianBlurFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageGaussianBlurFilter.h; path = framework/Source/GPUImageGaussianBlurFilter.h; sourceTree = ""; }; - E17C159C87DA98A853415C410757984D /* YYKVStorage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YYKVStorage.m; path = YYCache/YYKVStorage.m; sourceTree = ""; }; - E26335B2F22D282C8B7582834BD0A07E /* GPUImageLuminanceThresholdFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageLuminanceThresholdFilter.h; path = framework/Source/GPUImageLuminanceThresholdFilter.h; sourceTree = ""; }; - E388169E7433BC6A1E766BB6E2C53605 /* MBProgressHUD.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MBProgressHUD.debug.xcconfig; sourceTree = ""; }; - E460D5B0416D36F66EE8EC89E5D2FA0A /* libYYModel.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = libYYModel.a; path = libYYModel.a; sourceTree = BUILT_PRODUCTS_DIR; }; - E48C3FA68C009689F44837B466401AA1 /* MASViewConstraint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MASViewConstraint.m; path = Masonry/MASViewConstraint.m; sourceTree = ""; }; - E578EF7302261D7D50382800254764B6 /* UIImage+YYWebImage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+YYWebImage.m"; path = "YYWebImage/Categories/UIImage+YYWebImage.m"; sourceTree = ""; }; - E5AE2B148F45F4E8B8FB0225084DEE18 /* GPUImageNobleCornerDetectionFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageNobleCornerDetectionFilter.h; path = framework/Source/GPUImageNobleCornerDetectionFilter.h; sourceTree = ""; }; - E5C1184106339F84D7D501170074B1B4 /* Masonry-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Masonry-dummy.m"; sourceTree = ""; }; - E63C05F85CF505C1F4F6C1F2A5264989 /* GPUImageHazeFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageHazeFilter.h; path = framework/Source/GPUImageHazeFilter.h; sourceTree = ""; }; - E75C8905888A317693F48FC06029AC84 /* GPUImagePerlinNoiseFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImagePerlinNoiseFilter.h; path = framework/Source/GPUImagePerlinNoiseFilter.h; sourceTree = ""; }; - E7ED5325591277156B4BB5CC580E9723 /* GPUImageVoronoiConsumerFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageVoronoiConsumerFilter.m; path = framework/Source/GPUImageVoronoiConsumerFilter.m; sourceTree = ""; }; - E82866E758AEDE0697B2D6542D52887E /* GPUImageHalftoneFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageHalftoneFilter.h; path = framework/Source/GPUImageHalftoneFilter.h; sourceTree = ""; }; - E8B488F92B9569C2D4E2C544410035E4 /* GPUImageLocalBinaryPatternFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageLocalBinaryPatternFilter.h; path = framework/Source/GPUImageLocalBinaryPatternFilter.h; sourceTree = ""; }; - E9AD39DB2F1E55880567989B269FAC3D /* GPUImageParallelCoordinateLineTransformFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageParallelCoordinateLineTransformFilter.m; path = framework/Source/GPUImageParallelCoordinateLineTransformFilter.m; sourceTree = ""; }; - E9BE79BD70E8A2BBB669B77DE76E87B2 /* GPUImageMovieComposition.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageMovieComposition.m; path = framework/Source/GPUImageMovieComposition.m; sourceTree = ""; }; - E9EBE53088D96916DD20443C82AFBDE7 /* GPUImageWhiteBalanceFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageWhiteBalanceFilter.h; path = framework/Source/GPUImageWhiteBalanceFilter.h; sourceTree = ""; }; - EA2A44D6FF0F9ACEE1DADC1A14F2854D /* GPUImageExposureFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageExposureFilter.m; path = framework/Source/GPUImageExposureFilter.m; sourceTree = ""; }; - EB47C074A601454370424E7CFB464BCF /* GPUImageThresholdSketchFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageThresholdSketchFilter.m; path = framework/Source/GPUImageThresholdSketchFilter.m; sourceTree = ""; }; - ECDB7EC80A81B25D21106D0157935999 /* GPUImage-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GPUImage-prefix.pch"; sourceTree = ""; }; - ECEA2E9EE22767E7510CE7AA87771919 /* GPUImageLightenBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageLightenBlendFilter.m; path = framework/Source/GPUImageLightenBlendFilter.m; sourceTree = ""; }; - ECF46625DB05146F6E98B2E53445EFC8 /* YYImageCoder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YYImageCoder.h; path = YYImage/YYImageCoder.h; sourceTree = ""; }; - ECFEB2E93FCE91E7C240F7A5418610E8 /* GPUImageDirectionalSobelEdgeDetectionFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageDirectionalSobelEdgeDetectionFilter.m; path = framework/Source/GPUImageDirectionalSobelEdgeDetectionFilter.m; sourceTree = ""; }; - ED7087E1AAD6DCA511A73A2D2B30D6B4 /* GPUImageFalseColorFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageFalseColorFilter.h; path = framework/Source/GPUImageFalseColorFilter.h; sourceTree = ""; }; - EE42EB7F34AB1582A3A5744A834BD119 /* GPUImageFramebufferCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageFramebufferCache.m; path = framework/Source/GPUImageFramebufferCache.m; sourceTree = ""; }; - EEF00EBDB95094FD4257D5613DD330E0 /* GPUImageLevelsFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageLevelsFilter.m; path = framework/Source/GPUImageLevelsFilter.m; sourceTree = ""; }; - EFE4CF43587E7DD929FB9764A673B90D /* Pods-DarkMode-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-DarkMode-acknowledgements.plist"; sourceTree = ""; }; - EFFD8A1B500FDBD56314E8131E14CAA5 /* Masonry-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Masonry-prefix.pch"; sourceTree = ""; }; - F02B616DA404DA9F64E1EB8DD4C522B1 /* UIImage+YYWebImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+YYWebImage.h"; path = "YYWebImage/Categories/UIImage+YYWebImage.h"; sourceTree = ""; }; - F11B4258E3FA4A8841B1604E377E7F3D /* GPUImageUIElement.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageUIElement.m; path = framework/Source/GPUImageUIElement.m; sourceTree = ""; }; - F167A2004301C4034FFB0D96A262B99D /* GPUImageSketchFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageSketchFilter.h; path = framework/Source/GPUImageSketchFilter.h; sourceTree = ""; }; - F1A5C4493663A851186ED81654C1C388 /* MASViewConstraint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MASViewConstraint.h; path = Masonry/MASViewConstraint.h; sourceTree = ""; }; - F1C3D508DA7E563DEA7799B00D9E2113 /* GPUImageScreenBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageScreenBlendFilter.h; path = framework/Source/GPUImageScreenBlendFilter.h; sourceTree = ""; }; - F2F67F28D47899C70E83AA9305D4E341 /* GPUImageOpeningFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageOpeningFilter.h; path = framework/Source/GPUImageOpeningFilter.h; sourceTree = ""; }; - F38E818E85AFE98DD31A606DB69D79D5 /* UIButton+YYWebImage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIButton+YYWebImage.h"; path = "YYWebImage/Categories/UIButton+YYWebImage.h"; sourceTree = ""; }; - F3FB9DB94CA9285178C40FCA640755A3 /* GPUImageAverageColor.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageAverageColor.m; path = framework/Source/GPUImageAverageColor.m; sourceTree = ""; }; - F412634986B6427C47BFE33290B76D0C /* GPUImageParallelCoordinateLineTransformFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageParallelCoordinateLineTransformFilter.h; path = framework/Source/GPUImageParallelCoordinateLineTransformFilter.h; sourceTree = ""; }; - F448306B3687298FFAD025EB2DDD73EF /* GPUImageMissEtikateFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageMissEtikateFilter.h; path = framework/Source/GPUImageMissEtikateFilter.h; sourceTree = ""; }; - F478792CD6750762D653D4B974565731 /* GPUImageHistogramEqualizationFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageHistogramEqualizationFilter.h; path = framework/Source/GPUImageHistogramEqualizationFilter.h; sourceTree = ""; }; - F4CCD104A376890D8A12507C5239B8B1 /* GPUImageTwoPassTextureSamplingFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageTwoPassTextureSamplingFilter.h; path = framework/Source/GPUImageTwoPassTextureSamplingFilter.h; sourceTree = ""; }; - F53E198F369DD7B29FDFD1E67D7FEF92 /* GPUImageHueBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageHueBlendFilter.m; path = framework/Source/GPUImageHueBlendFilter.m; sourceTree = ""; }; - F56DBD12B11C3994DFB4255B1D7CC1D8 /* GPUImageColorMatrixFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageColorMatrixFilter.m; path = framework/Source/GPUImageColorMatrixFilter.m; sourceTree = ""; }; - F73A13F286165F4836D8D7D4AAC5C284 /* MASConstraint+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MASConstraint+Private.h"; path = "Masonry/MASConstraint+Private.h"; sourceTree = ""; }; - F776E442B4C1CDFEF257F6134CBE90D0 /* GPUImagePoissonBlendFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImagePoissonBlendFilter.h; path = framework/Source/GPUImagePoissonBlendFilter.h; sourceTree = ""; }; - F8F996C485D25C0141065FF489D1BA53 /* GPUImageRawDataInput.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageRawDataInput.h; path = framework/Source/GPUImageRawDataInput.h; sourceTree = ""; }; - FA45E049B5B5153FBD3529680C70E520 /* GPUImageBrightnessFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageBrightnessFilter.m; path = framework/Source/GPUImageBrightnessFilter.m; sourceTree = ""; }; - FABBE2C4A63D29A135EB2E35769CF66E /* GPUImageHarrisCornerDetectionFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageHarrisCornerDetectionFilter.m; path = framework/Source/GPUImageHarrisCornerDetectionFilter.m; sourceTree = ""; }; - FB24E4E098F3B7DE3B8F4ACF2BC28A28 /* GPUImageBulgeDistortionFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageBulgeDistortionFilter.h; path = framework/Source/GPUImageBulgeDistortionFilter.h; sourceTree = ""; }; - FB638C9B72C7E7F1B16A43E90A8BF20E /* GPUImageToneCurveFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageToneCurveFilter.m; path = framework/Source/GPUImageToneCurveFilter.m; sourceTree = ""; }; - FC1BB8206A536BE18D03949E8E9E8D59 /* YYModel.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = YYModel.release.xcconfig; sourceTree = ""; }; - FC2B794A56EF9D2701B9021759093037 /* GPUImageView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageView.m; path = framework/Source/iOS/GPUImageView.m; sourceTree = ""; }; - FC35CED2A95AFEA26980C9D4ABC06D40 /* GPUImageVignetteFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageVignetteFilter.h; path = framework/Source/GPUImageVignetteFilter.h; sourceTree = ""; }; - FC8FF675218469A34772983792A93F7D /* GPUImageGammaFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageGammaFilter.h; path = framework/Source/GPUImageGammaFilter.h; sourceTree = ""; }; - FD17D6790093A05DE5D3FEA809D11BAA /* GPUImageSourceOverBlendFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageSourceOverBlendFilter.m; path = framework/Source/GPUImageSourceOverBlendFilter.m; sourceTree = ""; }; - FD794A0352171C16DFE53E0AB396C398 /* GPUImageOutput.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GPUImageOutput.m; path = framework/Source/GPUImageOutput.m; sourceTree = ""; }; - FF365ED840058D960082D2B982FA9D49 /* Masonry.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Masonry.debug.xcconfig; sourceTree = ""; }; - FF5ACE2C67EA5C6E02ED4D4FBD28FBA7 /* GPUImageMaskFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GPUImageMaskFilter.h; path = framework/Source/GPUImageMaskFilter.h; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 01095FBE532CF5AA0855A20BDA54BF0B /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 24D3BE854C4E97B4CB4F4B6AEB3DDA1C /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3AA66CA5E57F3C1415A7D61A13C42528 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7E1F0A9AFCFD750D8D8E87867B919530 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 9C058CFEB46CC50AE17D1503E2EA34E9 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - CE2E267127242299A42286A0A8D5DA27 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - D9C15529BA839F56CA954D83368902D8 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - DCBC7FE987FB53FBB71A9E7155D9E871 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 105C7CB0B46A09824CEAF5904D491772 /* Support Files */ = { - isa = PBXGroup; - children = ( - 68619D6BC015E7B9AD2E0EF3660EC99B /* YYWebImage-dummy.m */, - 82F4ACE9BAABD111264FD788EF74546D /* YYWebImage-prefix.pch */, - 5AF9D53BF78794179DA5A171FD200059 /* YYWebImage.debug.xcconfig */, - CC511945A3B6F15907655303FBD595CC /* YYWebImage.release.xcconfig */, - ); - name = "Support Files"; - path = "../Target Support Files/YYWebImage"; - sourceTree = ""; - }; - 1074CCDDB3F516ED42AC73FF531270DC /* Core */ = { - isa = PBXGroup; - children = ( - 87B89822E64C2B0270C48FB5310A947F /* YYAnimatedImageView.h */, - BAA4F2B29058FE252D949D0C32390318 /* YYAnimatedImageView.m */, - BD8A6D912B9DADCD91A8CECBE8D365BF /* YYFrameImage.h */, - 7D1011A9244B271E11F082989E181A6D /* YYFrameImage.m */, - 094F16B0BD56037708312F6A3D1774F3 /* YYImage.h */, - AC24421A335214257CD3748289F31E7D /* YYImage.m */, - ECF46625DB05146F6E98B2E53445EFC8 /* YYImageCoder.h */, - 3E5E02B856C988A000B10E5E5512B56A /* YYImageCoder.m */, - D9580A4EE8AFE8DD3E68A776F88E557B /* YYSpriteSheetImage.h */, - 86B55374AABE32E7869673D68D81265B /* YYSpriteSheetImage.m */, - ); - name = Core; - sourceTree = ""; - }; - 141D0B28506AB42A59DFF063B66A5B9D /* Support Files */ = { - isa = PBXGroup; - children = ( - 2A0042D79436E9C952B47D4763A1C4AE /* GPUImage-dummy.m */, - ECDB7EC80A81B25D21106D0157935999 /* GPUImage-prefix.pch */, - 5278FBF2D16D0E9492F81D50E1B4E389 /* GPUImage.debug.xcconfig */, - 504C0F55ECD0EE366A432BE3CAF79E1F /* GPUImage.release.xcconfig */, - ); - name = "Support Files"; - path = "../Target Support Files/GPUImage"; - sourceTree = ""; - }; - 21FF95F8E6CE5D0E67ACE1DF80ED8D03 /* Support Files */ = { - isa = PBXGroup; - children = ( - 8C7EBDF59E4597071BF464EFAC596030 /* MBProgressHUD-dummy.m */, - 5D7C1EBCB0F669526CC10ADAA17FB565 /* MBProgressHUD-prefix.pch */, - E388169E7433BC6A1E766BB6E2C53605 /* MBProgressHUD.debug.xcconfig */, - D91BF331AAA5E77D9BEDA9C6D40DD41E /* MBProgressHUD.release.xcconfig */, - ); - name = "Support Files"; - path = "../Target Support Files/MBProgressHUD"; - sourceTree = ""; - }; - 378BFCD52F81F2771D1C85755501112C /* Support Files */ = { - isa = PBXGroup; - children = ( - 5F066292FE00E22395481D12B85DCF15 /* YYCache-dummy.m */, - AF05AFD8796F688202D7D60A24EE4B36 /* YYCache-prefix.pch */, - 5DA7010E9B001189E58C1D4FAF928DF7 /* YYCache.debug.xcconfig */, - 4713F7EF42A07902267E6A57EBC07D50 /* YYCache.release.xcconfig */, - ); - name = "Support Files"; - path = "../Target Support Files/YYCache"; - sourceTree = ""; - }; - 37A14F42D10EDBCCC6657E748D3F9A4A /* Support Files */ = { - isa = PBXGroup; - children = ( - E5C1184106339F84D7D501170074B1B4 /* Masonry-dummy.m */, - EFFD8A1B500FDBD56314E8131E14CAA5 /* Masonry-prefix.pch */, - FF365ED840058D960082D2B982FA9D49 /* Masonry.debug.xcconfig */, - 3FFF18D3BD6B92729084311D3FD98998 /* Masonry.release.xcconfig */, - ); - name = "Support Files"; - path = "../Target Support Files/Masonry"; - sourceTree = ""; - }; - 3B5EB31541FAB7B733903648FE8E1F55 /* Pods */ = { - isa = PBXGroup; - children = ( - 6F8E53491B9AD97EEE8695E0C7097D67 /* GPUImage */, - F6B09B74CE642AF4F9AB051723E51BB8 /* Masonry */, - 5F7F22C754196513F8C5696BE1789D15 /* MBProgressHUD */, - FD4CF277559D15A4F3FD03F6768FDB65 /* YYCache */, - 7596DCB5E576E1B05684D75984D7DEE5 /* YYImage */, - 6237A52316AD9B7195EC8FED1CABBCA1 /* YYModel */, - EE1473FB6742C310B59547D29782341E /* YYWebImage */, - ); - name = Pods; - sourceTree = ""; - }; - 4B4EDC9C48CE9C274B5A0CDEB8B1A446 /* Pods-DarkMode */ = { - isa = PBXGroup; - children = ( - D78C9DBE522A045B8E50F88417BA309E /* Pods-DarkMode-acknowledgements.markdown */, - EFE4CF43587E7DD929FB9764A673B90D /* Pods-DarkMode-acknowledgements.plist */, - 2B166651BD2944A773F9537AEC00AF13 /* Pods-DarkMode-dummy.m */, - 375E8723E93DD1BD999307185560F30B /* Pods-DarkMode-resources.sh */, - 16C4DC343FBAC71D13FF4FA9BCE10709 /* Pods-DarkMode.debug.xcconfig */, - CA6014EF6AE8930707D68E71ECA55D13 /* Pods-DarkMode.release.xcconfig */, - ); - name = "Pods-DarkMode"; - path = "Target Support Files/Pods-DarkMode"; - sourceTree = ""; - }; - 5F7F22C754196513F8C5696BE1789D15 /* MBProgressHUD */ = { - isa = PBXGroup; - children = ( - 768B4BE6A62741EA37180E7EC67437C1 /* MBProgressHUD.h */, - B5319E1423AA1E35ADBA7A3B04DF598E /* MBProgressHUD.m */, - 21FF95F8E6CE5D0E67ACE1DF80ED8D03 /* Support Files */, - ); - name = MBProgressHUD; - path = MBProgressHUD; - sourceTree = ""; - }; - 6237A52316AD9B7195EC8FED1CABBCA1 /* YYModel */ = { - isa = PBXGroup; - children = ( - D4336A5672C30CDB1EBF2ABE41670A08 /* NSObject+YYModel.h */, - B72EC130B00BB80835F63C15885EEB06 /* NSObject+YYModel.m */, - 970BB19E23C4B9B7AA3309F224CC0E71 /* YYClassInfo.h */, - D65307FDE17DBA7A0B3A73E64332F870 /* YYClassInfo.m */, - 31214193F010827DB7A59D7F34A65AF0 /* YYModel.h */, - C6C81AD3406E48E475916D291D2F3082 /* Support Files */, - ); - name = YYModel; - path = YYModel; - sourceTree = ""; - }; - 69373CF63774AD2866551D33EEBB796F /* Targets Support Files */ = { - isa = PBXGroup; - children = ( - 4B4EDC9C48CE9C274B5A0CDEB8B1A446 /* Pods-DarkMode */, - ); - name = "Targets Support Files"; - sourceTree = ""; - }; - 6E3986E9FC1C8EFD880C478B01B0EB42 /* Support Files */ = { - isa = PBXGroup; - children = ( - 6641303C0E807B1DB7DE0B014814E30A /* YYImage-dummy.m */, - 8F3589B845F9E0998764CC082B4636FE /* YYImage-prefix.pch */, - 5F8F677D95958C9F3D7EA1F6761CD291 /* YYImage.debug.xcconfig */, - 446D6F21C19F21359994D8C61A378A84 /* YYImage.release.xcconfig */, - ); - name = "Support Files"; - path = "../Target Support Files/YYImage"; - sourceTree = ""; - }; - 6F8E53491B9AD97EEE8695E0C7097D67 /* GPUImage */ = { - isa = PBXGroup; - children = ( - 36A3F94120C780455E9F79C31D756DEC /* GLProgram.h */, - B938A512490439A79E04F0C9697CD365 /* GLProgram.m */, - 4A1109257C4F91B78B674D3ED606F875 /* GPUImage.h */, - BE0B9D8C884083422794279D51378D71 /* GPUImage3x3ConvolutionFilter.h */, - 1B209441C9B2647C1E347736EE8FC64A /* GPUImage3x3ConvolutionFilter.m */, - 115B979659F12A2946B4CE9FB629FC55 /* GPUImage3x3TextureSamplingFilter.h */, - D41C9CF88307CC423AE666B56182E5B9 /* GPUImage3x3TextureSamplingFilter.m */, - 129DAE9BAABDCB922089CE7D3BDF76EC /* GPUImageAdaptiveThresholdFilter.h */, - 00D7FBFB94E92C7589C179A64EA9B9E1 /* GPUImageAdaptiveThresholdFilter.m */, - 5002004ECCBA2AFB115693A8FF292F8D /* GPUImageAddBlendFilter.h */, - 0C250AC091347FFBBF15D1616FB339BA /* GPUImageAddBlendFilter.m */, - 7B03CEF081AF2EB3E5F9FF382D2515F8 /* GPUImageAlphaBlendFilter.h */, - 462A9647EF473D7371FF63E7DF5E9FB1 /* GPUImageAlphaBlendFilter.m */, - 42C7A8AF75309C3CA628C0B8775A0F0B /* GPUImageAmatorkaFilter.h */, - 15E496E703C5AD87E7989377C681D73B /* GPUImageAmatorkaFilter.m */, - D4A60FDE318E3C0F278D020D96060453 /* GPUImageAverageColor.h */, - F3FB9DB94CA9285178C40FCA640755A3 /* GPUImageAverageColor.m */, - 9F1724BCB76C8A64AA536BCED3D812D4 /* GPUImageAverageLuminanceThresholdFilter.h */, - 722AE0C698ABB0490DECD454A56B78D5 /* GPUImageAverageLuminanceThresholdFilter.m */, - 77A6428D36533AF050B1E9F92BF82FD8 /* GPUImageBilateralFilter.h */, - C6C160D9019636230267BE3289CF1EF8 /* GPUImageBilateralFilter.m */, - 03A0D571B1A527AB8B7B3CA882F4D673 /* GPUImageBoxBlurFilter.h */, - 202D068CFDA5C22DA922D9FD075D1806 /* GPUImageBoxBlurFilter.m */, - 89911F978F34916A355191709CBB5802 /* GPUImageBrightnessFilter.h */, - FA45E049B5B5153FBD3529680C70E520 /* GPUImageBrightnessFilter.m */, - 527337E5AE7218053824FE826DE95FB6 /* GPUImageBuffer.h */, - 571C0946C15922F37A4FF9DC53636F23 /* GPUImageBuffer.m */, - FB24E4E098F3B7DE3B8F4ACF2BC28A28 /* GPUImageBulgeDistortionFilter.h */, - B600C9B478F0D9AD34362F46737F82C5 /* GPUImageBulgeDistortionFilter.m */, - A0B5C9037C5004A4E5533B5FE12C1BE7 /* GPUImageCannyEdgeDetectionFilter.h */, - 048641897F1CF7D044ACD0D40581C549 /* GPUImageCannyEdgeDetectionFilter.m */, - 2119B781CCC19BD3D0A42F303D2E7812 /* GPUImageCGAColorspaceFilter.h */, - B748550FB21BB7C03E6327054546AAD9 /* GPUImageCGAColorspaceFilter.m */, - B11AD2552FDB15FF1C538A2621C8454E /* GPUImageChromaKeyBlendFilter.h */, - 76CEE856E426B01553F3D79A1347C109 /* GPUImageChromaKeyBlendFilter.m */, - 12F2B7D58256DFE9C2869DEE816D2FDD /* GPUImageChromaKeyFilter.h */, - 3193AAC04525E3412D850A3D7AD99612 /* GPUImageChromaKeyFilter.m */, - 6FE16BE5263EBF1D2F9145482FAE76E3 /* GPUImageClosingFilter.h */, - BD9B919D49630BD01C44E78237FBD863 /* GPUImageClosingFilter.m */, - 16D91E4D58A94C5524A115536224EA76 /* GPUImageColorBlendFilter.h */, - DC785C323CE09EC09CDC2F8014081C38 /* GPUImageColorBlendFilter.m */, - 73B8731A5CF568F198781C8412733FB0 /* GPUImageColorBurnBlendFilter.h */, - 917747700EB9C26B29A0199F357B3B12 /* GPUImageColorBurnBlendFilter.m */, - 8F83E8DB73761A3F59617E28A1A9351E /* GPUImageColorDodgeBlendFilter.h */, - 0F6459CEEE271680736FA479FD981BD4 /* GPUImageColorDodgeBlendFilter.m */, - 467740B1EE1788F570B996D82E451066 /* GPUImageColorInvertFilter.h */, - B63E6AF28713967F264112F9450B3F8C /* GPUImageColorInvertFilter.m */, - A040C6DAEB250520DDAB80B89F5BDE6B /* GPUImageColorMatrixFilter.h */, - F56DBD12B11C3994DFB4255B1D7CC1D8 /* GPUImageColorMatrixFilter.m */, - 0E3174DCAC3A1A90A069C1EFAE99859F /* GPUImageColorPackingFilter.h */, - 5B231C196006B4B6C3DD281978E5EB74 /* GPUImageColorPackingFilter.m */, - 6679F37F751FAB9174C4595A35CF4822 /* GPUImageContext.h */, - 69BEFC89CA92FA91FB606E547079BABE /* GPUImageContext.m */, - D66E3D513B5531F7F4B074A1AEC523B8 /* GPUImageContrastFilter.h */, - 78FB8998E490B19D8A2CFE9E092F2132 /* GPUImageContrastFilter.m */, - 69E7B0C997A3206F5C0D10C360A6D957 /* GPUImageCropFilter.h */, - BA29045FFD62C4F2F08018346E53B773 /* GPUImageCropFilter.m */, - 611CC398C3A952328326F836188CEC88 /* GPUImageCrosshairGenerator.h */, - 795CA168A9604FBD8784D73FA8C9DE4A /* GPUImageCrosshairGenerator.m */, - 8897A494B1993654654BD96F0352C036 /* GPUImageCrosshatchFilter.h */, - B5497DA96594CCECE8E15AC43C9A2C6B /* GPUImageCrosshatchFilter.m */, - BE4970CD6356FFFAA48E1613FE580EB0 /* GPUImageDarkenBlendFilter.h */, - 6872FC509316C9B4DCA67FFA969849E6 /* GPUImageDarkenBlendFilter.m */, - 64B98E97EBB4B89FF8C0A73B4905060A /* GPUImageDifferenceBlendFilter.h */, - 9DF64883F152558549C53B4951455B9B /* GPUImageDifferenceBlendFilter.m */, - 856409B61D04B0A9D91A67DFFB1C680D /* GPUImageDilationFilter.h */, - DF18464EBC41D32FBD924D4FBD3DCF7D /* GPUImageDilationFilter.m */, - 08FD869A4FD865D449B925CD47230E72 /* GPUImageDirectionalNonMaximumSuppressionFilter.h */, - 1495EAEF4EC6B8FB6E18881881B3573B /* GPUImageDirectionalNonMaximumSuppressionFilter.m */, - 0F5D87CE6703E1941A5580858F307A6D /* GPUImageDirectionalSobelEdgeDetectionFilter.h */, - ECFEB2E93FCE91E7C240F7A5418610E8 /* GPUImageDirectionalSobelEdgeDetectionFilter.m */, - 63157528C8EC3BBA57A086A9E876519F /* GPUImageDissolveBlendFilter.h */, - 27A2C6937109C3C8643FB3E370CDBE29 /* GPUImageDissolveBlendFilter.m */, - 47104284B40E3FE25D823BBBF6BBD751 /* GPUImageDivideBlendFilter.h */, - 40BEB1831EED3C7A7E80C4057D3DA022 /* GPUImageDivideBlendFilter.m */, - 83180B57DF37B3555ED1B68472C45C2C /* GPUImageEmbossFilter.h */, - 6E126A469B8B4CA1D5708D0C66DBCB45 /* GPUImageEmbossFilter.m */, - 1F2C1EF174D0C89A1ECD8D871814D3C5 /* GPUImageErosionFilter.h */, - 48C35BCA747620F3BF149953BFDC422D /* GPUImageErosionFilter.m */, - 1E272A947106122CD1F27C631D653DA4 /* GPUImageExclusionBlendFilter.h */, - DA4B2BBB528CEAFC918860127115B034 /* GPUImageExclusionBlendFilter.m */, - 985698BFE05D67C00294DF094B379513 /* GPUImageExposureFilter.h */, - EA2A44D6FF0F9ACEE1DADC1A14F2854D /* GPUImageExposureFilter.m */, - ED7087E1AAD6DCA511A73A2D2B30D6B4 /* GPUImageFalseColorFilter.h */, - 34E2DEEB4F0ADF11F9C9E23D43C1A3B6 /* GPUImageFalseColorFilter.m */, - 71D502A5B132B8E2D515B9A975C85309 /* GPUImageFASTCornerDetectionFilter.h */, - 50E15C340F7D31DE893B684AFF6EC189 /* GPUImageFASTCornerDetectionFilter.m */, - DCDB8D6607C77835C1EC75EB9F36E5C5 /* GPUImageFilter.h */, - 6FAE5EFDF6BAE35B5464066D6F82F34E /* GPUImageFilter.m */, - 10AF522841E0BF1975899E1F731DDF5D /* GPUImageFilterGroup.h */, - 675DA2B87C4D3A22040B4457A6387B04 /* GPUImageFilterGroup.m */, - 11CCBC30AD14409191CFABD8D074A58D /* GPUImageFilterPipeline.h */, - 2EAC8FE75CB608768A2CEA2F31EDF290 /* GPUImageFilterPipeline.m */, - DEC5E896CBBBB4368B3D73E3B6DF98AF /* GPUImageFramebuffer.h */, - 838B4FE7CBA73D00A0885739EF9AA694 /* GPUImageFramebuffer.m */, - D17E8A9196C94BC7F7B14D0D08A31A90 /* GPUImageFramebufferCache.h */, - EE42EB7F34AB1582A3A5744A834BD119 /* GPUImageFramebufferCache.m */, - 71F455391A9616D714CC8874A51F7EE6 /* GPUImageFramework.h */, - FC8FF675218469A34772983792A93F7D /* GPUImageGammaFilter.h */, - 43F07509067BACE67AB5E9CE46DBB3EE /* GPUImageGammaFilter.m */, - E170213BF8AB60A888762910A4745B2B /* GPUImageGaussianBlurFilter.h */, - 291AEAB6C085560A71960DDDD62ACD1A /* GPUImageGaussianBlurFilter.m */, - C48D8B50088748FC4BC5FC2E0C491663 /* GPUImageGaussianBlurPositionFilter.h */, - 404551280AEA0058459B3385F82AFBBA /* GPUImageGaussianBlurPositionFilter.m */, - AF4FAC2BFB19ABFAB2B98973CF3F2F19 /* GPUImageGaussianSelectiveBlurFilter.h */, - 2B2CFE441A1614F51B47AA982B4E448B /* GPUImageGaussianSelectiveBlurFilter.m */, - 169DF30CA515684B51A770DE262AC808 /* GPUImageGlassSphereFilter.h */, - 4EB243D1C497784152C266E096C23C6C /* GPUImageGlassSphereFilter.m */, - 3C138582918D37CF364E6D3C9898D68F /* GPUImageGrayscaleFilter.h */, - 751129785F65D4A3EA3332CE56D280DD /* GPUImageGrayscaleFilter.m */, - E82866E758AEDE0697B2D6542D52887E /* GPUImageHalftoneFilter.h */, - 2B3AB6691A881BF883BB176FDAB07FBA /* GPUImageHalftoneFilter.m */, - 94E26D38916B6B7C099A974F7D4801BB /* GPUImageHardLightBlendFilter.h */, - 784B2008FD82B473DC377FEEC4B7EFD4 /* GPUImageHardLightBlendFilter.m */, - 2CE39347324DF5B3FC2761B6D191DA9C /* GPUImageHarrisCornerDetectionFilter.h */, - FABBE2C4A63D29A135EB2E35769CF66E /* GPUImageHarrisCornerDetectionFilter.m */, - E63C05F85CF505C1F4F6C1F2A5264989 /* GPUImageHazeFilter.h */, - 8CAC7D39500D3FC8B5E4380E69FFBCCA /* GPUImageHazeFilter.m */, - 2988FF2F5DA771E11045F136F9BD4F0A /* GPUImageHighlightShadowFilter.h */, - 10015A94BC5970A447441E41EFA84CC4 /* GPUImageHighlightShadowFilter.m */, - 4A6F1BA241429526CAA01D945FD69E28 /* GPUImageHighPassFilter.h */, - 30871DDE7586CFF91A2ACC7F23FF6105 /* GPUImageHighPassFilter.m */, - F478792CD6750762D653D4B974565731 /* GPUImageHistogramEqualizationFilter.h */, - B93FEAD1B3DB233D4B21EB7567E5E3A0 /* GPUImageHistogramEqualizationFilter.m */, - 8472059D35BC092DEF41EC2604D795FB /* GPUImageHistogramFilter.h */, - 5D6101DA1E24CEAF212864D149AAA311 /* GPUImageHistogramFilter.m */, - 8CEEEBC4B26A07F17E3509809AE7C514 /* GPUImageHistogramGenerator.h */, - 49E415F2BA5768C469A662DF8C823B3C /* GPUImageHistogramGenerator.m */, - 6CA047F4F7C29EBD892E71642C0B6FD0 /* GPUImageHoughTransformLineDetector.h */, - CF2F73298D0AAD1A41B6CB86926D9317 /* GPUImageHoughTransformLineDetector.m */, - 6DC692CA9FD5C1A42113F450FA649F67 /* GPUImageHSBFilter.h */, - 3262E2097D957FBD0444889742CB1C80 /* GPUImageHSBFilter.m */, - C080FC8084166668F65F78ED0AA4A69B /* GPUImageHueBlendFilter.h */, - F53E198F369DD7B29FDFD1E67D7FEF92 /* GPUImageHueBlendFilter.m */, - 04EED508463C74DA6E7C59026CB90BE8 /* GPUImageHueFilter.h */, - C7E61395FE8E961D58658EFC5FE914A3 /* GPUImageHueFilter.m */, - 79F32CA2AC9383860E5A101F3891F01F /* GPUImageiOSBlurFilter.h */, - 864D6DEE6397881CD3F0FCBC2443BB60 /* GPUImageiOSBlurFilter.m */, - DA29E62F007F394173C5A6E96F4EA3A1 /* GPUImageJFAVoronoiFilter.h */, - 5AB2E9FBA9B5DC6C3B50148EBA2EB69C /* GPUImageJFAVoronoiFilter.m */, - 82C6F83D1D031E0F313B5E11137E072B /* GPUImageKuwaharaFilter.h */, - AC97F32440360E91D0907B1696EFA925 /* GPUImageKuwaharaFilter.m */, - 29114F4BF994DD99DA8B15BD714B5488 /* GPUImageKuwaharaRadius3Filter.h */, - 453BE721D27626D4753B1F021A0126F4 /* GPUImageKuwaharaRadius3Filter.m */, - B015E5C22E17335E3A77DFA9908BB606 /* GPUImageLanczosResamplingFilter.h */, - 37B3E429270DF855D2663E4BE0DCE666 /* GPUImageLanczosResamplingFilter.m */, - B49CFF15CC2A8F9BE7A7F6E9858CF4A9 /* GPUImageLaplacianFilter.h */, - 533CF0E1A935E0C8D6084DE984AA9A48 /* GPUImageLaplacianFilter.m */, - 6460B60CAEB361F43B409D943DD5919E /* GPUImageLevelsFilter.h */, - EEF00EBDB95094FD4257D5613DD330E0 /* GPUImageLevelsFilter.m */, - DFE90665F8A100159773904C5A2F8967 /* GPUImageLightenBlendFilter.h */, - ECEA2E9EE22767E7510CE7AA87771919 /* GPUImageLightenBlendFilter.m */, - 1AF1FBA24B5573418B3316CD3B2CAF8B /* GPUImageLinearBurnBlendFilter.h */, - A3CD8B04FB70BC53E721DA44020D04B1 /* GPUImageLinearBurnBlendFilter.m */, - 3FA9A4C47EC9F4059DAB7AADC578E5AF /* GPUImageLineGenerator.h */, - 2276B332FA8EDDC35FE32348D3EB368C /* GPUImageLineGenerator.m */, - E8B488F92B9569C2D4E2C544410035E4 /* GPUImageLocalBinaryPatternFilter.h */, - DD88158BB140DD22AAFBE5A81587E42D /* GPUImageLocalBinaryPatternFilter.m */, - D5AB4ADA23B1748AB0ED4BB1DB527C69 /* GPUImageLookupFilter.h */, - 9E5657C2668E3B4C728034FA1EA9A0A4 /* GPUImageLookupFilter.m */, - BA371A875E27E7EE7D0FCD1007D94CF2 /* GPUImageLowPassFilter.h */, - 5B86F3F70B22B26EC06C5C412D9B9733 /* GPUImageLowPassFilter.m */, - A22790AD2F8E9488E3E272090ACDE88B /* GPUImageLuminanceRangeFilter.h */, - 94F2208CD8400EF9A4FE9B63DAC5E6E0 /* GPUImageLuminanceRangeFilter.m */, - E26335B2F22D282C8B7582834BD0A07E /* GPUImageLuminanceThresholdFilter.h */, - 7C17752936CF711DF066A5BA091BFA81 /* GPUImageLuminanceThresholdFilter.m */, - 8F06970C1605988B31A04FC0D429E908 /* GPUImageLuminosity.h */, - CFC1905D68B43955A7ECC39E228564DC /* GPUImageLuminosity.m */, - A827A26F6AFD11185014B81B1EDDC257 /* GPUImageLuminosityBlendFilter.h */, - 8BA72D587A6A6B053532804FF36E8E46 /* GPUImageLuminosityBlendFilter.m */, - FF5ACE2C67EA5C6E02ED4D4FBD28FBA7 /* GPUImageMaskFilter.h */, - 21B2916276232C456951467038D3E2FF /* GPUImageMaskFilter.m */, - AB9AABEFA3783A1EFB3AF263028EA22E /* GPUImageMedianFilter.h */, - 34284363F58BE296025C3C9CBD8F317C /* GPUImageMedianFilter.m */, - F448306B3687298FFAD025EB2DDD73EF /* GPUImageMissEtikateFilter.h */, - 1E01E00886BEDC0765B232733C255C1C /* GPUImageMissEtikateFilter.m */, - C3415B253778A17AB9D9E9539C59982E /* GPUImageMonochromeFilter.h */, - A21D094A16257D428FAE0B259CD960F5 /* GPUImageMonochromeFilter.m */, - D24C3AB3AE7CD24FB83746C901F281BA /* GPUImageMosaicFilter.h */, - 9ADFE335A749F6242A5501FC31B4EDB2 /* GPUImageMosaicFilter.m */, - 34804E531C9635A205640CD71C357B77 /* GPUImageMotionBlurFilter.h */, - 488651029866527C3B2644FD81E92587 /* GPUImageMotionBlurFilter.m */, - 2715DCC6112CFACF55C762832D38626D /* GPUImageMotionDetector.h */, - 4CE0EB4E232A38B13CACAA200001C7D9 /* GPUImageMotionDetector.m */, - 3918FDF9EBD2B1FA91FD529E6E34785A /* GPUImageMovie.h */, - 68CD24B140838D08A6E5DD6A70FD8923 /* GPUImageMovie.m */, - 00BAF7C4E2492F63C9589A48B9A174F5 /* GPUImageMovieComposition.h */, - E9BE79BD70E8A2BBB669B77DE76E87B2 /* GPUImageMovieComposition.m */, - 21CD080746E9E7BC9C0BA1E1A2EDF8F0 /* GPUImageMovieWriter.h */, - A17B47159361544A9A5041BCADFB2DA3 /* GPUImageMovieWriter.m */, - 61E2A63537B14F7A60668071C08241DE /* GPUImageMultiplyBlendFilter.h */, - CF78B4B80A067EF3C1E69807978B0212 /* GPUImageMultiplyBlendFilter.m */, - E5AE2B148F45F4E8B8FB0225084DEE18 /* GPUImageNobleCornerDetectionFilter.h */, - 8F4D069CFC80E40C0955894061DC5082 /* GPUImageNobleCornerDetectionFilter.m */, - BDD3B32644BC93C7355A1C520C495A48 /* GPUImageNonMaximumSuppressionFilter.h */, - 4A7B42C55528946ABE27DCA7F4A86E7A /* GPUImageNonMaximumSuppressionFilter.m */, - 35D609B903920B4F5B05401FBC7E489D /* GPUImageNormalBlendFilter.h */, - 49B9B7911201EAA735B877B4E99D31D9 /* GPUImageNormalBlendFilter.m */, - D20E7200664BDC1CA23F83B69DB2AF00 /* GPUImageOpacityFilter.h */, - A0A98FEBD19728184776073D5B656C40 /* GPUImageOpacityFilter.m */, - F2F67F28D47899C70E83AA9305D4E341 /* GPUImageOpeningFilter.h */, - 250D4D5BDE79FE3FB3D8E6BDF13C6F79 /* GPUImageOpeningFilter.m */, - 43471FC538F7533EBC5AA010B09E0958 /* GPUImageOutput.h */, - FD794A0352171C16DFE53E0AB396C398 /* GPUImageOutput.m */, - 80F0F94732C9BFC491C85042FF7D14A5 /* GPUImageOverlayBlendFilter.h */, - D784A6CD68E1A5D8D6580987562CE66F /* GPUImageOverlayBlendFilter.m */, - F412634986B6427C47BFE33290B76D0C /* GPUImageParallelCoordinateLineTransformFilter.h */, - E9AD39DB2F1E55880567989B269FAC3D /* GPUImageParallelCoordinateLineTransformFilter.m */, - E75C8905888A317693F48FC06029AC84 /* GPUImagePerlinNoiseFilter.h */, - 20BC00B3DDB29110A58176CE51605FD4 /* GPUImagePerlinNoiseFilter.m */, - B8113E2BE805826C2206219087AF2FEB /* GPUImagePicture.h */, - B4F3FFA58FE342F21294920E38929E3F /* GPUImagePicture.m */, - 1E9095CF9176D72147052B3FD215EF7F /* GPUImagePicture+TextureSubimage.h */, - C1703B1CC3A8EF46F7E0BC97EF312B15 /* GPUImagePicture+TextureSubimage.m */, - 4272FC95B847753C0B6BA23100C3957E /* GPUImagePinchDistortionFilter.h */, - 870991E39050AAA48FC751AB989A0CEE /* GPUImagePinchDistortionFilter.m */, - D2C5AB16BD22FA6146D9733E98392177 /* GPUImagePixellateFilter.h */, - 9D99E942362A4061252F3303E92A955A /* GPUImagePixellateFilter.m */, - 6DA0D34140F270C03A5A2D7F4CC54517 /* GPUImagePixellatePositionFilter.h */, - AB79E1A4A66A6C04AB9D9EBE73E0A218 /* GPUImagePixellatePositionFilter.m */, - F776E442B4C1CDFEF257F6134CBE90D0 /* GPUImagePoissonBlendFilter.h */, - D54971E35D67E4E2B0A20F8CD8BDB2D4 /* GPUImagePoissonBlendFilter.m */, - 228003B3476B41761F56C932AA1DE129 /* GPUImagePolarPixellateFilter.h */, - 7CD5AC12DA2322B95DFCB7F7D42FBD49 /* GPUImagePolarPixellateFilter.m */, - CA5BC3210A0DC9C52CF983E3FBA33D3D /* GPUImagePolkaDotFilter.h */, - 5B933CA3EC0B18A8DB363F31A85D1268 /* GPUImagePolkaDotFilter.m */, - 69E5EB77E2A5E329FE60A250611BF2FC /* GPUImagePosterizeFilter.h */, - 43A18B72D843666583E43734D2462B4F /* GPUImagePosterizeFilter.m */, - 5021D951EBE0EE5ACBFF0A1D5BF60EC2 /* GPUImagePrewittEdgeDetectionFilter.h */, - 414E85F24E79E32F8EA8031796253C7F /* GPUImagePrewittEdgeDetectionFilter.m */, - F8F996C485D25C0141065FF489D1BA53 /* GPUImageRawDataInput.h */, - D3B1D10EA9F731D0F5F681A4CAEDE5D6 /* GPUImageRawDataInput.m */, - 08FB776087C19D638AA775DF1EA2E6A6 /* GPUImageRawDataOutput.h */, - A1BDF8E1519711BE1634F7B98C1BE5A4 /* GPUImageRawDataOutput.m */, - 56D2D8153149A60C61AB14238CE5A721 /* GPUImageRGBClosingFilter.h */, - 8BBCCF9A4A7C3B7E1D6638E2D15B2B83 /* GPUImageRGBClosingFilter.m */, - 31F4DFCE2BAF8205326A79D123842D37 /* GPUImageRGBDilationFilter.h */, - 87611103457106E50CE6DF1459C428CF /* GPUImageRGBDilationFilter.m */, - 96B10DB742FBE734F2EE564DC1808399 /* GPUImageRGBErosionFilter.h */, - 080F15FCC36CE02B5AA7B6A38D2A6F1C /* GPUImageRGBErosionFilter.m */, - 6E747934866906927486DC94DEC4581B /* GPUImageRGBFilter.h */, - 97BB1E9D14B5C9A8E04954127CF899DD /* GPUImageRGBFilter.m */, - 1A8E625D6539753D6AC67978B97C5D7C /* GPUImageRGBOpeningFilter.h */, - CD17316111B32EDFB414E2DB7107670D /* GPUImageRGBOpeningFilter.m */, - 3F37E42BC4BE8E0517824BABC9869273 /* GPUImageSaturationBlendFilter.h */, - B76EEE6CDA11AED2C0DF42954264E2E4 /* GPUImageSaturationBlendFilter.m */, - 219E2548D3FF4C96F4ED257B47311123 /* GPUImageSaturationFilter.h */, - 1577D323A093A5E9B341C97A2C56FDFF /* GPUImageSaturationFilter.m */, - F1C3D508DA7E563DEA7799B00D9E2113 /* GPUImageScreenBlendFilter.h */, - D4C994A6E8F57B6828552CA504C66D58 /* GPUImageScreenBlendFilter.m */, - 71669CD78F52A5CA28F626C8A16A194C /* GPUImageSepiaFilter.h */, - 5DADF97A372B96269C7E574FFD19EA84 /* GPUImageSepiaFilter.m */, - BBB88E5B5C49D8640CAD758ACB9A6965 /* GPUImageSharpenFilter.h */, - 20C5BE19C1459E39FC196D7A94B0CBE9 /* GPUImageSharpenFilter.m */, - 254E957A25195EAAC2658009BDAEEBBD /* GPUImageShiTomasiFeatureDetectionFilter.h */, - 5388C8B9509AE2A725C77FB08EAB1262 /* GPUImageShiTomasiFeatureDetectionFilter.m */, - 3C8EF79EE8E13A7229E1AF925AEC3BC4 /* GPUImageSingleComponentGaussianBlurFilter.h */, - 4284D70C7F26D1B5D00CB148C3E562E1 /* GPUImageSingleComponentGaussianBlurFilter.m */, - F167A2004301C4034FFB0D96A262B99D /* GPUImageSketchFilter.h */, - 9F81E2DA24707028F902CA5D2165F3AF /* GPUImageSketchFilter.m */, - 3CF95A800A5428B6D2C82CDC82A21CD5 /* GPUImageSmoothToonFilter.h */, - B81F4796AC0D72D4F1B2047D5A0E8AC0 /* GPUImageSmoothToonFilter.m */, - E16FF3BBD2E461C6B31F4D28293DEC1F /* GPUImageSobelEdgeDetectionFilter.h */, - 38948BFE21048F7C6D91B1281E521F1B /* GPUImageSobelEdgeDetectionFilter.m */, - 525E00D440284C93311DF077591CDA15 /* GPUImageSoftEleganceFilter.h */, - AB5B9F20F2CC4E7B1E64873C8F4C7DEB /* GPUImageSoftEleganceFilter.m */, - A0D905911F4E966E46571AE6336725F8 /* GPUImageSoftLightBlendFilter.h */, - 7AF69C635DEFF07CF03F7EC5C93EECC6 /* GPUImageSoftLightBlendFilter.m */, - B43D8D3315443CDCAF2566D64DDEE04B /* GPUImageSolidColorGenerator.h */, - 42D084FF6A05E8F634B9ECC121BB2F70 /* GPUImageSolidColorGenerator.m */, - 074228E092340DEFE657CAF4F22AF822 /* GPUImageSourceOverBlendFilter.h */, - FD17D6790093A05DE5D3FEA809D11BAA /* GPUImageSourceOverBlendFilter.m */, - 844471BB500349B7E35E4D0A96389D2F /* GPUImageSphereRefractionFilter.h */, - B8043D2AA30371284EF62F7AE00669A6 /* GPUImageSphereRefractionFilter.m */, - 77F4D03A5C3A7B3755BD05C6BC87D853 /* GPUImageStillCamera.h */, - 8A630DEACFD6C33B16EABFCBA7B10B6B /* GPUImageStillCamera.m */, - 4A94921FCB9C25F627D3B1EB025EB097 /* GPUImageStretchDistortionFilter.h */, - 22245274C4F286C6221A887D6CD7F1AE /* GPUImageStretchDistortionFilter.m */, - 4A0251929026FA746DAF38200C6045F2 /* GPUImageSubtractBlendFilter.h */, - B841981319C7EF7EE2877086FCA683E5 /* GPUImageSubtractBlendFilter.m */, - BEFFA1F44D79B03904E27FC68BA02324 /* GPUImageSwirlFilter.h */, - B1CF0307FA26395C0EBDD879BF40EE7F /* GPUImageSwirlFilter.m */, - 2428E8C70A2E6595B6031EC3C1851FEF /* GPUImageTextureInput.h */, - 6CCD41C6BD2C0E9ABB3148B70C4BC918 /* GPUImageTextureInput.m */, - 0E198F28897BDB4F191CE84351A84102 /* GPUImageTextureOutput.h */, - 621DA413177A46757ACA5C0C17FE0C8C /* GPUImageTextureOutput.m */, - 5A14EDB5BB818BEE5CEE11AB9273F285 /* GPUImageThreeInputFilter.h */, - 8736944B2594030670245A252F39B7FA /* GPUImageThreeInputFilter.m */, - 240C513A27F958A5DE57B92A02EA4229 /* GPUImageThresholdEdgeDetectionFilter.h */, - 36B4A09ADA586EFD92A79ECD4C0E35A8 /* GPUImageThresholdEdgeDetectionFilter.m */, - 99007670CCD9C91A8F619B9CEA906413 /* GPUImageThresholdedNonMaximumSuppressionFilter.h */, - 07C2E5E0DB6558AF1D582E8DD0D244EB /* GPUImageThresholdedNonMaximumSuppressionFilter.m */, - BBE357EF73F92D80EB2A32F6C9ADC813 /* GPUImageThresholdSketchFilter.h */, - EB47C074A601454370424E7CFB464BCF /* GPUImageThresholdSketchFilter.m */, - 05AE57422D69487A72FEC0CB766E61D0 /* GPUImageTiltShiftFilter.h */, - C0C8CE6B752A1D6DC908E8EBC379636C /* GPUImageTiltShiftFilter.m */, - 5D6604B45B92B4410C171D7E0C6B4939 /* GPUImageToneCurveFilter.h */, - FB638C9B72C7E7F1B16A43E90A8BF20E /* GPUImageToneCurveFilter.m */, - CE8390129A638BE0F4AE19C96CACE467 /* GPUImageToonFilter.h */, - 80DCA9ABD24683C3D8FAE083D96F58E5 /* GPUImageToonFilter.m */, - 0E48FED45DEF3A3929689CA91C2C802C /* GPUImageTransformFilter.h */, - 25B452C9C925DADC958E77C39081288F /* GPUImageTransformFilter.m */, - 0CA0BA0CC8335A694D5350A133298DB3 /* GPUImageTwoInputCrossTextureSamplingFilter.h */, - 59C6E40234EEDDD4087F2CFFF63582D0 /* GPUImageTwoInputCrossTextureSamplingFilter.m */, - 537E9A1D3C9B19E06AD252A90F35F4FC /* GPUImageTwoInputFilter.h */, - 30A8C055AB3C18A2E3FE4F47E4F66E5A /* GPUImageTwoInputFilter.m */, - A7E3C6A77B24BBCAF360A95E890B7F76 /* GPUImageTwoPassFilter.h */, - 84948E8F3C90A486BDED1DDC42DD9B6D /* GPUImageTwoPassFilter.m */, - F4CCD104A376890D8A12507C5239B8B1 /* GPUImageTwoPassTextureSamplingFilter.h */, - 53D16559576FCC95A4CD46C46C5DE443 /* GPUImageTwoPassTextureSamplingFilter.m */, - ABEA5E282030B2AACB13107445796E9B /* GPUImageUIElement.h */, - F11B4258E3FA4A8841B1604E377E7F3D /* GPUImageUIElement.m */, - A02D900146C224595943A9226D2DCAD8 /* GPUImageUnsharpMaskFilter.h */, - 1F0C80FAC0118D3106441EE7BCBCFF00 /* GPUImageUnsharpMaskFilter.m */, - 3FE5C658FDFFD20E3BCD7C36D40923A3 /* GPUImageVideoCamera.h */, - DDB88636BCAA89B17531BEAC2B7677B4 /* GPUImageVideoCamera.m */, - 295A7F01A1F9CE9A049C72379F8EC892 /* GPUImageView.h */, - FC2B794A56EF9D2701B9021759093037 /* GPUImageView.m */, - FC35CED2A95AFEA26980C9D4ABC06D40 /* GPUImageVignetteFilter.h */, - 9FE18CDF175FE55AE74C18EF88123854 /* GPUImageVignetteFilter.m */, - 83FF0DCFBB0CF862F4E2370485036696 /* GPUImageVoronoiConsumerFilter.h */, - E7ED5325591277156B4BB5CC580E9723 /* GPUImageVoronoiConsumerFilter.m */, - 894067B7B8B143B196F909226A542245 /* GPUImageWeakPixelInclusionFilter.h */, - 092384ABCABB5474EAF3E9D8F02DF29F /* GPUImageWeakPixelInclusionFilter.m */, - E9EBE53088D96916DD20443C82AFBDE7 /* GPUImageWhiteBalanceFilter.h */, - 7FEA48B785F73A0492D9D729976FD86B /* GPUImageWhiteBalanceFilter.m */, - C8EFB486F7011880B250BD588AF6B03A /* GPUImageXYDerivativeFilter.h */, - 2BB60AA6A277030CEA93B362B1061701 /* GPUImageXYDerivativeFilter.m */, - 8A10226B00432CC14F57C84CDA29A0B6 /* GPUImageZoomBlurFilter.h */, - 0274C1DACB9A0794CFD00841FAE59E3D /* GPUImageZoomBlurFilter.m */, - AEC0F8FA3365AF5A65D1E737B9F44CA2 /* Resources */, - 141D0B28506AB42A59DFF063B66A5B9D /* Support Files */, - ); - name = GPUImage; - path = GPUImage; - sourceTree = ""; - }; - 7596DCB5E576E1B05684D75984D7DEE5 /* YYImage */ = { - isa = PBXGroup; - children = ( - 1074CCDDB3F516ED42AC73FF531270DC /* Core */, - 6E3986E9FC1C8EFD880C478B01B0EB42 /* Support Files */, - ); - name = YYImage; - path = YYImage; - sourceTree = ""; - }; - 992A970CDF3E62FE974C2FB731009A04 /* Products */ = { - isa = PBXGroup; - children = ( - 79E8CB24F46AA9A51F87BBDF2D0AC238 /* libGPUImage.a */, - 1FFED36A657123030ABB700256D73F15 /* libMasonry.a */, - 8B8FAB0D627B17EDE1366984278705D9 /* libMBProgressHUD.a */, - 0B4A1372A24E73913DC7C605E4BD9472 /* libPods-DarkMode.a */, - 48ACF38225AF5129416A1F090F6D3286 /* libYYCache.a */, - 0C6F4829D47D1826F47CDC4264F9F6A8 /* libYYImage.a */, - E460D5B0416D36F66EE8EC89E5D2FA0A /* libYYModel.a */, - 4FC1978206616CE319648B302B05AA8A /* libYYWebImage.a */, - ); - name = Products; - sourceTree = ""; - }; - AEC0F8FA3365AF5A65D1E737B9F44CA2 /* Resources */ = { - isa = PBXGroup; - children = ( - 8AC2A96E79A66C63B15134B252A9BD15 /* lookup.png */, - AC973EBC40064F309FCCDDEC38ED1151 /* lookup_amatorka.png */, - 48BC391B2B9B8DF60B1BC90CF239FC80 /* lookup_miss_etikate.png */, - BF320EFBDD4F9B7040C07E0E3056F74E /* lookup_soft_elegance_1.png */, - 85B8CD154BD93A91C3B231B46DFA42BC /* lookup_soft_elegance_2.png */, - ); - name = Resources; - sourceTree = ""; - }; - C6C81AD3406E48E475916D291D2F3082 /* Support Files */ = { - isa = PBXGroup; - children = ( - 55DC707CC4179395588164EA0C8D4DF8 /* YYModel-dummy.m */, - 0D0402BAF334A2BDC1E4932E93A77CFD /* YYModel-prefix.pch */, - BE1BD7513325F0024AB5F0B2AA5B5308 /* YYModel.debug.xcconfig */, - FC1BB8206A536BE18D03949E8E9E8D59 /* YYModel.release.xcconfig */, - ); - name = "Support Files"; - path = "../Target Support Files/YYModel"; - sourceTree = ""; - }; - CF1408CF629C7361332E53B88F7BD30C = { - isa = PBXGroup; - children = ( - 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, - D89477F20FB1DE18A04690586D7808C4 /* Frameworks */, - 3B5EB31541FAB7B733903648FE8E1F55 /* Pods */, - 992A970CDF3E62FE974C2FB731009A04 /* Products */, - 69373CF63774AD2866551D33EEBB796F /* Targets Support Files */, - ); - sourceTree = ""; - }; - D89477F20FB1DE18A04690586D7808C4 /* Frameworks */ = { - isa = PBXGroup; - children = ( - ); - name = Frameworks; - sourceTree = ""; - }; - EE1473FB6742C310B59547D29782341E /* YYWebImage */ = { - isa = PBXGroup; - children = ( - 3D59E89941BC318DF7FC1D5BC49895CD /* _YYWebImageSetter.h */, - 216F8CFBA824F61AE51F0BE1FB37998B /* _YYWebImageSetter.m */, - B9A029945B47FB73CDE3CC37104F813F /* CALayer+YYWebImage.h */, - C05B47CD66C71D9CAAF1627186D1C6DE /* CALayer+YYWebImage.m */, - 01B971D8030BF11EC3D14181720444C4 /* MKAnnotationView+YYWebImage.h */, - 9680F05DBD64586E9AB59F33EA7E289F /* MKAnnotationView+YYWebImage.m */, - F38E818E85AFE98DD31A606DB69D79D5 /* UIButton+YYWebImage.h */, - 0920AF97BC9AA2C404C3E60972978562 /* UIButton+YYWebImage.m */, - F02B616DA404DA9F64E1EB8DD4C522B1 /* UIImage+YYWebImage.h */, - E578EF7302261D7D50382800254764B6 /* UIImage+YYWebImage.m */, - B4080351977D02914F701E5AF2820E28 /* UIImageView+YYWebImage.h */, - DD2430725CE2EF7139ADE4BBC1C7CBA8 /* UIImageView+YYWebImage.m */, - 372EFFE9AC19817C164303970B18F910 /* YYImageCache.h */, - CB5A0BE4A5245E286AF7E6814CDD1436 /* YYImageCache.m */, - 8DEFD1186E4AE1006B42EF52538073A3 /* YYWebImage.h */, - 5C40FD404F6B8A2300E4B45AA2B6F9A8 /* YYWebImageManager.h */, - 8F3286B04ABC750B2DA6269CDAB9A3B0 /* YYWebImageManager.m */, - 019AEDB1F84B03733946BD4BAABB969C /* YYWebImageOperation.h */, - 48F476DACC4D9202F44C5407ACDA8410 /* YYWebImageOperation.m */, - 105C7CB0B46A09824CEAF5904D491772 /* Support Files */, - ); - name = YYWebImage; - path = YYWebImage; - sourceTree = ""; - }; - F6B09B74CE642AF4F9AB051723E51BB8 /* Masonry */ = { - isa = PBXGroup; - children = ( - 1601092CB8E312022FDE49393A610FA4 /* MASCompositeConstraint.h */, - AF50E9AAD19F008B707D7D8F7EACA2D3 /* MASCompositeConstraint.m */, - 13093D7BD9574A7D40FB42A21DB87F15 /* MASConstraint.h */, - B31F1147C4556865B64D707FEE8CCC97 /* MASConstraint.m */, - F73A13F286165F4836D8D7D4AAC5C284 /* MASConstraint+Private.h */, - 5E64875CACD9293F8463A7DEB77900AF /* MASConstraintMaker.h */, - C8E3D2D6BFE3A6A5011A9A78D5041D6B /* MASConstraintMaker.m */, - 0D5623738ABFF1744B71396958D31566 /* MASLayoutConstraint.h */, - 8C3AE50C738678F7E82112FDB4A8E70C /* MASLayoutConstraint.m */, - CAD1753F08C939B747A9310D6E2C7CCD /* Masonry.h */, - CE8B3FE478847A7AAD2B21BC40809B56 /* MASUtilities.h */, - 3E7EB13B2D474F8DE4852C033BF689FB /* MASViewAttribute.h */, - 9B4EE9ADF2AF51D5C395568406645F72 /* MASViewAttribute.m */, - F1A5C4493663A851186ED81654C1C388 /* MASViewConstraint.h */, - E48C3FA68C009689F44837B466401AA1 /* MASViewConstraint.m */, - BE81F8031495E743E805E3F1ABB005EE /* NSArray+MASAdditions.h */, - 05C8A3D41E95FB4EF796E14A592986C7 /* NSArray+MASAdditions.m */, - E11AAC1475379E882BBED87C93CA898B /* NSArray+MASShorthandAdditions.h */, - 36454A100B7DDEDEA1E782EF2E9E27AC /* NSLayoutConstraint+MASDebugAdditions.h */, - 8D6496F72C325C292BB59F2D94A654A2 /* NSLayoutConstraint+MASDebugAdditions.m */, - C4193CD804FDADD82E3B8FE1883F6D29 /* View+MASAdditions.h */, - 7EBD52032DCAFDAEC06FD991BB8695A8 /* View+MASAdditions.m */, - 82945F15766B165DCCA8DA4BC2C4BD87 /* View+MASShorthandAdditions.h */, - 5C0B54E85F3F7357A3084FAC6447AFF1 /* ViewController+MASAdditions.h */, - 6EEB662CC37ABBC8474275EEA42AB477 /* ViewController+MASAdditions.m */, - 37A14F42D10EDBCCC6657E748D3F9A4A /* Support Files */, - ); - name = Masonry; - path = Masonry; - sourceTree = ""; - }; - FD4CF277559D15A4F3FD03F6768FDB65 /* YYCache */ = { - isa = PBXGroup; - children = ( - 2E5AC46F45E4451E72AC537BB70B1812 /* YYCache.h */, - 160895B89A8B29B177F36E3AF17C2C11 /* YYCache.m */, - 926120A3C10BB72D3539005BC5D12636 /* YYDiskCache.h */, - 7B515D86A399467A37FA4BA15B8B0887 /* YYDiskCache.m */, - 41E7FFB3E5D0BA8ABC62E1A89D3063A8 /* YYKVStorage.h */, - E17C159C87DA98A853415C410757984D /* YYKVStorage.m */, - AFB401E05E9C8DEA8B23609216EB64E5 /* YYMemoryCache.h */, - D6DEC4D0701355737F042ABE9389A98E /* YYMemoryCache.m */, - 378BFCD52F81F2771D1C85755501112C /* Support Files */, - ); - name = YYCache; - path = YYCache; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 1AF60014033E7281EAFAD4E7CD034ABA /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 74BEC30868283F25D6D5F8ABFF0BE76B /* GLProgram.h in Headers */, - 029F819514A66087992EE035796FB9F2 /* GPUImage.h in Headers */, - D3E0F67215B94615E748A1D2C98439AD /* GPUImage3x3ConvolutionFilter.h in Headers */, - 70E9D98EAD51C5A686AAD7DCDF267C0A /* GPUImage3x3TextureSamplingFilter.h in Headers */, - D8AC3A3A9FC2C585805D8130985DFA64 /* GPUImageAdaptiveThresholdFilter.h in Headers */, - 8F2F540C8BCC922C80CB0EEC85AE2CB6 /* GPUImageAddBlendFilter.h in Headers */, - AA6F89A3BB414439A39AD2FE6C4B6C5A /* GPUImageAlphaBlendFilter.h in Headers */, - 32EE5B60261B8BC36AFE11DF61DF7FE8 /* GPUImageAmatorkaFilter.h in Headers */, - B9A2408D5950F5547F7D82E84217F63E /* GPUImageAverageColor.h in Headers */, - 8E76ED19F995FA81CFA03FF86BF480D8 /* GPUImageAverageLuminanceThresholdFilter.h in Headers */, - 2DF0E53968A631FCBDD17A7F6476285E /* GPUImageBilateralFilter.h in Headers */, - E0D741EB912B03FB998FF163F941827A /* GPUImageBoxBlurFilter.h in Headers */, - F4BA7E7FFAF565B29CC82D54B793EF78 /* GPUImageBrightnessFilter.h in Headers */, - D945A64F6CF78BE653585C4ACE0E24EF /* GPUImageBuffer.h in Headers */, - AAD0F39A4AA032B8C0C0B40EA7441E94 /* GPUImageBulgeDistortionFilter.h in Headers */, - 501A410F165BE59627833296C733AD55 /* GPUImageCannyEdgeDetectionFilter.h in Headers */, - CCC7F68CE9545A177EC9EA20AA2AE9C5 /* GPUImageCGAColorspaceFilter.h in Headers */, - 0B1B3B1DB51A07B13F0A363BC22F59A2 /* GPUImageChromaKeyBlendFilter.h in Headers */, - E7AF1651C307635FC4A9E52F6911B3B3 /* GPUImageChromaKeyFilter.h in Headers */, - 71F48775913C25AC156501B0EC59BFEA /* GPUImageClosingFilter.h in Headers */, - CDF22D54534615D38B7CB2ECF4C15367 /* GPUImageColorBlendFilter.h in Headers */, - 608A35BC3D8DA3484591875607E5D90C /* GPUImageColorBurnBlendFilter.h in Headers */, - 089AB5F862A3EF9A0218037D8C73DB9D /* GPUImageColorDodgeBlendFilter.h in Headers */, - D983E144A1EAF9EF20BFD31AEBD9BEBF /* GPUImageColorInvertFilter.h in Headers */, - D9760E3346290F95407D7DC02CE7CBCC /* GPUImageColorMatrixFilter.h in Headers */, - 749A8557351FDA52225E717CA8D80719 /* GPUImageColorPackingFilter.h in Headers */, - 832DE22BB0C9275FF031A74E88D0BFD6 /* GPUImageContext.h in Headers */, - B631B16F2CBE7157B23476CBDCE715E5 /* GPUImageContrastFilter.h in Headers */, - 9FA8C873F74D9C40A96BE74F017385CB /* GPUImageCropFilter.h in Headers */, - B1E3E64D5F9CBBA0AC445152F0502EAA /* GPUImageCrosshairGenerator.h in Headers */, - 3AA724CDE56C03778D0D8C6C614C28E5 /* GPUImageCrosshatchFilter.h in Headers */, - 7F421D9C31DC0525924101675B8EE24E /* GPUImageDarkenBlendFilter.h in Headers */, - 6B40D4EB83F51507D03ACD5FDBBEF888 /* GPUImageDifferenceBlendFilter.h in Headers */, - BD451674A244E95543E0CE56FEB2DDD4 /* GPUImageDilationFilter.h in Headers */, - FC910491DAAFF857945049B0434F398D /* GPUImageDirectionalNonMaximumSuppressionFilter.h in Headers */, - 3506EE5862108B2A8C41A20D99355F18 /* GPUImageDirectionalSobelEdgeDetectionFilter.h in Headers */, - 6D8EBA9E4E1129A31580B8B4D7345A8F /* GPUImageDissolveBlendFilter.h in Headers */, - 7D9CEFE99BDDDF6D1AD696E3A8E3C349 /* GPUImageDivideBlendFilter.h in Headers */, - EEF7E74667C5176B5F1554D7184F2A6A /* GPUImageEmbossFilter.h in Headers */, - 4FF8537039C6FB3E87DCC9F4A0390D2F /* GPUImageErosionFilter.h in Headers */, - 012A87349E85A8CA10E4AD07361E6D86 /* GPUImageExclusionBlendFilter.h in Headers */, - 7706E5C445117A81B0442E5C19F7AF84 /* GPUImageExposureFilter.h in Headers */, - 8E64B342157226991EE54B8F6152A1A4 /* GPUImageFalseColorFilter.h in Headers */, - 52914E62535E485DD3712D4563197A4E /* GPUImageFASTCornerDetectionFilter.h in Headers */, - 647A2EAB797A3D68176CC3AC101F2F1A /* GPUImageFilter.h in Headers */, - B82BCA913A74C5C17CF67BB48430A6E9 /* GPUImageFilterGroup.h in Headers */, - F3E6FD4C3F7B20EDF489236C6EC945DF /* GPUImageFilterPipeline.h in Headers */, - 307069FED8CBB5FD30C15FC7C0A62182 /* GPUImageFramebuffer.h in Headers */, - 9F1608BD340BF4B02A5B88CA03707AA1 /* GPUImageFramebufferCache.h in Headers */, - 0F9FB5E7A6BC661FC3F8852F4FC69D86 /* GPUImageFramework.h in Headers */, - EB76EA09E1FC065CB6203F5F602D76F0 /* GPUImageGammaFilter.h in Headers */, - 26A8C66FE48977B328358F9F2BF641A0 /* GPUImageGaussianBlurFilter.h in Headers */, - F8357854AE9106751D53AB8C32932F46 /* GPUImageGaussianBlurPositionFilter.h in Headers */, - 7A4F580731F192D5E8C6AF86AB44FBF3 /* GPUImageGaussianSelectiveBlurFilter.h in Headers */, - AFB6AFAD5CDE82433B7EF710AEABFFEC /* GPUImageGlassSphereFilter.h in Headers */, - 5EAB582B3DAE152158E656DDCD462408 /* GPUImageGrayscaleFilter.h in Headers */, - B8835F0715C5DCFFDB7FED7098B47596 /* GPUImageHalftoneFilter.h in Headers */, - C2480784B8731B3505C36BEC36F43F77 /* GPUImageHardLightBlendFilter.h in Headers */, - 293D641452CDA50B1DE046BB9B5105B1 /* GPUImageHarrisCornerDetectionFilter.h in Headers */, - D29C5C66C8885349266175C1D749F02F /* GPUImageHazeFilter.h in Headers */, - 441A09967A85ABE244200F5B5E6EC9A3 /* GPUImageHighlightShadowFilter.h in Headers */, - EA5E2729A6E87C922CDF98A3ACB985BC /* GPUImageHighPassFilter.h in Headers */, - A407D6E4E7732ABCAB9C121D415AF3E6 /* GPUImageHistogramEqualizationFilter.h in Headers */, - 42EF3318A12DEA2D31B64DA77EFE2FB3 /* GPUImageHistogramFilter.h in Headers */, - 3A87E2458C94D01EEEC9538DB032AC9D /* GPUImageHistogramGenerator.h in Headers */, - 2F701A9E49DDA3C1A240D28CC2285636 /* GPUImageHoughTransformLineDetector.h in Headers */, - D5193E9E46629B96BDEB10DAEF57582D /* GPUImageHSBFilter.h in Headers */, - 044D6E9E03CB8ECD6E58801E7C6C527A /* GPUImageHueBlendFilter.h in Headers */, - EB847D328F7F2D583D63181D9829991A /* GPUImageHueFilter.h in Headers */, - 4B1D960FF8280CC54413CABB5D2F2A2E /* GPUImageiOSBlurFilter.h in Headers */, - F82C2A26F6554330AF6E40C05326362A /* GPUImageJFAVoronoiFilter.h in Headers */, - 40B61558F93F007E0435D240EBA4A5E4 /* GPUImageKuwaharaFilter.h in Headers */, - 6480781DB47D05BF915975DC8A7B61BE /* GPUImageKuwaharaRadius3Filter.h in Headers */, - 3BF8C851F81EBF3411E82F9E1C793DAE /* GPUImageLanczosResamplingFilter.h in Headers */, - 4EC8896E34902FB81D8ECE3CBCE43F22 /* GPUImageLaplacianFilter.h in Headers */, - 2B3F38B85111F3D785A806C971FE2F23 /* GPUImageLevelsFilter.h in Headers */, - 0F1318DD0AD76D96EB95DA11FE97A2C1 /* GPUImageLightenBlendFilter.h in Headers */, - 47699E5E05076562ACB35B1C71C13347 /* GPUImageLinearBurnBlendFilter.h in Headers */, - 076971540B7FE20B66B50A6DBEC80064 /* GPUImageLineGenerator.h in Headers */, - 7F4CA66F56ECEC45306530ABA32178DD /* GPUImageLocalBinaryPatternFilter.h in Headers */, - 2516CA9197EA00286EFFAAD3A11402C5 /* GPUImageLookupFilter.h in Headers */, - D0C48086A9D1C8721C57BC59E3ABC9B4 /* GPUImageLowPassFilter.h in Headers */, - 5E8E7BB740E167DE322057CBF4E4ACFF /* GPUImageLuminanceRangeFilter.h in Headers */, - F96CD4E0A91280398E5A1874D2B3A5D0 /* GPUImageLuminanceThresholdFilter.h in Headers */, - 715144603B1E95E5FD199B6A820F3FC8 /* GPUImageLuminosity.h in Headers */, - 92AE518A0FBE98A0DF863B8DF7AC1FF3 /* GPUImageLuminosityBlendFilter.h in Headers */, - B78DB212BF2C1ADB6DCF09953314CABD /* GPUImageMaskFilter.h in Headers */, - E692F6CB653BDF7FCCE2A253E019F409 /* GPUImageMedianFilter.h in Headers */, - 21D3457D9AA054C835BB17F56A79041D /* GPUImageMissEtikateFilter.h in Headers */, - BFBF5806B8FB170749BF71FCFA77096D /* GPUImageMonochromeFilter.h in Headers */, - 44ABF3A14712E8B399B82DF3A2967A0A /* GPUImageMosaicFilter.h in Headers */, - 66ED1E95B81405D02E043A58017D95F0 /* GPUImageMotionBlurFilter.h in Headers */, - D0AA94BD089FEAD90D37D172CE9803B5 /* GPUImageMotionDetector.h in Headers */, - 6D957B3608267293F263AC16C250F6FD /* GPUImageMovie.h in Headers */, - 686489D54A6EA62779A0F4C34D29934F /* GPUImageMovieComposition.h in Headers */, - 9679F252AD137F1DC4749381E3238620 /* GPUImageMovieWriter.h in Headers */, - 00BC50439EB78BC024C8271F5FC50579 /* GPUImageMultiplyBlendFilter.h in Headers */, - C3215C21113B7017773F61D8E2C0F05C /* GPUImageNobleCornerDetectionFilter.h in Headers */, - 6FA721F4651B626AD252155EAC6BF7F4 /* GPUImageNonMaximumSuppressionFilter.h in Headers */, - D90E1DB2985F031A249C1CD1D7A48AF6 /* GPUImageNormalBlendFilter.h in Headers */, - F0088DAB471D5A3F2924964CD410BE41 /* GPUImageOpacityFilter.h in Headers */, - A6D788652DBBA97BB929B66E8FABF5FC /* GPUImageOpeningFilter.h in Headers */, - 527FC696CFE9E79296FAE22B581EDF93 /* GPUImageOutput.h in Headers */, - 15237712FC9D46A2037F26E70353D2EA /* GPUImageOverlayBlendFilter.h in Headers */, - 858B891B75D0F43A511C03E9CCEA9E8C /* GPUImageParallelCoordinateLineTransformFilter.h in Headers */, - 3490572882298AE0C0313A3214E36B06 /* GPUImagePerlinNoiseFilter.h in Headers */, - 247F37C5897D9F02668D125EFFB75B59 /* GPUImagePicture+TextureSubimage.h in Headers */, - 3E31203B357CAE0A15DB0850091BB79B /* GPUImagePicture.h in Headers */, - 9B2FF85F49CFCBFD69ABF044B8AF17CA /* GPUImagePinchDistortionFilter.h in Headers */, - 1FDB79E9550E8876B19B618E78F53309 /* GPUImagePixellateFilter.h in Headers */, - A5ECEA60FC0AADF57283128443C642E7 /* GPUImagePixellatePositionFilter.h in Headers */, - F4026D5FBB3EB246FEF59DA6B805FDAD /* GPUImagePoissonBlendFilter.h in Headers */, - E611F7A8E5966E6E2E68224A3F4F42EB /* GPUImagePolarPixellateFilter.h in Headers */, - 70F45CBA5AE0D7F59DDD9340AB3BD317 /* GPUImagePolkaDotFilter.h in Headers */, - 64000452C59702057A087C4A76CFE687 /* GPUImagePosterizeFilter.h in Headers */, - 531132F9F82136C7E0089691EF9D1836 /* GPUImagePrewittEdgeDetectionFilter.h in Headers */, - 5F285812B5CDF5D9FD0533372DA93B36 /* GPUImageRawDataInput.h in Headers */, - 703D0714CF1905012533BA95ECFFF425 /* GPUImageRawDataOutput.h in Headers */, - 63546D4E91CCFC991D704AA7E55D3EF4 /* GPUImageRGBClosingFilter.h in Headers */, - 23FBD272CA96DCB898B9271EB71F7D51 /* GPUImageRGBDilationFilter.h in Headers */, - 7B6553286815200C94E24B0AD34C3E42 /* GPUImageRGBErosionFilter.h in Headers */, - A1CB7B78C1D3374BAEA9A2BCC3A25656 /* GPUImageRGBFilter.h in Headers */, - 8620831289FD8F3A3595EAF6DAE7138F /* GPUImageRGBOpeningFilter.h in Headers */, - AD8503BD62763B8ACD0D4FFF1E8C56A2 /* GPUImageSaturationBlendFilter.h in Headers */, - BB2A9B9161E5F0AECC9F3CC31F6D85F6 /* GPUImageSaturationFilter.h in Headers */, - D379D3AECD4C3EDBD261235D63E260FF /* GPUImageScreenBlendFilter.h in Headers */, - 03182402D9CC511877544D993D1FFA9E /* GPUImageSepiaFilter.h in Headers */, - 29B8B5BB202D5EAB464A41B22DE1B5BC /* GPUImageSharpenFilter.h in Headers */, - DF95FC4FF9019EEB2C9717A8BE4F2EFE /* GPUImageShiTomasiFeatureDetectionFilter.h in Headers */, - 83A1B04E0BA640C7FB29FAA7A629B328 /* GPUImageSingleComponentGaussianBlurFilter.h in Headers */, - C4E5DEC7DF514A359AA062C7F13C95A4 /* GPUImageSketchFilter.h in Headers */, - DA49D1C675F5679D26CB9069A7269185 /* GPUImageSmoothToonFilter.h in Headers */, - 4B3E8A322CC1A802C18F4D2BC353D07B /* GPUImageSobelEdgeDetectionFilter.h in Headers */, - 2EEFD3082E5C0D943EB927EE0E18FCB1 /* GPUImageSoftEleganceFilter.h in Headers */, - B79E092F5B29C5C8B7359493C043A4DE /* GPUImageSoftLightBlendFilter.h in Headers */, - 940FA559831E8663F4C3C2CFAB214B86 /* GPUImageSolidColorGenerator.h in Headers */, - 37CE879D95C30445360AD6D0C1FA7CC4 /* GPUImageSourceOverBlendFilter.h in Headers */, - E5C0807D620C0E07706C6C00F87B7D7D /* GPUImageSphereRefractionFilter.h in Headers */, - E84C5D01F33A6C9AFFFA1B009D4BD25E /* GPUImageStillCamera.h in Headers */, - A07E94BD19655E823533CEFB4DBDD203 /* GPUImageStretchDistortionFilter.h in Headers */, - 9B8A55EA1B0232CA9B99B1F3B67595F4 /* GPUImageSubtractBlendFilter.h in Headers */, - 89215341FB58A6E29005197E676AC1FC /* GPUImageSwirlFilter.h in Headers */, - 9AF58F81BAD92835CEEDBB31C74435DB /* GPUImageTextureInput.h in Headers */, - D73DFCB550FD90D81582D87DEC5FBFBB /* GPUImageTextureOutput.h in Headers */, - 9B3F3992A312CBF772A509E737CD7230 /* GPUImageThreeInputFilter.h in Headers */, - 54AC6004FE0F928E06D79A88364B08C2 /* GPUImageThresholdEdgeDetectionFilter.h in Headers */, - 4B29282458432763173D54C2F5B21719 /* GPUImageThresholdedNonMaximumSuppressionFilter.h in Headers */, - 50C2B02BB91270A6EB35F60571F06E54 /* GPUImageThresholdSketchFilter.h in Headers */, - E275F7BF40EC2FB17B2ED9029FF06BCA /* GPUImageTiltShiftFilter.h in Headers */, - 46FBEAFB68F195DBF93DEE185B5B821E /* GPUImageToneCurveFilter.h in Headers */, - 9F1EDF344FCF17EE6EF5A072D727E3A7 /* GPUImageToonFilter.h in Headers */, - 2A0981C33E3E8401ECD3482994B3BCBF /* GPUImageTransformFilter.h in Headers */, - 6CD33B44569EC746123A3B3684E2CE91 /* GPUImageTwoInputCrossTextureSamplingFilter.h in Headers */, - F1750C9B60511FA4C2FFA9326C53194F /* GPUImageTwoInputFilter.h in Headers */, - 29065AD49ABF0ECB23CF05B75B448A05 /* GPUImageTwoPassFilter.h in Headers */, - 5ECA6D4026DE7F909DD178B2DBF665FB /* GPUImageTwoPassTextureSamplingFilter.h in Headers */, - FC39728CECE4A700D8315298E8649507 /* GPUImageUIElement.h in Headers */, - F4147D4455B06FAC3BF47FD552C69DDA /* GPUImageUnsharpMaskFilter.h in Headers */, - 168FB6A74A76E3979C4E47BBADF7DBFE /* GPUImageVideoCamera.h in Headers */, - 41CC5477C7CC1FCAFA0486B4710DB563 /* GPUImageView.h in Headers */, - FF641038FDDC7E524267A555915BBA70 /* GPUImageVignetteFilter.h in Headers */, - 1C02510C4D6500A7A376A57169D955DC /* GPUImageVoronoiConsumerFilter.h in Headers */, - AFD895639FCE8E367E47C39C13807509 /* GPUImageWeakPixelInclusionFilter.h in Headers */, - 76429EB123F7CB8020EB29A82765DFDB /* GPUImageWhiteBalanceFilter.h in Headers */, - 47DDAD3895F510382B2D81B70B620529 /* GPUImageXYDerivativeFilter.h in Headers */, - EFD2E46C54A13C1D9D72DE9F8531AD92 /* GPUImageZoomBlurFilter.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 2697A8D6B2989B073B236F7B4BF67F30 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 92BF70E9D3285561EB404A7C4A4A6DEE /* MASCompositeConstraint.h in Headers */, - 4CE091F886EC6324673EFE0AEBBEA0FE /* MASConstraint+Private.h in Headers */, - EB663E3E1EB4BB670DC29B77DB330135 /* MASConstraint.h in Headers */, - 9194B58ACE900ED6BAE6AD92E24A2CFF /* MASConstraintMaker.h in Headers */, - 7CF2AC7A3B3ED03B30C1E4ED662B0551 /* MASLayoutConstraint.h in Headers */, - B20A0E5D8F9BCED1A82793C4BE9E7258 /* Masonry.h in Headers */, - 65E88072A2BDC576BFC85E67EF9FBBC6 /* MASUtilities.h in Headers */, - 42947699890A199B08A896144A878D80 /* MASViewAttribute.h in Headers */, - 115ACCE253A886181B55773DDC70D6ED /* MASViewConstraint.h in Headers */, - F1B75048874B8773E5568E6D3ACA12E4 /* NSArray+MASAdditions.h in Headers */, - 81F811A56B6724F7E8E2D25364E595E3 /* NSArray+MASShorthandAdditions.h in Headers */, - C74D2E856ADC8139CD00DBD184061B23 /* NSLayoutConstraint+MASDebugAdditions.h in Headers */, - 46692A2E77157B00827182C8DC686F72 /* View+MASAdditions.h in Headers */, - A3307B8FB6EE0A049DBAE3AA4D2C6DA0 /* View+MASShorthandAdditions.h in Headers */, - E76935CFF4AF327F8D9A7C1935F7D900 /* ViewController+MASAdditions.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 30507E6E56EE9983B55BBEBE33BEA90A /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 560C9C53134D5D23E6224C71AAC09371 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 57AE9C0FF97670789648FCFFCF23A28F /* YYCache.h in Headers */, - 8F136A8285B1AA9501C02EBE717D9749 /* YYDiskCache.h in Headers */, - 9AE51F7A10F7D2A41DB5AE00A230DEA2 /* YYKVStorage.h in Headers */, - 0BD4E21F29F34FB17265C7BD9887C84D /* YYMemoryCache.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 768078E15AA23B4B19A2C12FF46E415D /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 0B8E7DAF6EF79317C606AAF3BDF1B166 /* NSObject+YYModel.h in Headers */, - F654313B55A14132792476E2B2FA2AE2 /* YYClassInfo.h in Headers */, - CC46255DAABC498A35F70078C1A566BD /* YYModel.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 80C7C99747850DB02131F97B959FADB0 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 6DA9CE75744CD9CAD2A497743A002CB3 /* _YYWebImageSetter.h in Headers */, - D98126521560BEA4D6CB57439643C89E /* CALayer+YYWebImage.h in Headers */, - 7DC9EA1A80CD849FA3A67BB8813C16F1 /* MKAnnotationView+YYWebImage.h in Headers */, - 639230154DADB35273109F737BA51C7D /* UIButton+YYWebImage.h in Headers */, - FA31F4C6D96B604EEB4BF55DEF7087C8 /* UIImage+YYWebImage.h in Headers */, - 410F226804ABA48DDADFB2C40CDBDF90 /* UIImageView+YYWebImage.h in Headers */, - 72492130AA1799D5BE6B9446C7836BD7 /* YYImageCache.h in Headers */, - 4720A768E07B694895699C1A455D433B /* YYWebImage.h in Headers */, - FA0845E169D8DC9A8096C6DB7BD71C75 /* YYWebImageManager.h in Headers */, - 5D6023B887E0BCB76115B617532A5390 /* YYWebImageOperation.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - DAE5F9D13DD8EFD05CAF6E589EDC8C23 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - D5FC0D8E4622A03DA9AD9C7D2FD993E1 /* YYAnimatedImageView.h in Headers */, - C249EDF7D50D5A7BEA1C40AABCE51E7D /* YYFrameImage.h in Headers */, - 6B18BAD834E408DE82E33DB82DD63168 /* YYImage.h in Headers */, - 0D257609B3B75A4CBFFBD05133D61391 /* YYImageCoder.h in Headers */, - 3B055578547C840E193F2BCB94BF4C02 /* YYSpriteSheetImage.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - F69A1D7D9933B5C2BFB41B06C24EC219 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - C564C8D042998164475E13AD54B0A294 /* MBProgressHUD.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 488E8C830C5A5694EE916251B9ADAADA /* YYWebImage */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3F177AA52C1CC43535F1A9DCF3B78737 /* Build configuration list for PBXNativeTarget "YYWebImage" */; - buildPhases = ( - 80C7C99747850DB02131F97B959FADB0 /* Headers */, - 497AEDBF5B0106E2A52E8E23D0174346 /* Sources */, - CE2E267127242299A42286A0A8D5DA27 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - D1104BEDA54FA285BE2839DED718F805 /* PBXTargetDependency */, - 1FC26DA76AAA17813ECD410079A19A5B /* PBXTargetDependency */, - ); - name = YYWebImage; - productName = YYWebImage; - productReference = 4FC1978206616CE319648B302B05AA8A /* libYYWebImage.a */; - productType = "com.apple.product-type.library.static"; - }; - 55AF53E6C77A10ED4985E04D74A8878E /* Masonry */ = { - isa = PBXNativeTarget; - buildConfigurationList = 0B9F7EAACDDA564EC328F53A4AB8CF85 /* Build configuration list for PBXNativeTarget "Masonry" */; - buildPhases = ( - 2697A8D6B2989B073B236F7B4BF67F30 /* Headers */, - 8C28688BF2BD730285E2F5DE30F8C021 /* Sources */, - 01095FBE532CF5AA0855A20BDA54BF0B /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Masonry; - productName = Masonry; - productReference = 1FFED36A657123030ABB700256D73F15 /* libMasonry.a */; - productType = "com.apple.product-type.library.static"; - }; - 614A938FC334CABC61438FB14592FCEE /* Pods-DarkMode */ = { - isa = PBXNativeTarget; - buildConfigurationList = 8C17BE03124A4FF652DA36FB95BCEFD3 /* Build configuration list for PBXNativeTarget "Pods-DarkMode" */; - buildPhases = ( - 30507E6E56EE9983B55BBEBE33BEA90A /* Headers */, - 6D7D6FBD36BACF23BD0601611C1ED139 /* Sources */, - 24D3BE854C4E97B4CB4F4B6AEB3DDA1C /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 1D8CCC89F051C17D14E3B38FC8B47808 /* PBXTargetDependency */, - 19F4913477DF26E22CE907F59DE01F7C /* PBXTargetDependency */, - 2A49221EA0E5571525EE3FC82BF5E3A9 /* PBXTargetDependency */, - 61F8A9F2C5108EA5AC01D0AC156FD910 /* PBXTargetDependency */, - 0DB5F8867746B672CEAD27163C3A794E /* PBXTargetDependency */, - 5CD3D5F636E39C63FEABB144679F396F /* PBXTargetDependency */, - 22BFB162E190FA1451BD5D0F35603F44 /* PBXTargetDependency */, - ); - name = "Pods-DarkMode"; - productName = "Pods-DarkMode"; - productReference = 0B4A1372A24E73913DC7C605E4BD9472 /* libPods-DarkMode.a */; - productType = "com.apple.product-type.library.static"; - }; - 822E44240F2922DAB12018A6B649BD19 /* YYImage */ = { - isa = PBXNativeTarget; - buildConfigurationList = 8D1AB1D2CF4C258BC2DA0CC48A1F8CE5 /* Build configuration list for PBXNativeTarget "YYImage" */; - buildPhases = ( - DAE5F9D13DD8EFD05CAF6E589EDC8C23 /* Headers */, - B0EE8786489CEC81AF58B7FA5377C830 /* Sources */, - D9C15529BA839F56CA954D83368902D8 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = YYImage; - productName = YYImage; - productReference = 0C6F4829D47D1826F47CDC4264F9F6A8 /* libYYImage.a */; - productType = "com.apple.product-type.library.static"; - }; - 82B0A41D3031FF27D78E17B0A9A46FB0 /* MBProgressHUD */ = { - isa = PBXNativeTarget; - buildConfigurationList = 20217F7F18136BEC6503B8147352D3E3 /* Build configuration list for PBXNativeTarget "MBProgressHUD" */; - buildPhases = ( - F69A1D7D9933B5C2BFB41B06C24EC219 /* Headers */, - 12490B6EBA14F6030F9CBD9575807097 /* Sources */, - DCBC7FE987FB53FBB71A9E7155D9E871 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = MBProgressHUD; - productName = MBProgressHUD; - productReference = 8B8FAB0D627B17EDE1366984278705D9 /* libMBProgressHUD.a */; - productType = "com.apple.product-type.library.static"; - }; - 84B44807A12996D487A4A591A481D6A0 /* YYModel */ = { - isa = PBXNativeTarget; - buildConfigurationList = 07475BFF49F618F9523EA1A2F1925CD1 /* Build configuration list for PBXNativeTarget "YYModel" */; - buildPhases = ( - 768078E15AA23B4B19A2C12FF46E415D /* Headers */, - 09320F3BD0AA7E1D3B07FE201411AC58 /* Sources */, - 9C058CFEB46CC50AE17D1503E2EA34E9 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = YYModel; - productName = YYModel; - productReference = E460D5B0416D36F66EE8EC89E5D2FA0A /* libYYModel.a */; - productType = "com.apple.product-type.library.static"; - }; - CFDAE6EB02F58B9A37CADCF439AE6082 /* YYCache */ = { - isa = PBXNativeTarget; - buildConfigurationList = DF4E826F9DA37765B10F3D1B0EC4F9B2 /* Build configuration list for PBXNativeTarget "YYCache" */; - buildPhases = ( - 560C9C53134D5D23E6224C71AAC09371 /* Headers */, - 1414B7ACE73195D9F0670A0752E84BDD /* Sources */, - 7E1F0A9AFCFD750D8D8E87867B919530 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = YYCache; - productName = YYCache; - productReference = 48ACF38225AF5129416A1F090F6D3286 /* libYYCache.a */; - productType = "com.apple.product-type.library.static"; - }; - DB13B1641D72A72D8C9AE53FF81C8950 /* GPUImage */ = { - isa = PBXNativeTarget; - buildConfigurationList = E9E74E2AD7CA08D9840C4895CF07BBC1 /* Build configuration list for PBXNativeTarget "GPUImage" */; - buildPhases = ( - 1AF60014033E7281EAFAD4E7CD034ABA /* Headers */, - 456CAEA58DC1F88341774A3E1FEDD0C6 /* Sources */, - 3AA66CA5E57F3C1415A7D61A13C42528 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = GPUImage; - productName = GPUImage; - productReference = 79E8CB24F46AA9A51F87BBDF2D0AC238 /* libGPUImage.a */; - productType = "com.apple.product-type.library.static"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - BFDFE7DC352907FC980B868725387E98 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 1100; - LastUpgradeCheck = 1100; - }; - buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; - compatibilityVersion = "Xcode 10.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = CF1408CF629C7361332E53B88F7BD30C; - productRefGroup = 992A970CDF3E62FE974C2FB731009A04 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - DB13B1641D72A72D8C9AE53FF81C8950 /* GPUImage */, - 55AF53E6C77A10ED4985E04D74A8878E /* Masonry */, - 82B0A41D3031FF27D78E17B0A9A46FB0 /* MBProgressHUD */, - 614A938FC334CABC61438FB14592FCEE /* Pods-DarkMode */, - CFDAE6EB02F58B9A37CADCF439AE6082 /* YYCache */, - 822E44240F2922DAB12018A6B649BD19 /* YYImage */, - 84B44807A12996D487A4A591A481D6A0 /* YYModel */, - 488E8C830C5A5694EE916251B9ADAADA /* YYWebImage */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - 09320F3BD0AA7E1D3B07FE201411AC58 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 332F47F53E6998F86527587E29CA5D9E /* NSObject+YYModel.m in Sources */, - E2F119888DA6312834DB6A2E84FF5906 /* YYClassInfo.m in Sources */, - 06EB7CC11A03D75FD2DA07D284685F73 /* YYModel-dummy.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 12490B6EBA14F6030F9CBD9575807097 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - C7FD66D3D320095B45AD9D39EF1B858B /* MBProgressHUD-dummy.m in Sources */, - D6438BA4F863AE0A7891F212EE3C06D0 /* MBProgressHUD.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1414B7ACE73195D9F0670A0752E84BDD /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0AAAED8B75B6AD69452465FD9596FD0D /* YYCache-dummy.m in Sources */, - 2C41DD251C08A607AB0D65FD88E3A066 /* YYCache.m in Sources */, - 472C8A534A872D0B6D85286483E6D753 /* YYDiskCache.m in Sources */, - 0B6FE241DFB3843F412B6468A8F4D2E2 /* YYKVStorage.m in Sources */, - 4D71EEBCF009BD38CDBDCB7FF48E9D3D /* YYMemoryCache.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 456CAEA58DC1F88341774A3E1FEDD0C6 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 86BA3E6F0F738FB8D5FA5E4F469C8694 /* GLProgram.m in Sources */, - 7F834C5C649E322048D41F16488A8520 /* GPUImage-dummy.m in Sources */, - C7710525EC84D4EB1FAF4D571DB64D90 /* GPUImage3x3ConvolutionFilter.m in Sources */, - 7BBADDA4A51EDD4DB7B9178A2AD9B6F0 /* GPUImage3x3TextureSamplingFilter.m in Sources */, - 0DFAF263663A062127902C54C6983A09 /* GPUImageAdaptiveThresholdFilter.m in Sources */, - 17EF299F850C9C8628F34469C37013DD /* GPUImageAddBlendFilter.m in Sources */, - 3B7BB04082AF2620E265A3088B2B4D0D /* GPUImageAlphaBlendFilter.m in Sources */, - 701EB7C0B4375EE2BF4F17FDDA91C3D7 /* GPUImageAmatorkaFilter.m in Sources */, - 54C308204D830A23ADC5E7E77F11FAD9 /* GPUImageAverageColor.m in Sources */, - 18A409862FE2BD9E7AEB7F8C443A2EEA /* GPUImageAverageLuminanceThresholdFilter.m in Sources */, - 01DA5C61D7BA40621EC5460EED38200E /* GPUImageBilateralFilter.m in Sources */, - 11E619FEA09D4BF81ACE5C2921D00B19 /* GPUImageBoxBlurFilter.m in Sources */, - BF4117E228B603963206D603A99B6CB0 /* GPUImageBrightnessFilter.m in Sources */, - 3477F92624D8C9133F3041A79491FA59 /* GPUImageBuffer.m in Sources */, - 3E63B4119CD44378A1093476E54E2474 /* GPUImageBulgeDistortionFilter.m in Sources */, - 7FB5C3196DB87FB6E92DABE225494BDC /* GPUImageCannyEdgeDetectionFilter.m in Sources */, - ED6CA2C4FFF084A9C6BC0C3058F2FC0E /* GPUImageCGAColorspaceFilter.m in Sources */, - C3D1B9C0AB90607D224B2440ADDDBF7D /* GPUImageChromaKeyBlendFilter.m in Sources */, - 1860650813D77F0191C8979285AEFC40 /* GPUImageChromaKeyFilter.m in Sources */, - C36D1358DE52DDFE9561872046B15CDA /* GPUImageClosingFilter.m in Sources */, - C8533435ED95323AD49B5ABA46309592 /* GPUImageColorBlendFilter.m in Sources */, - 2F71447BF395AFE0424A0173E1D3941B /* GPUImageColorBurnBlendFilter.m in Sources */, - 68BCD2A517C5CB6DF61FE1187DD63266 /* GPUImageColorDodgeBlendFilter.m in Sources */, - 8DF2798CBFBF2B27970A065636E5350C /* GPUImageColorInvertFilter.m in Sources */, - C1819B0277FEA363D59F734D9AD8AA4B /* GPUImageColorMatrixFilter.m in Sources */, - B129AF9904B49BDEBFA2CBE15CD8C832 /* GPUImageColorPackingFilter.m in Sources */, - 60CBB436C809283781907EA30C935F35 /* GPUImageContext.m in Sources */, - 93A3C001CF21FF9A011DBE76D08E6FD9 /* GPUImageContrastFilter.m in Sources */, - ED1F02433F3A912D677F43E1FF11A86D /* GPUImageCropFilter.m in Sources */, - 8E75885AC38F2FD27A93B5365669B7D1 /* GPUImageCrosshairGenerator.m in Sources */, - B8DBBA903BF381C26A07E80FB3B673F2 /* GPUImageCrosshatchFilter.m in Sources */, - 8230F51E5396B2EA356525E246B13E65 /* GPUImageDarkenBlendFilter.m in Sources */, - 4F9FCCD41B5DB358F6471868A7AF0FF8 /* GPUImageDifferenceBlendFilter.m in Sources */, - 90A044FA9883FAB9D1BC675A7BCCAD39 /* GPUImageDilationFilter.m in Sources */, - C0CE23B393799A65CB7626FED30D8B87 /* GPUImageDirectionalNonMaximumSuppressionFilter.m in Sources */, - E584CF8B9CA73334B373D6AEC20870CF /* GPUImageDirectionalSobelEdgeDetectionFilter.m in Sources */, - 694F36DE0A2C6B75B53CA842A09C450C /* GPUImageDissolveBlendFilter.m in Sources */, - 180A83B65E6DDB6EB746870CF41325A1 /* GPUImageDivideBlendFilter.m in Sources */, - B16B792802266C47B1C05A7938DB2FDD /* GPUImageEmbossFilter.m in Sources */, - 72DDDD2224AE6BE60BA942D9CF3856DF /* GPUImageErosionFilter.m in Sources */, - F240CA1217BACD2BA4C0B0EB15F62EF8 /* GPUImageExclusionBlendFilter.m in Sources */, - 43392130FF1BA22BCD40F201F94DF7C0 /* GPUImageExposureFilter.m in Sources */, - AC6FF619E5FDA1335F97C3C9E4C4276B /* GPUImageFalseColorFilter.m in Sources */, - 82844D6EFDF6891200BBCD3A4C9C54AB /* GPUImageFASTCornerDetectionFilter.m in Sources */, - DA13233E99DAD01F4F1CF918A1828173 /* GPUImageFilter.m in Sources */, - E3FDBC252DF4EE97EF2A47F9FD299138 /* GPUImageFilterGroup.m in Sources */, - 44B2A991A256252267B769DAE2328918 /* GPUImageFilterPipeline.m in Sources */, - 5F7E38F771E8D6181B8C72C5D8C10C14 /* GPUImageFramebuffer.m in Sources */, - 5107E16FCC65F65EC492836E724F0BFE /* GPUImageFramebufferCache.m in Sources */, - BBD0DCB580B12F696F7240575892FAA2 /* GPUImageGammaFilter.m in Sources */, - 0E7080397F8B5AE0B8A3D7AF280BB094 /* GPUImageGaussianBlurFilter.m in Sources */, - DB5CD837D88F4C0A6E260922756085EB /* GPUImageGaussianBlurPositionFilter.m in Sources */, - A7208F4AAB19736637ED7314D63F7D2E /* GPUImageGaussianSelectiveBlurFilter.m in Sources */, - E8D139B563E36F0BA0C9F5B2B20C75B1 /* GPUImageGlassSphereFilter.m in Sources */, - 3A8C1A0178B01AD26430FC5B130F5E0D /* GPUImageGrayscaleFilter.m in Sources */, - 6A92349242C40DAA199A7FB7C7ACDCC1 /* GPUImageHalftoneFilter.m in Sources */, - 69FC4C251095ED7B8667F599EE032BF9 /* GPUImageHardLightBlendFilter.m in Sources */, - 032FBF65C1B7C211B28D54B160B1612D /* GPUImageHarrisCornerDetectionFilter.m in Sources */, - 969CB0062DE1F74E8011E8AD2A79DD6A /* GPUImageHazeFilter.m in Sources */, - 436BC7F553DA755100A82BA0F05483D5 /* GPUImageHighlightShadowFilter.m in Sources */, - 7CAD51A1A08B950CEBA05C4DBA95DDA4 /* GPUImageHighPassFilter.m in Sources */, - 0BB1F971030D1518F9CF319E9D4DC1AD /* GPUImageHistogramEqualizationFilter.m in Sources */, - EAAE5E8238A63B075863D7007624DA43 /* GPUImageHistogramFilter.m in Sources */, - 4FCB792F4D09A7A6EC830F3F09E57E3E /* GPUImageHistogramGenerator.m in Sources */, - 8BFFBA9AD7ADDBA5B802F107161884F1 /* GPUImageHoughTransformLineDetector.m in Sources */, - 23AE0543B10B548DC5EA894199172600 /* GPUImageHSBFilter.m in Sources */, - 2D98C578934FC343F36EE6FE89BFDB11 /* GPUImageHueBlendFilter.m in Sources */, - DC4A074004FA5271EA709589DFCBEB15 /* GPUImageHueFilter.m in Sources */, - CDE62540A3FD2D838E06A3FCAB1EE58E /* GPUImageiOSBlurFilter.m in Sources */, - F2FD414ADEF65434E578A08DF0676F0D /* GPUImageJFAVoronoiFilter.m in Sources */, - A853401FDAA9E7088AD5028D09787374 /* GPUImageKuwaharaFilter.m in Sources */, - 87AF8CBBDCBB0C50612AB69D6D742742 /* GPUImageKuwaharaRadius3Filter.m in Sources */, - 3561CB57DDD73F8AFA84BF0E76ABB946 /* GPUImageLanczosResamplingFilter.m in Sources */, - F7DDEDD5401FF5E6458969FA7EC518F5 /* GPUImageLaplacianFilter.m in Sources */, - 83788DC3CB98DF8D12BB87500570D4FC /* GPUImageLevelsFilter.m in Sources */, - 8845BDFA0653F4E71762578DB183BCDB /* GPUImageLightenBlendFilter.m in Sources */, - 7CCCD7A77FF08770AD9EB67866E33E57 /* GPUImageLinearBurnBlendFilter.m in Sources */, - 47AD0E032FC7AA3EEB930742976CB88D /* GPUImageLineGenerator.m in Sources */, - 2280B1BE277126BD771028C12BD6A59E /* GPUImageLocalBinaryPatternFilter.m in Sources */, - 8CE29353E6184B70D568D3B99E94D149 /* GPUImageLookupFilter.m in Sources */, - 2A056E4E0CB5341CF83B2902850B496C /* GPUImageLowPassFilter.m in Sources */, - BC130E24128D66199EF316BA62B7FE30 /* GPUImageLuminanceRangeFilter.m in Sources */, - A834995186E9FE7D0150677B989DDD8B /* GPUImageLuminanceThresholdFilter.m in Sources */, - 6F1483002AE6E1A074656FE296A380DC /* GPUImageLuminosity.m in Sources */, - D3AF12B25881D1AAF4DE417F1D5407B9 /* GPUImageLuminosityBlendFilter.m in Sources */, - 24D5BD2976FC932DE4ADAEB93A0479F6 /* GPUImageMaskFilter.m in Sources */, - A722D1944A6F15819EA75CAC4A65CD8D /* GPUImageMedianFilter.m in Sources */, - 0319334D0B9B8B673C0BAEAC13FFE1FB /* GPUImageMissEtikateFilter.m in Sources */, - 203ECB87C9B02B1B8BAAF78D8A62A1DE /* GPUImageMonochromeFilter.m in Sources */, - 28A79E1849CD533B44B7BEFEB7E23FCD /* GPUImageMosaicFilter.m in Sources */, - 55E840167C4D134B42027183FE12AA5F /* GPUImageMotionBlurFilter.m in Sources */, - 8372234603432285BBF01ED1A21DCF08 /* GPUImageMotionDetector.m in Sources */, - 35CBA794B313B0A704877F12F8D1ABFA /* GPUImageMovie.m in Sources */, - 4BA1A0406DD78FE4D11CF77A531CF5C3 /* GPUImageMovieComposition.m in Sources */, - AB11AF112E43D1FF1522A8844564CD74 /* GPUImageMovieWriter.m in Sources */, - 8FA19489C4BAAB00154C1E14F0692F3E /* GPUImageMultiplyBlendFilter.m in Sources */, - EB0DC31314035D14CF7D560816C5820A /* GPUImageNobleCornerDetectionFilter.m in Sources */, - C465BDCDDAD3B3CD57F1C64294A1533A /* GPUImageNonMaximumSuppressionFilter.m in Sources */, - 958FD4275823EA710C09035D28BC5BB6 /* GPUImageNormalBlendFilter.m in Sources */, - C0F421E2359654EEC935728ECFE098C8 /* GPUImageOpacityFilter.m in Sources */, - 76C328BA20BD9A30ECE8FC13577088CC /* GPUImageOpeningFilter.m in Sources */, - 8087873FCF7C582C567FBC9E7866FC00 /* GPUImageOutput.m in Sources */, - FC4B8B12DE32CC742444EC57C78E43BB /* GPUImageOverlayBlendFilter.m in Sources */, - 1EE8655B7099DFDF91AB09854A782014 /* GPUImageParallelCoordinateLineTransformFilter.m in Sources */, - 00986AC306A77F203295619535AF853F /* GPUImagePerlinNoiseFilter.m in Sources */, - 36C40AACF03A24A362EB39C429249959 /* GPUImagePicture+TextureSubimage.m in Sources */, - 67EE0DDBEB2517F5B04D04B93226A9BC /* GPUImagePicture.m in Sources */, - 16BEA757C13C39AF5F5FCDB143AF53A9 /* GPUImagePinchDistortionFilter.m in Sources */, - C38CB6D5CA3A24003E2314F3ED91BBA8 /* GPUImagePixellateFilter.m in Sources */, - DCDB85FBCE034BD943E4CAD37FE90B79 /* GPUImagePixellatePositionFilter.m in Sources */, - C90957CDE1F88C80D792F3CCBBBD86E7 /* GPUImagePoissonBlendFilter.m in Sources */, - 6FFCB41E003AD80298DCDC27CBD24248 /* GPUImagePolarPixellateFilter.m in Sources */, - 097C32010AB76B1FE9C162A2A1876ECE /* GPUImagePolkaDotFilter.m in Sources */, - A25BA1791E1B279225964FA5CB18271B /* GPUImagePosterizeFilter.m in Sources */, - 53C1EE743E9410FE7276FA94A236289F /* GPUImagePrewittEdgeDetectionFilter.m in Sources */, - 01C95E537574ABC59799352D0AD70028 /* GPUImageRawDataInput.m in Sources */, - 05C61347A8543E701B094D915BD5C838 /* GPUImageRawDataOutput.m in Sources */, - 19436D75D39F5FEC5CFC10989E8D21E7 /* GPUImageRGBClosingFilter.m in Sources */, - 75F2628186AF80E8B6B39E6A27F104A6 /* GPUImageRGBDilationFilter.m in Sources */, - 5934E71FD7CE977980F1F3E0FBB0589D /* GPUImageRGBErosionFilter.m in Sources */, - E9129B8F2C4716BB0E04A8AA7DF489ED /* GPUImageRGBFilter.m in Sources */, - 20E327AE2E71D49D773CD130992DCE16 /* GPUImageRGBOpeningFilter.m in Sources */, - EA2FCF7789C782BE597B4A462E5AC8D7 /* GPUImageSaturationBlendFilter.m in Sources */, - D90E2B61D12B3135282EC3264A4B6699 /* GPUImageSaturationFilter.m in Sources */, - F8A9EC123F285CCB4262D7419CB2F813 /* GPUImageScreenBlendFilter.m in Sources */, - 2AD9C4FEB3BDBD7AFABEFC1D2D16A04C /* GPUImageSepiaFilter.m in Sources */, - 7FA724745C6C17A6466F449C11EC81E9 /* GPUImageSharpenFilter.m in Sources */, - F06B38D5B6F52BE9B44E382F020D6B31 /* GPUImageShiTomasiFeatureDetectionFilter.m in Sources */, - F40E6B5DD24C45C5E16A11F8CB40482C /* GPUImageSingleComponentGaussianBlurFilter.m in Sources */, - CDCBBC093C8294D84332E954BD1A80E4 /* GPUImageSketchFilter.m in Sources */, - 463C05A520F9F187AA59A4532ED2DC98 /* GPUImageSmoothToonFilter.m in Sources */, - 19E2053A876C0F6A156C00BC10116E4B /* GPUImageSobelEdgeDetectionFilter.m in Sources */, - 5C176EB69346C558230FA62C8FF9445C /* GPUImageSoftEleganceFilter.m in Sources */, - 31D6CA90C42E5C93B586480348B000A3 /* GPUImageSoftLightBlendFilter.m in Sources */, - FD06FC7B591A78FD113F2D10FC51592E /* GPUImageSolidColorGenerator.m in Sources */, - AA3AEE471C21B1B2381CAAEA54557674 /* GPUImageSourceOverBlendFilter.m in Sources */, - 468E8582953579A3237E9B07A4290809 /* GPUImageSphereRefractionFilter.m in Sources */, - 35CB55CABE07087AB199A17790384536 /* GPUImageStillCamera.m in Sources */, - 8F87A31C7C5DCF2BFC9E7A9A9831DE3F /* GPUImageStretchDistortionFilter.m in Sources */, - 8A5D33655584772DCD0CF3C4EECCE0BA /* GPUImageSubtractBlendFilter.m in Sources */, - 75345833F7677B391F6B3AA4468CEA21 /* GPUImageSwirlFilter.m in Sources */, - FD3EAC5E0A791E73E27E422A197381BE /* GPUImageTextureInput.m in Sources */, - 0AEA27BF85DB689C14FB34D0FEBDB851 /* GPUImageTextureOutput.m in Sources */, - BE93BA2DA12D718619AAA3F8216D29F4 /* GPUImageThreeInputFilter.m in Sources */, - CC997265C47D1D37F34774F5E59DFCA2 /* GPUImageThresholdEdgeDetectionFilter.m in Sources */, - E73E4ED481B67985D7794448CA5DE53A /* GPUImageThresholdedNonMaximumSuppressionFilter.m in Sources */, - 942B26BBAD3D8D03EE64EADAA91984F4 /* GPUImageThresholdSketchFilter.m in Sources */, - 394A129E507245FF105966F376AB1C41 /* GPUImageTiltShiftFilter.m in Sources */, - 0CE8DDB17A7E7660B35605B8139FE3B3 /* GPUImageToneCurveFilter.m in Sources */, - 8194C101551A2584D8E3344E0FABD8F7 /* GPUImageToonFilter.m in Sources */, - D9EBD120B2572956219EB5E69C9987DB /* GPUImageTransformFilter.m in Sources */, - 3726AB2B00A42F73A0124907B9ACC3A9 /* GPUImageTwoInputCrossTextureSamplingFilter.m in Sources */, - 6AABC70C8EF035909F5A2D3DC6B5FA4A /* GPUImageTwoInputFilter.m in Sources */, - 7385628E7B625A9614D3044DE5AC3385 /* GPUImageTwoPassFilter.m in Sources */, - D5A4349BFFC852AA31E14DFB14A47976 /* GPUImageTwoPassTextureSamplingFilter.m in Sources */, - D0D36AA4AD8C0D0B5D667B37FE3F9EF2 /* GPUImageUIElement.m in Sources */, - A10B6F1BD9FC2A0A3BD16B0CA7951F83 /* GPUImageUnsharpMaskFilter.m in Sources */, - CBC2808292742C287F16EC38D82C57EB /* GPUImageVideoCamera.m in Sources */, - CE8EAEC4550BF203A6D4A25FB8FF772F /* GPUImageView.m in Sources */, - 4478C2AC2D38DD361F0F23A0C5B79C41 /* GPUImageVignetteFilter.m in Sources */, - D9742F495FB317A0EDED886CDEC37049 /* GPUImageVoronoiConsumerFilter.m in Sources */, - 16B07BF8A572D2B926D42CEB9A6491ED /* GPUImageWeakPixelInclusionFilter.m in Sources */, - 2702708CF3F7B8F8C71CD04CE0E0407B /* GPUImageWhiteBalanceFilter.m in Sources */, - 89360CB1E03A04FD4E4E35444535B5CB /* GPUImageXYDerivativeFilter.m in Sources */, - 39A315F02A4702D5670CB93A5C9BEEEA /* GPUImageZoomBlurFilter.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 497AEDBF5B0106E2A52E8E23D0174346 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - CA07E0D65A9F569E68A647D3A422C028 /* _YYWebImageSetter.m in Sources */, - 2607BC411D43A5440E53234F8AB482C8 /* CALayer+YYWebImage.m in Sources */, - 6BA2489921F50583559CC1BB13DB8B42 /* MKAnnotationView+YYWebImage.m in Sources */, - B893623350B4E001365E48E0AC5D1F91 /* UIButton+YYWebImage.m in Sources */, - FB62EF85A3768A158924A4FB8D21E7E4 /* UIImage+YYWebImage.m in Sources */, - F961EFDD9E3144F2F28EF4702C201F0A /* UIImageView+YYWebImage.m in Sources */, - FFB553681052A094EA7516D46F2A8C9C /* YYImageCache.m in Sources */, - A2EA584895A489FC00301707BF956355 /* YYWebImage-dummy.m in Sources */, - B80DB3332DCA3B96D6208277A30E39F1 /* YYWebImageManager.m in Sources */, - 0172B10DE456AE5736FD887F0CEB74AF /* YYWebImageOperation.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 6D7D6FBD36BACF23BD0601611C1ED139 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - C33E9361A533400A28DEE54586144691 /* Pods-DarkMode-dummy.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 8C28688BF2BD730285E2F5DE30F8C021 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 63F87C318437740E8202E4D3DD0826FA /* MASCompositeConstraint.m in Sources */, - EE936A6838005A5ED1BC5F74BE37B7BD /* MASConstraint.m in Sources */, - 1E5D56FF58658F9F45723CA2940489EE /* MASConstraintMaker.m in Sources */, - 0096B5A8BA8E4F2BFD8839D0FE7CD696 /* MASLayoutConstraint.m in Sources */, - D72EE0E749232B2C899702FC1C9402BB /* Masonry-dummy.m in Sources */, - A893FFB0F9137E298D6752729850D1D6 /* MASViewAttribute.m in Sources */, - 572D05B146EAA3EF5530A0D0E34904A0 /* MASViewConstraint.m in Sources */, - B946AFB1A725D85E07F645A7EF086383 /* NSArray+MASAdditions.m in Sources */, - 59EA578EED8BAC126FDC60C32AE11521 /* NSLayoutConstraint+MASDebugAdditions.m in Sources */, - C7920681F0164686C56327ED3C6AAC58 /* View+MASAdditions.m in Sources */, - C05FC6699632FE712174ED875A605410 /* ViewController+MASAdditions.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B0EE8786489CEC81AF58B7FA5377C830 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 596D6C47B56C81DAAF4AEFD6EBE90E4E /* YYAnimatedImageView.m in Sources */, - 83A21AF2AA24EC617540C8FBDADA56CF /* YYFrameImage.m in Sources */, - 54A44219E060C802B200A9A82B8F403C /* YYImage-dummy.m in Sources */, - 1646382FCB4B9AE1130EC8ACEDA90598 /* YYImage.m in Sources */, - 443DCC9EACB122059801B326E959DD2D /* YYImageCoder.m in Sources */, - 7A67C46F6E32AA2E17FC8CC92649971D /* YYSpriteSheetImage.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 0DB5F8867746B672CEAD27163C3A794E /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = YYImage; - target = 822E44240F2922DAB12018A6B649BD19 /* YYImage */; - targetProxy = 65906679C3DF4C10CE5279E1C83FA340 /* PBXContainerItemProxy */; - }; - 19F4913477DF26E22CE907F59DE01F7C /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = MBProgressHUD; - target = 82B0A41D3031FF27D78E17B0A9A46FB0 /* MBProgressHUD */; - targetProxy = E2F7E2998162B148B91D328B73DF9F38 /* PBXContainerItemProxy */; - }; - 1D8CCC89F051C17D14E3B38FC8B47808 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = GPUImage; - target = DB13B1641D72A72D8C9AE53FF81C8950 /* GPUImage */; - targetProxy = 5BB5B7F8294D2A559BA5BED33BAE2C7B /* PBXContainerItemProxy */; - }; - 1FC26DA76AAA17813ECD410079A19A5B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = YYImage; - target = 822E44240F2922DAB12018A6B649BD19 /* YYImage */; - targetProxy = 6E7A69E1F8BD32917A845DD8C233CA82 /* PBXContainerItemProxy */; - }; - 22BFB162E190FA1451BD5D0F35603F44 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = YYWebImage; - target = 488E8C830C5A5694EE916251B9ADAADA /* YYWebImage */; - targetProxy = 11065683D1DF6005F9525BBA539466D7 /* PBXContainerItemProxy */; - }; - 2A49221EA0E5571525EE3FC82BF5E3A9 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Masonry; - target = 55AF53E6C77A10ED4985E04D74A8878E /* Masonry */; - targetProxy = 817CD8DC71FA3B7C4B131536ECA0F1D0 /* PBXContainerItemProxy */; - }; - 5CD3D5F636E39C63FEABB144679F396F /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = YYModel; - target = 84B44807A12996D487A4A591A481D6A0 /* YYModel */; - targetProxy = AAC877F66336AAF9D915F41F63451BF2 /* PBXContainerItemProxy */; - }; - 61F8A9F2C5108EA5AC01D0AC156FD910 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = YYCache; - target = CFDAE6EB02F58B9A37CADCF439AE6082 /* YYCache */; - targetProxy = 0E525382322D144157FE54A2F8279ED0 /* PBXContainerItemProxy */; - }; - D1104BEDA54FA285BE2839DED718F805 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = YYCache; - target = CFDAE6EB02F58B9A37CADCF439AE6082 /* YYCache */; - targetProxy = 41577B33D18B0277BCC25CF6A140DEDD /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 0C8033609421B8522D89050AB6716743 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = D91BF331AAA5E77D9BEDA9C6D40DD41E /* MBProgressHUD.release.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - GCC_PREFIX_HEADER = "Target Support Files/MBProgressHUD/MBProgressHUD-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_MODULE_NAME = MBProgressHUD; - PRODUCT_NAME = MBProgressHUD; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 110F69768B51A32FCF8FB258C2035420 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = E388169E7433BC6A1E766BB6E2C53605 /* MBProgressHUD.debug.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - GCC_PREFIX_HEADER = "Target Support Files/MBProgressHUD/MBProgressHUD-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_MODULE_NAME = MBProgressHUD; - PRODUCT_NAME = MBProgressHUD; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 196DFA3E4A09A28224918543529A1885 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_DEBUG=1", - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - STRIP_INSTALLED_PRODUCT = NO; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - SYMROOT = "${SRCROOT}/../build"; - }; - name = Debug; - }; - 1D61CD432BA357545CE20DC1DD4F212A /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 446D6F21C19F21359994D8C61A378A84 /* YYImage.release.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - GCC_PREFIX_HEADER = "Target Support Files/YYImage/YYImage-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_MODULE_NAME = YYImage; - PRODUCT_NAME = YYImage; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 422D381F3D66E68EA4A8140685BA919C /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 16C4DC343FBAC71D13FF4FA9BCE10709 /* Pods-DarkMode.debug.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - MACH_O_TYPE = staticlib; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 48320E0430104EE330CB43EB638D8EFC /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 5DA7010E9B001189E58C1D4FAF928DF7 /* YYCache.debug.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - GCC_PREFIX_HEADER = "Target Support Files/YYCache/YYCache-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_MODULE_NAME = YYCache; - PRODUCT_NAME = YYCache; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 60212691106A7430DFE5F00513842211 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 4713F7EF42A07902267E6A57EBC07D50 /* YYCache.release.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - GCC_PREFIX_HEADER = "Target Support Files/YYCache/YYCache-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_MODULE_NAME = YYCache; - PRODUCT_NAME = YYCache; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 8AEEA5CC30001CB70A788717A32DBAB7 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 3FFF18D3BD6B92729084311D3FD98998 /* Masonry.release.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - GCC_PREFIX_HEADER = "Target Support Files/Masonry/Masonry-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_MODULE_NAME = Masonry; - PRODUCT_NAME = Masonry; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 97EDEBBA2A6FA148475697D9A7553A29 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 5F8F677D95958C9F3D7EA1F6761CD291 /* YYImage.debug.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - GCC_PREFIX_HEADER = "Target Support Files/YYImage/YYImage-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_MODULE_NAME = YYImage; - PRODUCT_NAME = YYImage; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - B01D14FDC83DCF9D4BE53066BEA96D05 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_RELEASE=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - STRIP_INSTALLED_PRODUCT = NO; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 5.0; - SYMROOT = "${SRCROOT}/../build"; - }; - name = Release; - }; - B1F46ABE2AE6830CD7251657FBB06711 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 5278FBF2D16D0E9492F81D50E1B4E389 /* GPUImage.debug.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - GCC_PREFIX_HEADER = "Target Support Files/GPUImage/GPUImage-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 5.0; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_MODULE_NAME = GPUImage; - PRODUCT_NAME = GPUImage; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - DCCA02CF7503BD7258D5F7FF1C813190 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = CA6014EF6AE8930707D68E71ECA55D13 /* Pods-DarkMode.release.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - MACH_O_TYPE = staticlib; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - E2FADAB2C8188790937CE35BD9000F26 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = FC1BB8206A536BE18D03949E8E9E8D59 /* YYModel.release.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - GCC_PREFIX_HEADER = "Target Support Files/YYModel/YYModel-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_MODULE_NAME = YYModel; - PRODUCT_NAME = YYModel; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - E7A52D7D06FF60DB10CBC15785828BFA /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = BE1BD7513325F0024AB5F0B2AA5B5308 /* YYModel.debug.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - GCC_PREFIX_HEADER = "Target Support Files/YYModel/YYModel-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_MODULE_NAME = YYModel; - PRODUCT_NAME = YYModel; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - EF692C7BD110D4D561D132828EA67F5A /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 5AF9D53BF78794179DA5A171FD200059 /* YYWebImage.debug.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - GCC_PREFIX_HEADER = "Target Support Files/YYWebImage/YYWebImage-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_MODULE_NAME = YYWebImage; - PRODUCT_NAME = YYWebImage; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - EFB35AA5E69F3509E6056504B3FDC11A /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = CC511945A3B6F15907655303FBD595CC /* YYWebImage.release.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - GCC_PREFIX_HEADER = "Target Support Files/YYWebImage/YYWebImage-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_MODULE_NAME = YYWebImage; - PRODUCT_NAME = YYWebImage; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - F04C5B8FBC233D0EC8789CF3767459DD /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 504C0F55ECD0EE366A432BE3CAF79E1F /* GPUImage.release.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - GCC_PREFIX_HEADER = "Target Support Files/GPUImage/GPUImage-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 5.0; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_MODULE_NAME = GPUImage; - PRODUCT_NAME = GPUImage; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - F99870D874C7FA838E84D9C55C010CF1 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = FF365ED840058D960082D2B982FA9D49 /* Masonry.debug.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - GCC_PREFIX_HEADER = "Target Support Files/Masonry/Masonry-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_MODULE_NAME = Masonry; - PRODUCT_NAME = Masonry; - PUBLIC_HEADERS_FOLDER_PATH = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 07475BFF49F618F9523EA1A2F1925CD1 /* Build configuration list for PBXNativeTarget "YYModel" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - E7A52D7D06FF60DB10CBC15785828BFA /* Debug */, - E2FADAB2C8188790937CE35BD9000F26 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 0B9F7EAACDDA564EC328F53A4AB8CF85 /* Build configuration list for PBXNativeTarget "Masonry" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - F99870D874C7FA838E84D9C55C010CF1 /* Debug */, - 8AEEA5CC30001CB70A788717A32DBAB7 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 20217F7F18136BEC6503B8147352D3E3 /* Build configuration list for PBXNativeTarget "MBProgressHUD" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 110F69768B51A32FCF8FB258C2035420 /* Debug */, - 0C8033609421B8522D89050AB6716743 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3F177AA52C1CC43535F1A9DCF3B78737 /* Build configuration list for PBXNativeTarget "YYWebImage" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - EF692C7BD110D4D561D132828EA67F5A /* Debug */, - EFB35AA5E69F3509E6056504B3FDC11A /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 196DFA3E4A09A28224918543529A1885 /* Debug */, - B01D14FDC83DCF9D4BE53066BEA96D05 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 8C17BE03124A4FF652DA36FB95BCEFD3 /* Build configuration list for PBXNativeTarget "Pods-DarkMode" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 422D381F3D66E68EA4A8140685BA919C /* Debug */, - DCCA02CF7503BD7258D5F7FF1C813190 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 8D1AB1D2CF4C258BC2DA0CC48A1F8CE5 /* Build configuration list for PBXNativeTarget "YYImage" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97EDEBBA2A6FA148475697D9A7553A29 /* Debug */, - 1D61CD432BA357545CE20DC1DD4F212A /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - DF4E826F9DA37765B10F3D1B0EC4F9B2 /* Build configuration list for PBXNativeTarget "YYCache" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 48320E0430104EE330CB43EB638D8EFC /* Debug */, - 60212691106A7430DFE5F00513842211 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - E9E74E2AD7CA08D9840C4895CF07BBC1 /* Build configuration list for PBXNativeTarget "GPUImage" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - B1F46ABE2AE6830CD7251657FBB06711 /* Debug */, - F04C5B8FBC233D0EC8789CF3767459DD /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = BFDFE7DC352907FC980B868725387E98 /* Project object */; -} diff --git a/iOS_Tips/Pods/Target Support Files/FBRetainCycleDetector/FBRetainCycleDetector-dummy.m b/iOS_Tips/Pods/Target Support Files/FBRetainCycleDetector/FBRetainCycleDetector-dummy.m deleted file mode 100644 index a9532e12..00000000 --- a/iOS_Tips/Pods/Target Support Files/FBRetainCycleDetector/FBRetainCycleDetector-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_FBRetainCycleDetector : NSObject -@end -@implementation PodsDummy_FBRetainCycleDetector -@end diff --git a/iOS_Tips/Pods/Target Support Files/FBRetainCycleDetector/FBRetainCycleDetector-prefix.pch b/iOS_Tips/Pods/Target Support Files/FBRetainCycleDetector/FBRetainCycleDetector-prefix.pch deleted file mode 100644 index beb2a244..00000000 --- a/iOS_Tips/Pods/Target Support Files/FBRetainCycleDetector/FBRetainCycleDetector-prefix.pch +++ /dev/null @@ -1,12 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - diff --git a/iOS_Tips/Pods/Target Support Files/FBRetainCycleDetector/FBRetainCycleDetector.xcconfig b/iOS_Tips/Pods/Target Support Files/FBRetainCycleDetector/FBRetainCycleDetector.xcconfig deleted file mode 100644 index f3b8c001..00000000 --- a/iOS_Tips/Pods/Target Support Files/FBRetainCycleDetector/FBRetainCycleDetector.xcconfig +++ /dev/null @@ -1,10 +0,0 @@ -CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FBRetainCycleDetector -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/FBRetainCycleDetector" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/FBRetainCycleDetector" -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PODS_TARGET_SRCROOT = ${PODS_ROOT}/FBRetainCycleDetector -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/iOS_Tips/Pods/Target Support Files/GPUImage/GPUImage-dummy.m b/iOS_Tips/Pods/Target Support Files/GPUImage/GPUImage-dummy.m deleted file mode 100644 index 92f4a7d4..00000000 --- a/iOS_Tips/Pods/Target Support Files/GPUImage/GPUImage-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_GPUImage : NSObject -@end -@implementation PodsDummy_GPUImage -@end diff --git a/iOS_Tips/Pods/Target Support Files/GPUImage/GPUImage-prefix.pch b/iOS_Tips/Pods/Target Support Files/GPUImage/GPUImage-prefix.pch deleted file mode 100644 index beb2a244..00000000 --- a/iOS_Tips/Pods/Target Support Files/GPUImage/GPUImage-prefix.pch +++ /dev/null @@ -1,12 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - diff --git a/iOS_Tips/Pods/Target Support Files/GPUImage/GPUImage.debug.xcconfig b/iOS_Tips/Pods/Target Support Files/GPUImage/GPUImage.debug.xcconfig deleted file mode 100644 index 3ac67a44..00000000 --- a/iOS_Tips/Pods/Target Support Files/GPUImage/GPUImage.debug.xcconfig +++ /dev/null @@ -1,11 +0,0 @@ -CLANG_MODULES_AUTOLINK = YES -CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GPUImage -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/GPUImage" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GPUImage" -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PODS_TARGET_SRCROOT = ${PODS_ROOT}/GPUImage -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/iOS_Tips/Pods/Target Support Files/GPUImage/GPUImage.release.xcconfig b/iOS_Tips/Pods/Target Support Files/GPUImage/GPUImage.release.xcconfig deleted file mode 100644 index 3ac67a44..00000000 --- a/iOS_Tips/Pods/Target Support Files/GPUImage/GPUImage.release.xcconfig +++ /dev/null @@ -1,11 +0,0 @@ -CLANG_MODULES_AUTOLINK = YES -CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GPUImage -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/GPUImage" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GPUImage" -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PODS_TARGET_SRCROOT = ${PODS_ROOT}/GPUImage -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/iOS_Tips/Pods/Target Support Files/GPUImage/GPUImage.xcconfig b/iOS_Tips/Pods/Target Support Files/GPUImage/GPUImage.xcconfig deleted file mode 100644 index 3ac67a44..00000000 --- a/iOS_Tips/Pods/Target Support Files/GPUImage/GPUImage.xcconfig +++ /dev/null @@ -1,11 +0,0 @@ -CLANG_MODULES_AUTOLINK = YES -CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GPUImage -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/GPUImage" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GPUImage" -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PODS_TARGET_SRCROOT = ${PODS_ROOT}/GPUImage -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/iOS_Tips/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-dummy.m b/iOS_Tips/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-dummy.m deleted file mode 100644 index 67a74df2..00000000 --- a/iOS_Tips/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_MBProgressHUD : NSObject -@end -@implementation PodsDummy_MBProgressHUD -@end diff --git a/iOS_Tips/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-prefix.pch b/iOS_Tips/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-prefix.pch deleted file mode 100644 index beb2a244..00000000 --- a/iOS_Tips/Pods/Target Support Files/MBProgressHUD/MBProgressHUD-prefix.pch +++ /dev/null @@ -1,12 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - diff --git a/iOS_Tips/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.debug.xcconfig b/iOS_Tips/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.debug.xcconfig deleted file mode 100644 index 56d33257..00000000 --- a/iOS_Tips/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.debug.xcconfig +++ /dev/null @@ -1,10 +0,0 @@ -CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/MBProgressHUD" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/MBProgressHUD" -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PODS_TARGET_SRCROOT = ${PODS_ROOT}/MBProgressHUD -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/iOS_Tips/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.release.xcconfig b/iOS_Tips/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.release.xcconfig deleted file mode 100644 index 56d33257..00000000 --- a/iOS_Tips/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.release.xcconfig +++ /dev/null @@ -1,10 +0,0 @@ -CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/MBProgressHUD" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/MBProgressHUD" -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PODS_TARGET_SRCROOT = ${PODS_ROOT}/MBProgressHUD -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/iOS_Tips/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.xcconfig b/iOS_Tips/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.xcconfig deleted file mode 100644 index 56d33257..00000000 --- a/iOS_Tips/Pods/Target Support Files/MBProgressHUD/MBProgressHUD.xcconfig +++ /dev/null @@ -1,10 +0,0 @@ -CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/MBProgressHUD" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/MBProgressHUD" -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PODS_TARGET_SRCROOT = ${PODS_ROOT}/MBProgressHUD -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/iOS_Tips/Pods/Target Support Files/MLeaksFinder/MLeaksFinder-dummy.m b/iOS_Tips/Pods/Target Support Files/MLeaksFinder/MLeaksFinder-dummy.m deleted file mode 100644 index f1aa9d0c..00000000 --- a/iOS_Tips/Pods/Target Support Files/MLeaksFinder/MLeaksFinder-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_MLeaksFinder : NSObject -@end -@implementation PodsDummy_MLeaksFinder -@end diff --git a/iOS_Tips/Pods/Target Support Files/MLeaksFinder/MLeaksFinder-prefix.pch b/iOS_Tips/Pods/Target Support Files/MLeaksFinder/MLeaksFinder-prefix.pch deleted file mode 100644 index beb2a244..00000000 --- a/iOS_Tips/Pods/Target Support Files/MLeaksFinder/MLeaksFinder-prefix.pch +++ /dev/null @@ -1,12 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - diff --git a/iOS_Tips/Pods/Target Support Files/MLeaksFinder/MLeaksFinder.xcconfig b/iOS_Tips/Pods/Target Support Files/MLeaksFinder/MLeaksFinder.xcconfig deleted file mode 100644 index 3ae6aa07..00000000 --- a/iOS_Tips/Pods/Target Support Files/MLeaksFinder/MLeaksFinder.xcconfig +++ /dev/null @@ -1,10 +0,0 @@ -CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MLeaksFinder -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/MLeaksFinder" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/FBRetainCycleDetector" "${PODS_ROOT}/Headers/Public/MLeaksFinder" -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PODS_TARGET_SRCROOT = ${PODS_ROOT}/MLeaksFinder -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/iOS_Tips/Pods/Target Support Files/Masonry/Masonry-dummy.m b/iOS_Tips/Pods/Target Support Files/Masonry/Masonry-dummy.m deleted file mode 100644 index 04001b1a..00000000 --- a/iOS_Tips/Pods/Target Support Files/Masonry/Masonry-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Masonry : NSObject -@end -@implementation PodsDummy_Masonry -@end diff --git a/iOS_Tips/Pods/Target Support Files/Masonry/Masonry-prefix.pch b/iOS_Tips/Pods/Target Support Files/Masonry/Masonry-prefix.pch deleted file mode 100644 index beb2a244..00000000 --- a/iOS_Tips/Pods/Target Support Files/Masonry/Masonry-prefix.pch +++ /dev/null @@ -1,12 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - diff --git a/iOS_Tips/Pods/Target Support Files/Masonry/Masonry.debug.xcconfig b/iOS_Tips/Pods/Target Support Files/Masonry/Masonry.debug.xcconfig deleted file mode 100644 index d8408858..00000000 --- a/iOS_Tips/Pods/Target Support Files/Masonry/Masonry.debug.xcconfig +++ /dev/null @@ -1,10 +0,0 @@ -CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Masonry -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Masonry" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Masonry" -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PODS_TARGET_SRCROOT = ${PODS_ROOT}/Masonry -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/iOS_Tips/Pods/Target Support Files/Masonry/Masonry.release.xcconfig b/iOS_Tips/Pods/Target Support Files/Masonry/Masonry.release.xcconfig deleted file mode 100644 index d8408858..00000000 --- a/iOS_Tips/Pods/Target Support Files/Masonry/Masonry.release.xcconfig +++ /dev/null @@ -1,10 +0,0 @@ -CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Masonry -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Masonry" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Masonry" -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PODS_TARGET_SRCROOT = ${PODS_ROOT}/Masonry -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-acknowledgements.markdown b/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-acknowledgements.markdown deleted file mode 100644 index f376b042..00000000 --- a/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-acknowledgements.markdown +++ /dev/null @@ -1,164 +0,0 @@ -# Acknowledgements -This application makes use of the following third party libraries: - -## GPUImage - -Copyright (c) 2012, Brad Larson, Ben Cochran, Hugues Lismonde, Keitaroh Kobayashi, Alaric Cole, Matthew Clark, Jacob Gundersen, Chris Williams. -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -Neither the name of the GPUImage framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -## MBProgressHUD - -Copyright © 2009-2016 Matej Bukovinski - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -## Masonry - -Copyright (c) 2011-2012 Masonry Team - https://github.com/Masonry - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -## YYCache - -The MIT License (MIT) - -Copyright (c) 2015 ibireme - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - - -## YYImage - -The MIT License (MIT) - -Copyright (c) 2015 ibireme - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - - -## YYModel - -The MIT License (MIT) - -Copyright (c) 2015 ibireme - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - - -## YYWebImage - -The MIT License (MIT) - -Copyright (c) 2015 ibireme - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -Generated by CocoaPods - https://cocoapods.org diff --git a/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-acknowledgements.plist b/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-acknowledgements.plist deleted file mode 100644 index c9a3f5e1..00000000 --- a/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-acknowledgements.plist +++ /dev/null @@ -1,232 +0,0 @@ - - - - - PreferenceSpecifiers - - - FooterText - This application makes use of the following third party libraries: - Title - Acknowledgements - Type - PSGroupSpecifier - - - FooterText - Copyright (c) 2012, Brad Larson, Ben Cochran, Hugues Lismonde, Keitaroh Kobayashi, Alaric Cole, Matthew Clark, Jacob Gundersen, Chris Williams. -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -Neither the name of the GPUImage framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - License - BSD - Title - GPUImage - Type - PSGroupSpecifier - - - FooterText - Copyright © 2009-2016 Matej Bukovinski - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - License - MIT - Title - MBProgressHUD - Type - PSGroupSpecifier - - - FooterText - Copyright (c) 2011-2012 Masonry Team - https://github.com/Masonry - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - License - MIT - Title - Masonry - Type - PSGroupSpecifier - - - FooterText - The MIT License (MIT) - -Copyright (c) 2015 ibireme <ibireme@gmail.com> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - - License - MIT - Title - YYCache - Type - PSGroupSpecifier - - - FooterText - The MIT License (MIT) - -Copyright (c) 2015 ibireme <ibireme@gmail.com> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - - License - MIT - Title - YYImage - Type - PSGroupSpecifier - - - FooterText - The MIT License (MIT) - -Copyright (c) 2015 ibireme <ibireme@gmail.com> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - - License - MIT - Title - YYModel - Type - PSGroupSpecifier - - - FooterText - The MIT License (MIT) - -Copyright (c) 2015 ibireme <ibireme@gmail.com> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - - License - MIT - Title - YYWebImage - Type - PSGroupSpecifier - - - FooterText - Generated by CocoaPods - https://cocoapods.org - Title - - Type - PSGroupSpecifier - - - StringsTable - Acknowledgements - Title - Acknowledgements - - diff --git a/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-dummy.m b/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-dummy.m deleted file mode 100644 index 5c9082c5..00000000 --- a/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Pods_DarkMode : NSObject -@end -@implementation PodsDummy_Pods_DarkMode -@end diff --git a/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-resources-Debug-input-files.xcfilelist b/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-resources-Debug-input-files.xcfilelist deleted file mode 100644 index 23eccc39..00000000 --- a/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-resources-Debug-input-files.xcfilelist +++ /dev/null @@ -1,6 +0,0 @@ -${PODS_ROOT}/Target Support Files/Pods-DarkMode/Pods-DarkMode-resources.sh -${PODS_ROOT}/GPUImage/framework/Resources/lookup.png -${PODS_ROOT}/GPUImage/framework/Resources/lookup_amatorka.png -${PODS_ROOT}/GPUImage/framework/Resources/lookup_miss_etikate.png -${PODS_ROOT}/GPUImage/framework/Resources/lookup_soft_elegance_1.png -${PODS_ROOT}/GPUImage/framework/Resources/lookup_soft_elegance_2.png \ No newline at end of file diff --git a/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-resources-Debug-output-files.xcfilelist b/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-resources-Debug-output-files.xcfilelist deleted file mode 100644 index e845b86c..00000000 --- a/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-resources-Debug-output-files.xcfilelist +++ /dev/null @@ -1,5 +0,0 @@ -${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/lookup.png -${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/lookup_amatorka.png -${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/lookup_miss_etikate.png -${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/lookup_soft_elegance_1.png -${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/lookup_soft_elegance_2.png \ No newline at end of file diff --git a/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-resources-Release-input-files.xcfilelist b/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-resources-Release-input-files.xcfilelist deleted file mode 100644 index 23eccc39..00000000 --- a/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-resources-Release-input-files.xcfilelist +++ /dev/null @@ -1,6 +0,0 @@ -${PODS_ROOT}/Target Support Files/Pods-DarkMode/Pods-DarkMode-resources.sh -${PODS_ROOT}/GPUImage/framework/Resources/lookup.png -${PODS_ROOT}/GPUImage/framework/Resources/lookup_amatorka.png -${PODS_ROOT}/GPUImage/framework/Resources/lookup_miss_etikate.png -${PODS_ROOT}/GPUImage/framework/Resources/lookup_soft_elegance_1.png -${PODS_ROOT}/GPUImage/framework/Resources/lookup_soft_elegance_2.png \ No newline at end of file diff --git a/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-resources-Release-output-files.xcfilelist b/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-resources-Release-output-files.xcfilelist deleted file mode 100644 index e845b86c..00000000 --- a/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-resources-Release-output-files.xcfilelist +++ /dev/null @@ -1,5 +0,0 @@ -${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/lookup.png -${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/lookup_amatorka.png -${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/lookup_miss_etikate.png -${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/lookup_soft_elegance_1.png -${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/lookup_soft_elegance_2.png \ No newline at end of file diff --git a/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-resources.sh b/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-resources.sh deleted file mode 100755 index 07a29283..00000000 --- a/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode-resources.sh +++ /dev/null @@ -1,137 +0,0 @@ -#!/bin/sh -set -e -set -u -set -o pipefail - -function on_error { - echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" -} -trap 'on_error $LINENO' ERR - -if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then - # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy - # resources to, so exit 0 (signalling the script phase was successful). - exit 0 -fi - -mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" - -RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt -> "$RESOURCES_TO_COPY" - -XCASSET_FILES=() - -# This protects against multiple targets copying the same framework dependency at the same time. The solution -# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html -RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") - -case "${TARGETED_DEVICE_FAMILY:-}" in - 1,2) - TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" - ;; - 1) - TARGET_DEVICE_ARGS="--target-device iphone" - ;; - 2) - TARGET_DEVICE_ARGS="--target-device ipad" - ;; - 3) - TARGET_DEVICE_ARGS="--target-device tv" - ;; - 4) - TARGET_DEVICE_ARGS="--target-device watch" - ;; - *) - TARGET_DEVICE_ARGS="--target-device mac" - ;; -esac - -install_resource() -{ - if [[ "$1" = /* ]] ; then - RESOURCE_PATH="$1" - else - RESOURCE_PATH="${PODS_ROOT}/$1" - fi - if [[ ! -e "$RESOURCE_PATH" ]] ; then - cat << EOM -error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. -EOM - exit 1 - fi - case $RESOURCE_PATH in - *.storyboard) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true - ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} - ;; - *.xib) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true - ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} - ;; - *.framework) - echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true - mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true - rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - ;; - *.xcdatamodel) - echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true - xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" - ;; - *.xcdatamodeld) - echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true - xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" - ;; - *.xcmappingmodel) - echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true - xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" - ;; - *.xcassets) - ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" - XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") - ;; - *) - echo "$RESOURCE_PATH" || true - echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" - ;; - esac -} -if [[ "$CONFIGURATION" == "Debug" ]]; then - install_resource "${PODS_ROOT}/GPUImage/framework/Resources/lookup.png" - install_resource "${PODS_ROOT}/GPUImage/framework/Resources/lookup_amatorka.png" - install_resource "${PODS_ROOT}/GPUImage/framework/Resources/lookup_miss_etikate.png" - install_resource "${PODS_ROOT}/GPUImage/framework/Resources/lookup_soft_elegance_1.png" - install_resource "${PODS_ROOT}/GPUImage/framework/Resources/lookup_soft_elegance_2.png" -fi -if [[ "$CONFIGURATION" == "Release" ]]; then - install_resource "${PODS_ROOT}/GPUImage/framework/Resources/lookup.png" - install_resource "${PODS_ROOT}/GPUImage/framework/Resources/lookup_amatorka.png" - install_resource "${PODS_ROOT}/GPUImage/framework/Resources/lookup_miss_etikate.png" - install_resource "${PODS_ROOT}/GPUImage/framework/Resources/lookup_soft_elegance_1.png" - install_resource "${PODS_ROOT}/GPUImage/framework/Resources/lookup_soft_elegance_2.png" -fi - -mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then - mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" - rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" -fi -rm -f "$RESOURCES_TO_COPY" - -if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] -then - # Find all other xcassets (this unfortunately includes those of path pods and other targets). - OTHER_XCASSETS=$(find -L "$PWD" -iname "*.xcassets" -type d) - while read line; do - if [[ $line != "${PODS_ROOT}*" ]]; then - XCASSET_FILES+=("$line") - fi - done <<<"$OTHER_XCASSETS" - - if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then - printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" - else - printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" - fi -fi diff --git a/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode.debug.xcconfig b/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode.debug.xcconfig deleted file mode 100644 index 15aeb0bf..00000000 --- a/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode.debug.xcconfig +++ /dev/null @@ -1,10 +0,0 @@ -CLANG_MODULES_AUTOLINK = YES -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GPUImage" "${PODS_ROOT}/Headers/Public/MBProgressHUD" "${PODS_ROOT}/Headers/Public/Masonry" "${PODS_ROOT}/Headers/Public/YYCache" "${PODS_ROOT}/Headers/Public/YYImage" "${PODS_ROOT}/Headers/Public/YYModel" "${PODS_ROOT}/Headers/Public/YYWebImage" -LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GPUImage" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/YYCache" "${PODS_CONFIGURATION_BUILD_DIR}/YYImage" "${PODS_CONFIGURATION_BUILD_DIR}/YYModel" "${PODS_CONFIGURATION_BUILD_DIR}/YYWebImage" -OTHER_LDFLAGS = $(inherited) -ObjC -l"GPUImage" -l"MBProgressHUD" -l"Masonry" -l"YYCache" -l"YYImage" -l"YYModel" -l"YYWebImage" -l"sqlite3" -l"z" -framework "AVFoundation" -framework "Accelerate" -framework "AssetsLibrary" -framework "CoreFoundation" -framework "CoreGraphics" -framework "CoreMedia" -framework "Foundation" -framework "ImageIO" -framework "MobileCoreServices" -framework "OpenGLES" -framework "QuartzCore" -framework "UIKit" -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_PODFILE_DIR_PATH = ${SRCROOT}/. -PODS_ROOT = ${SRCROOT}/Pods -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode.release.xcconfig b/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode.release.xcconfig deleted file mode 100644 index 15aeb0bf..00000000 --- a/iOS_Tips/Pods/Target Support Files/Pods-DarkMode/Pods-DarkMode.release.xcconfig +++ /dev/null @@ -1,10 +0,0 @@ -CLANG_MODULES_AUTOLINK = YES -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GPUImage" "${PODS_ROOT}/Headers/Public/MBProgressHUD" "${PODS_ROOT}/Headers/Public/Masonry" "${PODS_ROOT}/Headers/Public/YYCache" "${PODS_ROOT}/Headers/Public/YYImage" "${PODS_ROOT}/Headers/Public/YYModel" "${PODS_ROOT}/Headers/Public/YYWebImage" -LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GPUImage" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/YYCache" "${PODS_CONFIGURATION_BUILD_DIR}/YYImage" "${PODS_CONFIGURATION_BUILD_DIR}/YYModel" "${PODS_CONFIGURATION_BUILD_DIR}/YYWebImage" -OTHER_LDFLAGS = $(inherited) -ObjC -l"GPUImage" -l"MBProgressHUD" -l"Masonry" -l"YYCache" -l"YYImage" -l"YYModel" -l"YYWebImage" -l"sqlite3" -l"z" -framework "AVFoundation" -framework "Accelerate" -framework "AssetsLibrary" -framework "CoreFoundation" -framework "CoreGraphics" -framework "CoreMedia" -framework "Foundation" -framework "ImageIO" -framework "MobileCoreServices" -framework "OpenGLES" -framework "QuartzCore" -framework "UIKit" -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_PODFILE_DIR_PATH = ${SRCROOT}/. -PODS_ROOT = ${SRCROOT}/Pods -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES From 89fd526e718286a46509b4b16790ca5deb283141 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Fri, 12 Jun 2020 16:52:14 +0800 Subject: [PATCH 003/356] Update README.md --- README.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b27b2227..4056c0be 100644 --- a/README.md +++ b/README.md @@ -14,10 +14,13 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git >> 3.5、VideoToolBox和AudioToolBox音视频编解码 >> 3.6、AVFoundation 利用摄像头实时识别物体颜色 >> 3.7、AVFoundation 原生二维码扫描识别和生成 ->> + > 4、OpenGL ES学习 > 5、LeetCode算法练习 -> 6、键盘和UIMenuController的并存问题 +> 6、工作中踩过的坑 +>> 6.1、键盘和UIMenuController不能同时存在的问题 +>> 6.2、全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突 + > 7、iOS Crash防护 > 8、WKWebView相关 >> 8.1、WKWebView的使用 @@ -105,19 +108,25 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git > [LeetCode算法练习集合(Swift版) ~ 每天一道算法题](https://github.com/wsl2ls/AlgorithmSet.git) -## 6、[键盘和UIMenuController的并存问题](https://www.jianshu.com/p/ed1b57c4ecea) +## 6、工作中踩过的坑 + +### 6.1、[键盘和UIMenuController的并存问题](https://www.jianshu.com/p/ed1b57c4ecea) | ![问题描述.gif](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/10、键盘和UIMenuController不能同时出现的问题描述.gif) | ![并存问题解决](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/10、键盘和UIMenuController并存问题解决.gif) | +### 6.2、[全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突](https://juejin.im/post/5c0e1e73f265da616413d828) + + > 该代码地址在:https://github.com/wsl2ls/WSLTransferAnimation + ## 7、iOS Crash防护 > NSArray/NSMutableArray、NSDictionary/NSMutableDictionary、NSString/NSMutableString、Unrecognized Selector、KVO、KVC 、野指针定位、内存泄漏/循环引用 ## 8、[WKWebView相关](https://juejin.im/post/5ed999fd51882542f9389949) -> WKWebView的使用、WKWebView+UITableView混排、UIScrollView实现原理、WKWebView离线缓存功能、Html非文本元素替换为原生组件展示 +> [WKWebView的使用](https://juejin.im/post/5c0e1e2ae51d451d971743a1)、[WKWebView+UITableView混排](https://juejin.im/post/5ed999fd51882542f9389949)、UIScrollView实现原理、WKWebView离线缓存功能、Html非文本元素替换为原生组件展示 -![音视频编码](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/12、WKWebView.gif) +![WKWebView相关](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/12、WKWebView.gif) ## 问题说明: From ad780fc5e4b7350df44745a4be15ac0b6b5a9fd9 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 12 Jun 2020 17:16:20 +0800 Subject: [PATCH 004/356] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/.DS_Store | Bin 10244 -> 10244 bytes .../AVFoundation/SLAVListViewController.m | 12 +++++------- .../DarkMode/WKWebView/SLWebViewController.h | 3 +++ .../DarkMode/WKWebView/SLWebViewController.m | 12 ++++++++---- .../WorkIssues/SLWorkIssuesViewController.m | 6 +++--- 5 files changed, 19 insertions(+), 14 deletions(-) diff --git a/iOS_Tips/.DS_Store b/iOS_Tips/.DS_Store index 8c4ab2dc6d1cf2d0178693b6200368214c93a819..88debd4d5e9e14f5f3636a93d0a2f03498ce4cff 100644 GIT binary patch delta 163 zcmZn(XbG6$&nUGqU^hRb)Z{=xk @end -static NSString *KwebUrl = @"https://www.jianshu.com/p/5cf0d241ae12"; @implementation SLWebViewController #pragma mark - Override - (void)viewDidLoad { @@ -44,7 +43,6 @@ - (void)dealloc { #pragma mark - UI - (void)setupUI { - self.view.backgroundColor = UIColor.whiteColor; UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"上一步" style:UIBarButtonItemStyleDone target:self action:@selector(goBackAction:)]; UIBarButtonItem *forwardItem = [[UIBarButtonItem alloc] initWithTitle:@"下一步" style:UIBarButtonItemStyleDone target:self action:@selector(goForwardAction:)]; @@ -57,7 +55,7 @@ - (void)setupUI { [self.view addSubview:self.webView]; - NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:KwebUrl]]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.urlString]]; //设置上一次的请求时间 [request setValue:[SLMethod userDefaultsObjectForKey:@"localLastModified"] forHTTPHeaderField:@"If-Modified-Since"]; [_webView loadRequest:request]; @@ -84,6 +82,12 @@ - (UIProgressView *)progressView { } return _progressView; } +- (NSString *)urlString { + if (!_urlString) { + _urlString = @"https://www.jianshu.com/p/5cf0d241ae12"; + } + return _urlString; +} #pragma mark - Look Here ///关于WKWebView的那些坑: https://mp.weixin.qq.com/s/rhYKLIbXOsUJC_n6dt9UfA? @@ -183,7 +187,7 @@ - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigati } // 根据客户端受到的服务器响应头以及response相关信息来决定是否可以跳转 - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{ - if ([navigationResponse.response isKindOfClass:[NSHTTPURLResponse class]] && [navigationResponse.response.URL.absoluteString isEqualToString:KwebUrl]) { + if ([navigationResponse.response isKindOfClass:[NSHTTPURLResponse class]] && [navigationResponse.response.URL.absoluteString isEqualToString:self.urlString]) { NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)navigationResponse.response; if (httpResponse.statusCode == 304) { //自上次请求后,文件还没有修改变化 diff --git a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m index e864f3ed..b4f478d7 100644 --- a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m @@ -8,6 +8,7 @@ #import "SLWorkIssuesViewController.h" #import "SLMenuViewController.h" +#import "SLWebViewController.h" @interface SLWorkIssuesViewController () @property (nonatomic, strong) NSMutableArray *dataSource; @@ -43,7 +44,7 @@ - (void)getData { @"键盘和UIMenuController不能同时存在的问题", @"全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突"]]; [self.classArray addObjectsFromArray:@[[SLMenuViewController class], - [UIViewController class]]]; + [SLWebViewController class]]]; [self.tableView reloadData]; } @@ -76,8 +77,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath UIViewController *nextVc = [[self.classArray[indexPath.row] alloc] init]; switch (indexPath.row) { case 1: - [SLAlertView showAlertViewWithText:@"全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突: https://github.com/wsl2ls/WSLTransferAnimation" delayHid:2]; - break; + ((SLWebViewController *)nextVc).urlString = @"https://juejin.im/post/5c0e1e73f265da616413d828"; default: [self.navigationController pushViewController:nextVc animated:YES]; break; From beff3e95cc763a937bac8ffcb2041a4acb7eae9d Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 12 Jun 2020 17:46:03 +0800 Subject: [PATCH 005/356] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/.DS_Store | Bin 10244 -> 10244 bytes iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 6 +++++ .../DarkMode/General/Tool/PrefixHeader.pch | 1 + .../DarkMode/General/Tool/SLViewController.h | 17 +++++++++++++ .../DarkMode/General/Tool/SLViewController.m | 19 ++++++++++++++ iOS_Tips/DarkMode/ViewController.m | 4 +-- .../WKWebView/SLWebNativeViewController.h | 2 +- .../WKWebView/SLWebNativeViewController.m | 24 ++---------------- .../DarkMode/WKWebView/SLWebViewController.h | 2 +- .../DarkMode/WKWebView/SLWebViewController.m | 2 -- .../WKWebView/SLWebViewListController.m | 1 - .../WebCache/SLWebCacheViewController.h | 2 +- .../WebCache/SLWebCacheViewController.m | 1 - .../WebTableView/SLWebTableViewController.h | 2 +- .../WebTableView/SLWebTableViewController.m | 1 - .../WebTableView/SLWebTableViewController2.h | 2 +- .../WebTableView/SLWebTableViewController2.m | 1 - .../WebTableView/SLWebTableViewController3.h | 2 +- .../WebTableView/SLWebTableViewController3.m | 1 - .../WebTableView/SLWebTableViewController4.h | 2 +- .../WebTableView/SLWebTableViewController4.m | 1 - 21 files changed, 54 insertions(+), 39 deletions(-) create mode 100644 iOS_Tips/DarkMode/General/Tool/SLViewController.h create mode 100644 iOS_Tips/DarkMode/General/Tool/SLViewController.m diff --git a/iOS_Tips/.DS_Store b/iOS_Tips/.DS_Store index 88debd4d5e9e14f5f3636a93d0a2f03498ce4cff..787cc1353718a79c0428c885e26233ed8da573ad 100644 GIT binary patch delta 36 scmZn(XbG6$&nU4mU^hRb#N + +NS_ASSUME_NONNULL_BEGIN + +@interface SLViewController : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/General/Tool/SLViewController.m b/iOS_Tips/DarkMode/General/Tool/SLViewController.m new file mode 100644 index 00000000..a5a63efe --- /dev/null +++ b/iOS_Tips/DarkMode/General/Tool/SLViewController.m @@ -0,0 +1,19 @@ +// +// SLViewController.m +// DarkMode +// +// Created by wsl on 2020/6/12. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLViewController.h" + +@interface SLViewController () + +@end + +@implementation SLViewController +- (void)dealloc { + NSLog(@"%@释放了",NSStringFromClass(self.class)); +} +@end diff --git a/iOS_Tips/DarkMode/ViewController.m b/iOS_Tips/DarkMode/ViewController.m index a83241dc..cc8af04d 100644 --- a/iOS_Tips/DarkMode/ViewController.m +++ b/iOS_Tips/DarkMode/ViewController.m @@ -97,8 +97,8 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath } break; case 4: { - [SLAlertView showAlertViewWithText:@"LeetCode算法练习集合地址:https://github.com/wsl2ls/AlgorithmSet.git" delayHid:2]; - } + [SLAlertView showAlertViewWithText:@"LeetCode算法练习集合: https://github.com/wsl2ls/AlgorithmSet.git" delayHid:2]; + } break; default: [self.navigationController pushViewController:nextVc animated:YES]; diff --git a/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.h b/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.h index 32309c03..b2994f49 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.h +++ b/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.h @@ -11,7 +11,7 @@ NS_ASSUME_NONNULL_BEGIN /// WKWebView渲染的部分HTML元素替换为用原生组件显示 -@interface SLWebNativeViewController : UIViewController +@interface SLWebNativeViewController : SLViewController @end diff --git a/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.m b/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.m index d8406a8b..467ae836 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.m +++ b/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.m @@ -35,13 +35,13 @@ @implementation SLWebNativeModel */ @interface SLWebNativeViewController () @property (nonatomic, strong) WKWebView * webView; -///网页加载进度视图 +/// 网页加载进度视图 @property (nonatomic, strong) UIProgressView * progressView; /// WKWebView 内容的高度 @property (nonatomic, assign) CGFloat webContentHeight; /// 原生组件所需的HTML中元素的数据 @property (nonatomic, strong) NSMutableArray *dataSource; -///视频播放 +/// 音视频播放 @property (nonatomic, strong) SLAvPlayer *avPlayer; @end @@ -60,7 +60,6 @@ - (void)viewWillDisappear:(BOOL)animated { } - (void)dealloc { [self removeKVO]; - NSLog(@"%@释放了",NSStringFromClass(self.class)); } #pragma mark - UI @@ -193,8 +192,6 @@ -(void)rotateAnimate:(UIView *)view{ }]; } - - #pragma mark - WKNavigationDelegate // 根据WebView对于即将跳转的HTTP请求头信息和相关信息来决定是否跳转 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { @@ -262,21 +259,4 @@ - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigat - (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView{ } - -#pragma mark - WKUIDelegate -/** - * web界面中有弹出警告框时调用 - * - * @param webView 实现该代理的webview - * @param message 警告框中的内容 - * @param completionHandler 警告框消失调用 - */ -- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler { - UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"HTML的弹出框" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert]; - [alertController addAction:([UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { - completionHandler(); - }])]; - [self presentViewController:alertController animated:YES completion:nil]; -} - @end diff --git a/iOS_Tips/DarkMode/WKWebView/SLWebViewController.h b/iOS_Tips/DarkMode/WKWebView/SLWebViewController.h index 19af3563..cebe5dda 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLWebViewController.h +++ b/iOS_Tips/DarkMode/WKWebView/SLWebViewController.h @@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN /// https://github.com/ChenYilong/ParseSourceCodeStudy/blob/master/02_Parse%E7%9A%84%E7%BD%91%E7%BB%9C%E7%BC%93%E5%AD%98%E4%B8%8E%E7%A6%BB%E7%BA%BF%E5%AD%98%E5%82%A8/iOS%E7%BD%91%E7%BB%9C%E7%BC%93%E5%AD%98%E6%89%AB%E7%9B%B2%E7%AF%87.md /// https://dequan1331.github.io/index.html ///关于WKWebView的使用可以看我之前的总结: https://github.com/wsl2ls/WKWebView -@interface SLWebViewController : UIViewController +@interface SLWebViewController : SLViewController ///打开的web地址 默认:https://www.jianshu.com/p/5cf0d241ae12 @property (nonatomic, strong) NSString *urlString; diff --git a/iOS_Tips/DarkMode/WKWebView/SLWebViewController.m b/iOS_Tips/DarkMode/WKWebView/SLWebViewController.m index c75b4653..a8499e5c 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLWebViewController.m +++ b/iOS_Tips/DarkMode/WKWebView/SLWebViewController.m @@ -9,7 +9,6 @@ #import "SLWebViewController.h" #import #import "WKWebView+SLExtension.h" -#import "SLUrlProtocol.h" #import "SLUrlProtocolAddCookie.h" ///关于WKWebView的其他更多使用可以看我之前的总结: https://github.com/wsl2ls/WKWebView @@ -38,7 +37,6 @@ - (void)dealloc { [self removeKVO]; [WKWebView sl_unregisterSchemeForSupportHttpProtocol]; [NSURLProtocol registerClass:[NSURLProtocol class]]; - NSLog(@"%@释放了",NSStringFromClass(self.class)); } #pragma mark - UI diff --git a/iOS_Tips/DarkMode/WKWebView/SLWebViewListController.m b/iOS_Tips/DarkMode/WKWebView/SLWebViewListController.m index 98a52df4..33f453f9 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLWebViewListController.m +++ b/iOS_Tips/DarkMode/WKWebView/SLWebViewListController.m @@ -38,7 +38,6 @@ - (void)viewWillAppear:(BOOL)animated { - (BOOL)prefersStatusBarHidden { return NO; } - #pragma mark - UI - (void)setupUI { self.navigationItem.title = @"WKWebView"; diff --git a/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheViewController.h b/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheViewController.h index 13aab741..5542f0d2 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheViewController.h +++ b/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheViewController.h @@ -11,7 +11,7 @@ NS_ASSUME_NONNULL_BEGIN /// WKWebView 缓存实现 -@interface SLWebCacheViewController : UIViewController +@interface SLWebCacheViewController : SLViewController @end diff --git a/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheViewController.m b/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheViewController.m index 1cf5fbdb..c58e14c7 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheViewController.m +++ b/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheViewController.m @@ -37,7 +37,6 @@ - (void)dealloc { [self removeKVO]; //关闭缓存 [[SLWebCacheManager shareInstance] closeCache]; - NSLog(@"%@释放了",NSStringFromClass(self.class)); } #pragma mark - UI diff --git a/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController.h b/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController.h index 9f95fc1a..b64bf137 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController.h +++ b/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController.h @@ -15,7 +15,7 @@ NS_ASSUME_NONNULL_BEGIN 方案1:WebView作为TableView的Header, 撑开webView,显示渲染全部内容,当内容过多时,比如大量图片时,容易造成内存暴涨(不建议使用) 参考: https://www.jianshu.com/p/42858f95ab43、https://dequan1331.github.io/hybrid-page-kit.html、https://www.jianshu.com/p/3721d736cf68 */ -@interface SLWebTableViewController : UIViewController +@interface SLWebTableViewController : SLViewController @end diff --git a/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController.m b/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController.m index ecfc77dc..aa0f1aae 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController.m +++ b/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController.m @@ -33,7 +33,6 @@ - (void)viewWillDisappear:(BOOL)animated { } - (void)dealloc { [self removeKVO]; - NSLog(@"%@释放了",NSStringFromClass(self.class)); } #pragma mark - SetupUI diff --git a/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController2.h b/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController2.h index 663bfb89..4517aa9f 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController2.h +++ b/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController2.h @@ -16,7 +16,7 @@ NS_ASSUME_NONNULL_BEGIN 方案2:将tableView加到WKWebView.scrollView上, WKWebView加载的HTML最后留一个空白占位div,用于确定tableView的位置,在监听到webView.scrollView.contentSize变化后,不断调整tableView的位置,同时将该div的尺寸设置为tableView的尺寸。禁用tableView和webView.scrollVie的scrollEnabled = NO,通过添加pan手势,手动调整contentOffset。tableView的最大高度为屏幕高度,当内容不足一屏时,高度为内容高度。 参考: https://www.jianshu.com/p/42858f95ab43、https://dequan1331.github.io/hybrid-page-kit.html、https://www.jianshu.com/p/3721d736cf68 */ -@interface SLWebTableViewController2 : UIViewController +@interface SLWebTableViewController2 : SLViewController @end diff --git a/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController2.m b/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController2.m index ad194ee5..ebfadada 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController2.m +++ b/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController2.m @@ -48,7 +48,6 @@ - (void)viewWillDisappear:(BOOL)animated { } - (void)dealloc { [self removeKVO]; - NSLog(@"%@释放了",NSStringFromClass(self.class)); } // 滚动中单击可以停止滚动 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { diff --git a/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController3.h b/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController3.h index 4701d52f..0deb903a 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController3.h +++ b/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController3.h @@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN WKWebView + UITableView 方案3:(推荐) WKWebView作为TableView的Header, 但不撑开webView。禁用tableView和webView.scrollVie的scrollEnabled = NO,通过添加pan手势,手动调整contentOffset。WebView的最大高度为屏幕高度,当内容不足一屏时,高度为内容高度。和方案2类似,但是不需要插入占位Div。 */ -@interface SLWebTableViewController3 : UIViewController +@interface SLWebTableViewController3 : SLViewController @end diff --git a/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController3.m b/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController3.m index 02e2eddd..9f120ddd 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController3.m +++ b/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController3.m @@ -51,7 +51,6 @@ - (void)viewWillDisappear:(BOOL)animated { } - (void)dealloc { [self removeKVO]; - NSLog(@"%@释放了",NSStringFromClass(self.class)); } // 滚动中单击可以停止滚动 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { diff --git a/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController4.h b/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController4.h index fda2af04..a4a4c86a 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController4.h +++ b/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController4.h @@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN WKWebView + UITableView 方案4:(推荐)[UIScrollView addSubView: WKWebView & UITableView]; UIScrollView.contenSize = WKWebView.contenSize + UITableView.contenSize; WKWebView和UITableView的最大高度为一屏高,并禁用scrollEnabled=NO,然后根据UIScrollView的滑动偏移量调整WKWebView和UITableView的展示区域contenOffset */ -@interface SLWebTableViewController4 : UIViewController +@interface SLWebTableViewController4 : SLViewController @end diff --git a/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController4.m b/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController4.m index 44572758..eaedc1da 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController4.m +++ b/iOS_Tips/DarkMode/WKWebView/WebTableView/SLWebTableViewController4.m @@ -42,7 +42,6 @@ - (void)viewWillDisappear:(BOOL)animated { } - (void)dealloc { [self removeKVO]; - NSLog(@"%@释放了",NSStringFromClass(self.class)); } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; From 472db172fd71628e2cbe9696343a8bcaba488c5e Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 12 Jun 2020 20:06:37 +0800 Subject: [PATCH 006/356] =?UTF-8?q?UITableView=E5=AE=9E=E7=8E=B0=E5=8E=9F?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WKWebView/SLTableViewController.m | 104 +++++++++++++++--- 1 file changed, 88 insertions(+), 16 deletions(-) diff --git a/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m b/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m index 3a7e2939..ec774a1b 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m +++ b/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m @@ -9,11 +9,16 @@ #import "SLTableViewController.h" @interface SLTableViewController () +{ + UITableView *tableView; +} @property (nonatomic, strong) UIScrollView *scrollView; +///复用池 +@property (nonatomic, strong) NSMutableDictionary *> *reusablePool; +/// 每一行的坐标位置 +@property (nonatomic, strong) NSMutableArray *frameArray; - ///复用池 -@property (nonatomic, strong) NSMutableDictionary *> *multiplexingPool; @end @@ -29,6 +34,7 @@ - (void)viewDidLoad { - (void)setupUI { self.view.backgroundColor = [UIColor whiteColor]; [self.view addSubview:self.scrollView]; + [self reloadData]; } #pragma mark - Data @@ -38,52 +44,118 @@ - (UIScrollView *)scrollView { if (!_scrollView) { _scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; _scrollView.delegate = self; + if (@available(iOS 11.0, *)) { + _scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } else { + self.automaticallyAdjustsScrollViewInsets = NO; + } } return _scrollView; } -- (NSMutableDictionary *)multiplexingPool { - if (!_multiplexingPool) { - _multiplexingPool = [NSMutableDictionary dictionary]; +- (NSMutableDictionary *)reusablePool { + if (!_reusablePool) { + _reusablePool = [NSMutableDictionary dictionary]; + } + return _reusablePool;; +} +- (NSMutableArray *)frameArray { + if (!_frameArray) { + _frameArray = [NSMutableArray array]; } - return _multiplexingPool;; + return _frameArray; } #pragma mark - Help Methods ///刷新数据 - (void)reloadData { + //清空布局信息 + [self.frameArray removeAllObjects]; + //数据源个数 + NSInteger count = [self numberOfRowsInScrollView:self.scrollView]; + CGFloat y = 0; + //获取每一行的布局信息 + for (int i = 0; i < count; i++) { + CGFloat cellHeight = [self scrollView:self.scrollView heightForRowAtIndex:i]; + CGRect rect = CGRectMake(0, y, self.scrollView.sl_width, cellHeight); + [self.frameArray addObject:[NSValue valueWithCGRect:rect]]; + + //按需加载 只加载坐标位置是在当前窗口显示的视图 + if (rect.origin.y + rect.size.height >= self.scrollView.contentOffset.y && rect.origin.y <= self.scrollView.contentOffset.y + self.scrollView.sl_height) { + UIView *view = [self scrollView:self.scrollView cellForRowAtIndex:i]; + view.frame = rect; + [self.scrollView addSubview:view]; + } + + //下一行的起始纵坐标 + y += cellHeight; + + //最后 确定了内容大小 + if (i == count - 1) { + self.scrollView.contentSize = CGSizeMake(self.scrollView.sl_width, y); + } + } + + // NSArray *aa = [self indexForVisibleRows]; +} +//当前可见的cell +- (NSArray *)visibleCells { + return self.scrollView.subviews; +} +//当前可见cell的索引 其实绘制cell的时候就可以先保存可见的索引,不用每次遍历查询 +- (NSArray *)indexForVisibleRows { + NSMutableArray *indexs = [NSMutableArray array]; + for (int i = 0; i < self.frameArray.count; i++) { + CGRect rect = [self.frameArray[i] CGRectValue]; + if (rect.origin.y + rect.size.height >= self.scrollView.contentOffset.y && rect.origin.y <= self.scrollView.contentOffset.y + self.scrollView.sl_height) { + [indexs addObject:@(i)]; + } + } + return indexs; +} +//即将显示cell +- (void)willDisplayCell{ + + + +} + +///根据cellID去复用池reusablePool取可重用的view,如果没有,返回nil +- (UIView *)dequeueReusableCellWithIdentifier:(nonnull NSString *)cellID { + return nil; } ///注册样式 - (void)registerClass:(Class)class forCellReuseIdentifier:(NSString *)cellID { - self.multiplexingPool[cellID] = [NSHashTable weakObjectsHashTable]; + self.reusablePool[cellID] = [NSHashTable weakObjectsHashTable]; } ///行数 - (NSInteger)numberOfRowsInScrollView:(UIScrollView *)scrollView { - return 20; + return 20; } ///行高 - (CGFloat)scrollView:(UIScrollView *)scrollView heightForRowAtIndex:(NSInteger)index { - return 0; + return 100; } ///行内容 - (UIView *)scrollView:(UIScrollView *)scrollView cellForRowAtIndex:(NSInteger)index{ - UIView *view = [UIView new]; - view.backgroundColor = SL_UIColorFromRandomColor; - return view; + UILabel *label = [UILabel new]; + label.backgroundColor = SL_UIColorFromRandomColor; + label.text = [NSString stringWithFormat:@"第 %ld 个",(long)index]; + return label; } ///点击行 - (void)scrollView:(UIScrollView *)scrollView didSelectRowAtIndex:(NSInteger)index { } -#pragma mark - EventsHandle - #pragma mark - UIScrollViewDelegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView { + + + + } - - @end From e944eda5bf806f0e8f816bfa7c071dacb675ceb7 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sun, 14 Jun 2020 00:25:36 +0800 Subject: [PATCH 007/356] =?UTF-8?q?UITableView=E7=9A=84=E5=8E=9F=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WKWebView/SLTableViewController.m | 79 +++++++++++++++---- 1 file changed, 65 insertions(+), 14 deletions(-) diff --git a/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m b/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m index ec774a1b..89b3fa96 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m +++ b/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m @@ -19,6 +19,12 @@ @interface SLTableViewController () /// 每一行的坐标位置 @property (nonatomic, strong) NSMutableArray *frameArray; +///记录最后一次的偏移量,用来判断滑动方向 +@property (nonatomic, assign) CGFloat lastContentOffsetY; +///上边即将展示的索引 +@property (nonatomic, assign) NSInteger willDisplayIndexUp; +///下边即将展示的索引 +@property (nonatomic, assign) NSInteger willDisplayIndexDown; @end @@ -65,14 +71,28 @@ - (NSMutableArray *)frameArray { return _frameArray; } +#pragma mark - Setter +- (void)setWillDisplayIndexUp:(NSInteger)willDisplayIndexUp{ + _willDisplayIndexUp = willDisplayIndexUp; + _willDisplayIndexUp >= 0 ? _willDisplayIndexUp : -1; +} +- (void)setWillDisplayIndexDown:(NSInteger)willDisplayIndexDown { + NSInteger count = [self numberOfRowsInScrollView:self.scrollView]; + _willDisplayIndexDown = willDisplayIndexDown; + _willDisplayIndexDown < count ? _willDisplayIndexDown : count; +} + + #pragma mark - Help Methods ///刷新数据 - (void)reloadData { //清空布局信息 [self.frameArray removeAllObjects]; + self.willDisplayIndexUp = -1; + self.willDisplayIndexDown = 0; + //数据源个数 NSInteger count = [self numberOfRowsInScrollView:self.scrollView]; - CGFloat y = 0; //获取每一行的布局信息 for (int i = 0; i < count; i++) { @@ -80,6 +100,10 @@ - (void)reloadData { CGRect rect = CGRectMake(0, y, self.scrollView.sl_width, cellHeight); [self.frameArray addObject:[NSValue valueWithCGRect:rect]]; + if (rect.origin.y + rect.size.height < self.scrollView.contentOffset.y) { + self.willDisplayIndexUp = i; + } + //按需加载 只加载坐标位置是在当前窗口显示的视图 if (rect.origin.y + rect.size.height >= self.scrollView.contentOffset.y && rect.origin.y <= self.scrollView.contentOffset.y + self.scrollView.sl_height) { UIView *view = [self scrollView:self.scrollView cellForRowAtIndex:i]; @@ -87,6 +111,10 @@ - (void)reloadData { [self.scrollView addSubview:view]; } + if (rect.origin.y > self.scrollView.contentOffset.y + self.scrollView.sl_height && self.willDisplayIndexDown == 0) { + self.willDisplayIndexDown = i; + } + //下一行的起始纵坐标 y += cellHeight; @@ -96,7 +124,6 @@ - (void)reloadData { } } - // NSArray *aa = [self indexForVisibleRows]; } //当前可见的cell - (NSArray *)visibleCells { @@ -113,15 +140,39 @@ - (NSArray *)indexForVisibleRows { } return indexs; } -//即将显示cell -- (void)willDisplayCell{ - - - +//即将显示cell YES上 NO下 +- (void)willDisplayCellWithDirection:(BOOL)up { + if(up) { + if (_willDisplayIndexUp < 0) return; + NSLog(@"上"); + CGRect rect = [self.frameArray[self.willDisplayIndexUp] CGRectValue]; + //按需加载 只加载坐标位置是在当前窗口显示的视图 + if (rect.origin.y + rect.size.height >= self.scrollView.contentOffset.y && rect.origin.y <= self.scrollView.contentOffset.y + self.scrollView.sl_height) { + UIView *view = [self scrollView:self.scrollView cellForRowAtIndex:self.willDisplayIndexUp]; + view.frame = rect; + [self.scrollView addSubview:view]; + self.willDisplayIndexUp -=1; + } + }else { + NSInteger count = [self numberOfRowsInScrollView:self.scrollView]; + if (_willDisplayIndexDown == count) return; + NSLog(@"下"); + CGRect rect = [self.frameArray[self.willDisplayIndexDown] CGRectValue]; + //按需加载 只加载坐标位置是在当前窗口显示的视图 + if (rect.origin.y + rect.size.height >= self.scrollView.contentOffset.y && rect.origin.y <= self.scrollView.contentOffset.y + self.scrollView.sl_height) { + UIView *view = [self scrollView:self.scrollView cellForRowAtIndex:self.willDisplayIndexDown]; + view.frame = rect; + [self.scrollView addSubview:view]; + self.willDisplayIndexDown +=1; + } + } } ///根据cellID去复用池reusablePool取可重用的view,如果没有,返回nil - (UIView *)dequeueReusableCellWithIdentifier:(nonnull NSString *)cellID { + + + return nil; } ///注册样式 @@ -130,7 +181,7 @@ - (void)registerClass:(Class)class forCellReuseIdentifier:(NSString *)cellID { } ///行数 - (NSInteger)numberOfRowsInScrollView:(UIScrollView *)scrollView { - return 20; + return 30; } ///行高 - (CGFloat)scrollView:(UIScrollView *)scrollView heightForRowAtIndex:(NSInteger)index { @@ -150,12 +201,12 @@ - (void)scrollView:(UIScrollView *)scrollView didSelectRowAtIndex:(NSInteger)ind #pragma mark - UIScrollViewDelegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView { - - - - - - + if(scrollView.contentOffset.y > self.lastContentOffsetY) { + [self willDisplayCellWithDirection:NO]; + }else { + [self willDisplayCellWithDirection:YES]; + } + self.lastContentOffsetY = scrollView.contentOffset.y; } @end From a100c8464e5cc6a0cb684a34cb88a9caeffec2bb Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sun, 14 Jun 2020 02:16:36 +0800 Subject: [PATCH 008/356] =?UTF-8?q?UITableView=E7=9A=84=E5=8E=9F=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WKWebView/SLTableViewController.m | 149 +++++++++++------- 1 file changed, 92 insertions(+), 57 deletions(-) diff --git a/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m b/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m index 89b3fa96..c7a16d2d 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m +++ b/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m @@ -8,6 +8,12 @@ #import "SLTableViewController.h" +@interface SLScrollViewCell : UILabel +@property (nonatomic, copy) NSString *cellID; +@end +@implementation SLScrollViewCell +@end + @interface SLTableViewController () { UITableView *tableView; @@ -18,13 +24,15 @@ @interface SLTableViewController () @property (nonatomic, strong) NSMutableDictionary *> *reusablePool; /// 每一行的坐标位置 @property (nonatomic, strong) NSMutableArray *frameArray; +/// 当前可见的cells +@property (nonatomic, strong) NSMutableArray *visibleCells; ///记录最后一次的偏移量,用来判断滑动方向 @property (nonatomic, assign) CGFloat lastContentOffsetY; -///上边即将展示的索引 -@property (nonatomic, assign) NSInteger willDisplayIndexUp; -///下边即将展示的索引 -@property (nonatomic, assign) NSInteger willDisplayIndexDown; +///顶部即将展示的索引 +@property (nonatomic, assign) NSInteger willDisplayIndexTop; +///底部即将展示的索引 +@property (nonatomic, assign) NSInteger willDisplayIndexBottom; @end @@ -40,6 +48,7 @@ - (void)viewDidLoad { - (void)setupUI { self.view.backgroundColor = [UIColor whiteColor]; [self.view addSubview:self.scrollView]; + [self registerClass:[SLScrollViewCell class] forCellReuseIdentifier:@"cellID"]; [self reloadData]; } @@ -70,29 +79,32 @@ - (NSMutableArray *)frameArray { } return _frameArray; } +- (NSMutableArray *)visibleCells { + if (!_visibleCells) { + _visibleCells = [NSMutableArray array]; + } + return _visibleCells;; +} #pragma mark - Setter -- (void)setWillDisplayIndexUp:(NSInteger)willDisplayIndexUp{ - _willDisplayIndexUp = willDisplayIndexUp; - _willDisplayIndexUp >= 0 ? _willDisplayIndexUp : -1; +- (void)setwillDisplayIndexTop:(NSInteger)willDisplayIndexTop{ + _willDisplayIndexTop = willDisplayIndexTop >= 0 ? willDisplayIndexTop : -1; } -- (void)setWillDisplayIndexDown:(NSInteger)willDisplayIndexDown { +- (void)setwillDisplayIndexBottom:(NSInteger)willDisplayIndexBottom { NSInteger count = [self numberOfRowsInScrollView:self.scrollView]; - _willDisplayIndexDown = willDisplayIndexDown; - _willDisplayIndexDown < count ? _willDisplayIndexDown : count; + _willDisplayIndexBottom = willDisplayIndexBottom < count ? willDisplayIndexBottom : count; } - #pragma mark - Help Methods ///刷新数据 - (void)reloadData { //清空布局信息 [self.frameArray removeAllObjects]; - self.willDisplayIndexUp = -1; - self.willDisplayIndexDown = 0; - + self.willDisplayIndexTop = -1; //数据源个数 NSInteger count = [self numberOfRowsInScrollView:self.scrollView]; + self.willDisplayIndexBottom = count; + CGFloat y = 0; //获取每一行的布局信息 for (int i = 0; i < count; i++) { @@ -101,79 +113,99 @@ - (void)reloadData { [self.frameArray addObject:[NSValue valueWithCGRect:rect]]; if (rect.origin.y + rect.size.height < self.scrollView.contentOffset.y) { - self.willDisplayIndexUp = i; + self.willDisplayIndexTop = i; } //按需加载 只加载坐标位置是在当前窗口显示的视图 if (rect.origin.y + rect.size.height >= self.scrollView.contentOffset.y && rect.origin.y <= self.scrollView.contentOffset.y + self.scrollView.sl_height) { - UIView *view = [self scrollView:self.scrollView cellForRowAtIndex:i]; - view.frame = rect; - [self.scrollView addSubview:view]; + SLScrollViewCell *cell = [self scrollView:self.scrollView cellForRowAtIndex:i]; + cell.frame = rect; + [self.scrollView addSubview:cell]; + [self.visibleCells addObject:cell]; } - if (rect.origin.y > self.scrollView.contentOffset.y + self.scrollView.sl_height && self.willDisplayIndexDown == 0) { - self.willDisplayIndexDown = i; + if (rect.origin.y > self.scrollView.contentOffset.y + self.scrollView.sl_height && self.willDisplayIndexBottom == count) { + self.willDisplayIndexBottom = i; } //下一行的起始纵坐标 y += cellHeight; - //最后 确定了内容大小 + //最后 确定了内容大小contentSize if (i == count - 1) { self.scrollView.contentSize = CGSizeMake(self.scrollView.sl_width, y); } } - -} -//当前可见的cell -- (NSArray *)visibleCells { - return self.scrollView.subviews; } //当前可见cell的索引 其实绘制cell的时候就可以先保存可见的索引,不用每次遍历查询 - (NSArray *)indexForVisibleRows { NSMutableArray *indexs = [NSMutableArray array]; - for (int i = 0; i < self.frameArray.count; i++) { - CGRect rect = [self.frameArray[i] CGRectValue]; - if (rect.origin.y + rect.size.height >= self.scrollView.contentOffset.y && rect.origin.y <= self.scrollView.contentOffset.y + self.scrollView.sl_height) { - [indexs addObject:@(i)]; - } + for (NSInteger i = self.willDisplayIndexTop+1; i < self.willDisplayIndexBottom; i++) { + [indexs addObject:@(i)]; } return indexs; } -//即将显示cell YES上 NO下 -- (void)willDisplayCellWithDirection:(BOOL)up { - if(up) { - if (_willDisplayIndexUp < 0) return; +//即将显示的cell,显示时创建或从缓存池中取出调整坐标位置 top:YES上/NO下 +- (void)willDisplayCellWithDirection:(BOOL)top { + if(top) { + if (_willDisplayIndexTop < 0) return; NSLog(@"上"); - CGRect rect = [self.frameArray[self.willDisplayIndexUp] CGRectValue]; + CGRect rect = [self.frameArray[self.willDisplayIndexTop] CGRectValue]; //按需加载 只加载坐标位置是在当前窗口显示的视图 if (rect.origin.y + rect.size.height >= self.scrollView.contentOffset.y && rect.origin.y <= self.scrollView.contentOffset.y + self.scrollView.sl_height) { - UIView *view = [self scrollView:self.scrollView cellForRowAtIndex:self.willDisplayIndexUp]; - view.frame = rect; - [self.scrollView addSubview:view]; - self.willDisplayIndexUp -=1; + SLScrollViewCell *cell = [self scrollView:self.scrollView cellForRowAtIndex:self.willDisplayIndexTop]; + cell.frame = rect; + [self.scrollView addSubview:cell]; + self.willDisplayIndexTop -=1; + [self.visibleCells insertObject:cell atIndex:0]; } }else { NSInteger count = [self numberOfRowsInScrollView:self.scrollView]; - if (_willDisplayIndexDown == count) return; + if (_willDisplayIndexBottom == count) return; NSLog(@"下"); - CGRect rect = [self.frameArray[self.willDisplayIndexDown] CGRectValue]; + CGRect rect = [self.frameArray[self.willDisplayIndexBottom] CGRectValue]; //按需加载 只加载坐标位置是在当前窗口显示的视图 if (rect.origin.y + rect.size.height >= self.scrollView.contentOffset.y && rect.origin.y <= self.scrollView.contentOffset.y + self.scrollView.sl_height) { - UIView *view = [self scrollView:self.scrollView cellForRowAtIndex:self.willDisplayIndexDown]; - view.frame = rect; - [self.scrollView addSubview:view]; - self.willDisplayIndexDown +=1; + SLScrollViewCell *cell = [self scrollView:self.scrollView cellForRowAtIndex:self.willDisplayIndexBottom]; + cell.frame = rect; + [self.scrollView addSubview:cell]; + self.willDisplayIndexBottom +=1; + [self.visibleCells addObject:cell]; + } + } +} +//即将消失的cell,在消失时放入缓冲池里 top:YES上/NO下 +- (void)willDisappearCellWithDirection:(BOOL)top { + if(top) { + CGRect rect = [self.frameArray[self.willDisplayIndexTop+1] CGRectValue]; + if (rect.origin.y + rect.size.height < self.scrollView.contentOffset.y) { + self.willDisplayIndexTop = self.willDisplayIndexTop+1; + SLScrollViewCell *cell = self.visibleCells.firstObject; + NSHashTable * hashTable= self.reusablePool[cell.cellID]; + [hashTable addObject:cell]; + [self.visibleCells removeObjectAtIndex:0]; + } + }else { + CGRect rect = [self.frameArray[self.willDisplayIndexBottom-1] CGRectValue]; + if (rect.origin.y > self.scrollView.contentOffset.y + self.scrollView.sl_height) { + self.willDisplayIndexBottom = self.willDisplayIndexBottom-1; + SLScrollViewCell *cell = self.visibleCells.lastObject; + NSHashTable * hashTable= self.reusablePool[cell.cellID]; + [hashTable addObject:cell]; + [self.visibleCells removeLastObject]; } } } -///根据cellID去复用池reusablePool取可重用的view,如果没有,返回nil -- (UIView *)dequeueReusableCellWithIdentifier:(nonnull NSString *)cellID { - - - - return nil; +///根据cellID去复用池reusablePool取可重用的view,如果没有,重新创建一个新对象返回 +- (SLScrollViewCell *)dequeueReusableCellWithIdentifier:(nonnull NSString *)cellID{ + NSHashTable *hashTable = self.reusablePool[cellID]; + SLScrollViewCell *cell = hashTable.allObjects.firstObject; + if (cell == nil) { + cell = [[SLScrollViewCell alloc] init]; + cell.cellID = cellID; + } + return cell; } ///注册样式 - (void)registerClass:(Class)class forCellReuseIdentifier:(NSString *)cellID { @@ -188,11 +220,12 @@ - (CGFloat)scrollView:(UIScrollView *)scrollView heightForRowAtIndex:(NSInteger) return 100; } ///行内容 -- (UIView *)scrollView:(UIScrollView *)scrollView cellForRowAtIndex:(NSInteger)index{ - UILabel *label = [UILabel new]; - label.backgroundColor = SL_UIColorFromRandomColor; - label.text = [NSString stringWithFormat:@"第 %ld 个",(long)index]; - return label; +- (SLScrollViewCell *)scrollView:(UIScrollView *)scrollView cellForRowAtIndex:(NSInteger)index{ + SLScrollViewCell *cell = [self dequeueReusableCellWithIdentifier:@"cellID"]; + cell.layer.borderWidth = 3; + cell.text = [NSString stringWithFormat:@"第 %ld 个",(long)index]; + cell.textAlignment = NSTextAlignmentCenter; + return cell; } ///点击行 - (void)scrollView:(UIScrollView *)scrollView didSelectRowAtIndex:(NSInteger)index { @@ -203,8 +236,10 @@ - (void)scrollView:(UIScrollView *)scrollView didSelectRowAtIndex:(NSInteger)ind - (void)scrollViewDidScroll:(UIScrollView *)scrollView { if(scrollView.contentOffset.y > self.lastContentOffsetY) { [self willDisplayCellWithDirection:NO]; + [self willDisappearCellWithDirection:YES]; }else { [self willDisplayCellWithDirection:YES]; + [self willDisappearCellWithDirection:NO]; } self.lastContentOffsetY = scrollView.contentOffset.y; } From 1916fa136c74c258c11a0730964c56efbca02062 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sun, 14 Jun 2020 17:45:51 +0800 Subject: [PATCH 009/356] =?UTF-8?q?UITableView=E5=8E=9F=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WKWebView/SLTableViewController.m | 241 +++++++++++------- .../WKWebView/SLWebViewListController.m | 2 +- 2 files changed, 150 insertions(+), 93 deletions(-) diff --git a/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m b/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m index c7a16d2d..02a1cc15 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m +++ b/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m @@ -8,65 +8,64 @@ #import "SLTableViewController.h" -@interface SLScrollViewCell : UILabel +@interface SLTableViewCell : UIButton @property (nonatomic, copy) NSString *cellID; +@property (nonatomic, assign) NSInteger index; @end -@implementation SLScrollViewCell +@implementation SLTableViewCell @end -@interface SLTableViewController () -{ - UITableView *tableView; -} +@class SLTableView; +@protocol SLTableViewDataSource +@required +///行数 +- (NSInteger)numberOfRowsInTableView:(SLTableView *)tableView; +///行高 +- (CGFloat)tableView:(SLTableView *)tableView heightForRowAtIndex:(NSInteger)index; +///行内容 +- (SLTableViewCell *)tableView:(SLTableView *)tableView cellForRowAtIndex:(NSInteger)index; +@end +@protocol SLTableViewDelegate +///选中行 +- (void)tableView:(SLTableView *)tableView didSelectRowAtIndex:(NSInteger)index; +@end -@property (nonatomic, strong) UIScrollView *scrollView; +@interface SLTableView : UIScrollView ///复用池 @property (nonatomic, strong) NSMutableDictionary *> *reusablePool; /// 每一行的坐标位置 @property (nonatomic, strong) NSMutableArray *frameArray; /// 当前可见的cells -@property (nonatomic, strong) NSMutableArray *visibleCells; - +@property (nonatomic, strong) NSMutableArray *visibleCells; ///记录最后一次的偏移量,用来判断滑动方向 @property (nonatomic, assign) CGFloat lastContentOffsetY; ///顶部即将展示的索引 @property (nonatomic, assign) NSInteger willDisplayIndexTop; ///底部即将展示的索引 @property (nonatomic, assign) NSInteger willDisplayIndexBottom; - +///数据源代理 +@property (nonatomic, weak) iddelegate; +///数据源代理 +@property (nonatomic, weak) iddataSource; @end -@implementation SLTableViewController - +@implementation SLTableView +@dynamic delegate; #pragma mark - Override -- (void)viewDidLoad { - [super viewDidLoad]; - [self setupUI]; +- (void)willMoveToSuperview:(UIView *)newSuperview { + if (newSuperview) { + [self addKVO]; + } } - -#pragma mark - UI -- (void)setupUI { - self.view.backgroundColor = [UIColor whiteColor]; - [self.view addSubview:self.scrollView]; - [self registerClass:[SLScrollViewCell class] forCellReuseIdentifier:@"cellID"]; - [self reloadData]; +- (void)dealloc { + [self removeKVO]; } -#pragma mark - Data - -#pragma mark - Getter -- (UIScrollView *)scrollView { - if (!_scrollView) { - _scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; - _scrollView.delegate = self; - if (@available(iOS 11.0, *)) { - _scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; - } else { - self.automaticallyAdjustsScrollViewInsets = NO; - } - } - return _scrollView; +#pragma mark - Setter +- (void)setDelegate:(id)delegate{ + [super setDelegate:delegate]; } +#pragma mark - Getter - (NSMutableDictionary *)reusablePool { if (!_reusablePool) { _reusablePool = [NSMutableDictionary dictionary]; @@ -85,14 +84,32 @@ - (NSMutableArray *)visibleCells { } return _visibleCells;; } +- (id)delegate{ + id curDelegate = [super delegate]; + return curDelegate; +} -#pragma mark - Setter -- (void)setwillDisplayIndexTop:(NSInteger)willDisplayIndexTop{ - _willDisplayIndexTop = willDisplayIndexTop >= 0 ? willDisplayIndexTop : -1; +#pragma mark - KVO +- (void)addKVO { + [self addObserver:self + forKeyPath:@"contentOffset" + options:NSKeyValueObservingOptionNew + context:nil]; +} +- (void)removeKVO{ + [self removeObserver:self forKeyPath:@"contentOffset"]; } -- (void)setwillDisplayIndexBottom:(NSInteger)willDisplayIndexBottom { - NSInteger count = [self numberOfRowsInScrollView:self.scrollView]; - _willDisplayIndexBottom = willDisplayIndexBottom < count ? willDisplayIndexBottom : count; +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ + if(object == self && [keyPath isEqualToString:@"contentOffset"]) { + if(self.contentOffset.y > self.lastContentOffsetY) { + [self willDisplayCellWithDirection:NO]; + [self willDisappearCellWithDirection:YES]; + }else { + [self willDisplayCellWithDirection:YES]; + [self willDisappearCellWithDirection:NO]; + } + self.lastContentOffsetY = self.contentOffset.y; + } } #pragma mark - Help Methods @@ -102,29 +119,29 @@ - (void)reloadData { [self.frameArray removeAllObjects]; self.willDisplayIndexTop = -1; //数据源个数 - NSInteger count = [self numberOfRowsInScrollView:self.scrollView]; + NSInteger count = [self.dataSource numberOfRowsInTableView:self]; self.willDisplayIndexBottom = count; CGFloat y = 0; //获取每一行的布局信息 for (int i = 0; i < count; i++) { - CGFloat cellHeight = [self scrollView:self.scrollView heightForRowAtIndex:i]; - CGRect rect = CGRectMake(0, y, self.scrollView.sl_width, cellHeight); + CGFloat cellHeight = [self.dataSource tableView:self heightForRowAtIndex:i]; + CGRect rect = CGRectMake(0, y, self.sl_width, cellHeight); [self.frameArray addObject:[NSValue valueWithCGRect:rect]]; - if (rect.origin.y + rect.size.height < self.scrollView.contentOffset.y) { + if (rect.origin.y + rect.size.height < self.contentOffset.y) { self.willDisplayIndexTop = i; } //按需加载 只加载坐标位置是在当前窗口显示的视图 - if (rect.origin.y + rect.size.height >= self.scrollView.contentOffset.y && rect.origin.y <= self.scrollView.contentOffset.y + self.scrollView.sl_height) { - SLScrollViewCell *cell = [self scrollView:self.scrollView cellForRowAtIndex:i]; + if (rect.origin.y + rect.size.height >= self.contentOffset.y && rect.origin.y <= self.contentOffset.y + self.sl_height) { + SLTableViewCell *cell = [self.dataSource tableView:self cellForRowAtIndex:i]; cell.frame = rect; - [self.scrollView addSubview:cell]; + [self addSubview:cell]; [self.visibleCells addObject:cell]; } - if (rect.origin.y > self.scrollView.contentOffset.y + self.scrollView.sl_height && self.willDisplayIndexBottom == count) { + if (rect.origin.y > self.contentOffset.y + self.sl_height && self.willDisplayIndexBottom == count) { self.willDisplayIndexBottom = i; } @@ -133,11 +150,11 @@ - (void)reloadData { //最后 确定了内容大小contentSize if (i == count - 1) { - self.scrollView.contentSize = CGSizeMake(self.scrollView.sl_width, y); + self.contentSize = CGSizeMake(self.sl_width, y); } } } -//当前可见cell的索引 其实绘制cell的时候就可以先保存可见的索引,不用每次遍历查询 +///当前可见cell的索引 其实绘制cell的时候就可以先保存可见的索引,不用每次遍历查询 - (NSArray *)indexForVisibleRows { NSMutableArray *indexs = [NSMutableArray array]; for (NSInteger i = self.willDisplayIndexTop+1; i < self.willDisplayIndexBottom; i++) { @@ -145,30 +162,30 @@ - (NSArray *)indexForVisibleRows { } return indexs; } -//即将显示的cell,显示时创建或从缓存池中取出调整坐标位置 top:YES上/NO下 +///即将显示的cell,显示时创建或从缓存池中取出调整坐标位置 top:YES上/NO下 - (void)willDisplayCellWithDirection:(BOOL)top { if(top) { if (_willDisplayIndexTop < 0) return; - NSLog(@"上"); CGRect rect = [self.frameArray[self.willDisplayIndexTop] CGRectValue]; //按需加载 只加载坐标位置是在当前窗口显示的视图 - if (rect.origin.y + rect.size.height >= self.scrollView.contentOffset.y && rect.origin.y <= self.scrollView.contentOffset.y + self.scrollView.sl_height) { - SLScrollViewCell *cell = [self scrollView:self.scrollView cellForRowAtIndex:self.willDisplayIndexTop]; + if (rect.origin.y + rect.size.height >= self.contentOffset.y && rect.origin.y <= self.contentOffset.y + self.sl_height) { + NSLog(@"上 第 %ld 个cell显示",self.willDisplayIndexTop); + SLTableViewCell *cell = [self.dataSource tableView:self cellForRowAtIndex:self.willDisplayIndexTop]; cell.frame = rect; - [self.scrollView addSubview:cell]; + [self addSubview:cell]; self.willDisplayIndexTop -=1; [self.visibleCells insertObject:cell atIndex:0]; } }else { - NSInteger count = [self numberOfRowsInScrollView:self.scrollView]; + NSInteger count = [self.dataSource numberOfRowsInTableView:self]; if (_willDisplayIndexBottom == count) return; - NSLog(@"下"); CGRect rect = [self.frameArray[self.willDisplayIndexBottom] CGRectValue]; //按需加载 只加载坐标位置是在当前窗口显示的视图 - if (rect.origin.y + rect.size.height >= self.scrollView.contentOffset.y && rect.origin.y <= self.scrollView.contentOffset.y + self.scrollView.sl_height) { - SLScrollViewCell *cell = [self scrollView:self.scrollView cellForRowAtIndex:self.willDisplayIndexBottom]; + if (rect.origin.y + rect.size.height >= self.contentOffset.y && rect.origin.y <= self.contentOffset.y + self.sl_height) { + NSLog(@"下 第 %ld 个cell显示",self.willDisplayIndexBottom); + SLTableViewCell *cell = [self.dataSource tableView:self cellForRowAtIndex:self.willDisplayIndexBottom]; cell.frame = rect; - [self.scrollView addSubview:cell]; + [self addSubview:cell]; self.willDisplayIndexBottom +=1; [self.visibleCells addObject:cell]; } @@ -178,70 +195,110 @@ - (void)willDisplayCellWithDirection:(BOOL)top { - (void)willDisappearCellWithDirection:(BOOL)top { if(top) { CGRect rect = [self.frameArray[self.willDisplayIndexTop+1] CGRectValue]; - if (rect.origin.y + rect.size.height < self.scrollView.contentOffset.y) { + if (rect.origin.y + rect.size.height < self.contentOffset.y) { self.willDisplayIndexTop = self.willDisplayIndexTop+1; - SLScrollViewCell *cell = self.visibleCells.firstObject; + NSLog(@"上 第 %ld 个cell消失",self.willDisplayIndexTop); + SLTableViewCell *cell = self.visibleCells.firstObject; NSHashTable * hashTable= self.reusablePool[cell.cellID]; [hashTable addObject:cell]; [self.visibleCells removeObjectAtIndex:0]; } }else { CGRect rect = [self.frameArray[self.willDisplayIndexBottom-1] CGRectValue]; - if (rect.origin.y > self.scrollView.contentOffset.y + self.scrollView.sl_height) { + if (rect.origin.y > self.contentOffset.y + self.sl_height) { self.willDisplayIndexBottom = self.willDisplayIndexBottom-1; - SLScrollViewCell *cell = self.visibleCells.lastObject; + NSLog(@"下 第 %ld 个cell消失",self.willDisplayIndexBottom); + SLTableViewCell *cell = self.visibleCells.lastObject; NSHashTable * hashTable= self.reusablePool[cell.cellID]; [hashTable addObject:cell]; [self.visibleCells removeLastObject]; } } } - -///根据cellID去复用池reusablePool取可重用的view,如果没有,重新创建一个新对象返回 -- (SLScrollViewCell *)dequeueReusableCellWithIdentifier:(nonnull NSString *)cellID{ +///根据cellID从复用池reusablePool取可重用的view,如果没有,重新创建一个新对象返回 +- (SLTableViewCell *)dequeueReusableCellWithIdentifier:(nonnull NSString *)cellID index:(NSInteger)index{ NSHashTable *hashTable = self.reusablePool[cellID]; - SLScrollViewCell *cell = hashTable.allObjects.firstObject; + SLTableViewCell *cell = hashTable.allObjects.firstObject; if (cell == nil) { - cell = [[SLScrollViewCell alloc] init]; + //复用池reusablePool没有可重用的,就重新创建一个新对象返回 + cell = [[SLTableViewCell alloc] init]; + [cell addTarget:self action:@selector(didSelectedAction:) forControlEvents:UIControlEventTouchUpInside]; cell.cellID = cellID; + }else { + //从缓冲池中取出可重用的cell + [hashTable removeObject:cell]; } + cell.index = index; return cell; } ///注册样式 - (void)registerClass:(Class)class forCellReuseIdentifier:(NSString *)cellID { self.reusablePool[cellID] = [NSHashTable weakObjectsHashTable]; } + +#pragma mark - +- (void)didSelectedAction:(SLTableViewCell *)cell { + [self.delegate tableView:self didSelectRowAtIndex:cell.index]; +} +@end + +@interface SLTableViewController () +@property (nonatomic, strong) SLTableView *tableView; +@end + +@implementation SLTableViewController +#pragma mark - Override +- (void)viewDidLoad { + [super viewDidLoad]; + [self setupUI]; +} + +#pragma mark - UI +- (void)setupUI { + self.view.backgroundColor = [UIColor whiteColor]; + [self.view addSubview:self.tableView]; + [self.tableView reloadData]; +} + +#pragma mark - Getter +- (SLTableView *)tableView { + if (!_tableView) { + _tableView = [[SLTableView alloc] initWithFrame:self.view.bounds]; + _tableView.dataSource = self; + _tableView.delegate = self; + if (@available(iOS 11.0, *)) { + _tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } else { + self.automaticallyAdjustsScrollViewInsets = NO; + } + [_tableView registerClass:[SLTableViewCell class] forCellReuseIdentifier:@"cellID"]; + } + return _tableView; +} + +#pragma mark - SLTableViewDataSource ///行数 -- (NSInteger)numberOfRowsInScrollView:(UIScrollView *)scrollView { - return 30; +- (NSInteger)numberOfRowsInTableView:(SLTableView *)tableView { + return 40; } ///行高 -- (CGFloat)scrollView:(UIScrollView *)scrollView heightForRowAtIndex:(NSInteger)index { +- (CGFloat)tableView:(SLTableView *)tableView heightForRowAtIndex:(NSInteger)index { return 100; } ///行内容 -- (SLScrollViewCell *)scrollView:(UIScrollView *)scrollView cellForRowAtIndex:(NSInteger)index{ - SLScrollViewCell *cell = [self dequeueReusableCellWithIdentifier:@"cellID"]; +- (SLTableViewCell *)tableView:(SLTableView *)tableView cellForRowAtIndex:(NSInteger)index { + SLTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellID" index:index]; cell.layer.borderWidth = 3; - cell.text = [NSString stringWithFormat:@"第 %ld 个",(long)index]; - cell.textAlignment = NSTextAlignmentCenter; + [cell setTitle:[NSString stringWithFormat:@"第 %ld 个",(long)index] forState:UIControlStateNormal]; + [cell setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + cell.titleLabel.textAlignment = NSTextAlignmentCenter; return cell; } -///点击行 -- (void)scrollView:(UIScrollView *)scrollView didSelectRowAtIndex:(NSInteger)index { - -} -#pragma mark - UIScrollViewDelegate -- (void)scrollViewDidScroll:(UIScrollView *)scrollView { - if(scrollView.contentOffset.y > self.lastContentOffsetY) { - [self willDisplayCellWithDirection:NO]; - [self willDisappearCellWithDirection:YES]; - }else { - [self willDisplayCellWithDirection:YES]; - [self willDisappearCellWithDirection:NO]; - } - self.lastContentOffsetY = scrollView.contentOffset.y; +#pragma mark - SLTableViewDelegate +///选中行 +- (void)tableView:(SLTableView *)tableView didSelectRowAtIndex:(NSInteger)index { + NSLog(@"选中 %ld",(long)index); } @end diff --git a/iOS_Tips/DarkMode/WKWebView/SLWebViewListController.m b/iOS_Tips/DarkMode/WKWebView/SLWebViewListController.m index 33f453f9..884ae2f0 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLWebViewListController.m +++ b/iOS_Tips/DarkMode/WKWebView/SLWebViewListController.m @@ -55,7 +55,7 @@ - (void)getData { @" WKWebView离线缓存", @" WKWebView渲染的部分HTML元素替换为用原生组件显示(doing)", @" UIScrollView的实现原理", - @" UITableView的原理 (doing)"]]; + @" UITableView的原理"]]; [self.subTitles addObjectsFromArray:@[@" WKWebView的使用、JS和OC的交互、网页内容加载进度条的实现、NSNSURLProtocol拦截、Cookies丢失、设置UserAgent", @" tableView.tableHeaderView = webView 撑开webView ", @" [webView.scrollView addSubview:tableView] + 占位Div ", From f88cd25aab9217a6e581415252c83e0d917dc6a3 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sun, 14 Jun 2020 20:14:42 +0800 Subject: [PATCH 010/356] =?UTF-8?q?UITableView=E5=A4=8D=E7=94=A8=E5=8E=9F?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 6 + .../DarkMode/WKWebView/SLReusableManager.h | 35 +++ .../DarkMode/WKWebView/SLReusableManager.m | 221 ++++++++++++++++++ .../WKWebView/SLTableViewController.m | 3 +- .../WKWebView/SLWebViewListController.m | 2 +- 5 files changed, 264 insertions(+), 3 deletions(-) create mode 100644 iOS_Tips/DarkMode/WKWebView/SLReusableManager.h create mode 100644 iOS_Tips/DarkMode/WKWebView/SLReusableManager.m diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 1dd1ac23..f9abfff4 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -100,6 +100,7 @@ 7884247F2492102900C2E505 /* SLWorkIssuesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7884247E2492102900C2E505 /* SLWorkIssuesViewController.m */; }; 788424822492159F00C2E505 /* SLNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 788424812492159F00C2E505 /* SLNavigationController.m */; }; 7884248B2493851B00C2E505 /* SLViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7884248A2493851B00C2E505 /* SLViewController.m */; }; + 7884248E24963FD200C2E505 /* SLReusableManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 7884248D24963FD200C2E505 /* SLReusableManager.m */; }; 788ACD622390BFD400737EC2 /* SLLoadImageVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 788ACD612390BFD400737EC2 /* SLLoadImageVC.m */; }; 788ACD652390EA3A00737EC2 /* SLCubeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 788ACD642390EA3A00737EC2 /* SLCubeViewController.m */; }; 788ADB382441F48F00302CD9 /* SLCrashViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 788ADB362441F48F00302CD9 /* SLCrashViewController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; @@ -324,6 +325,8 @@ 788424812492159F00C2E505 /* SLNavigationController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLNavigationController.m; sourceTree = ""; }; 788424892493851B00C2E505 /* SLViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLViewController.h; sourceTree = ""; }; 7884248A2493851B00C2E505 /* SLViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLViewController.m; sourceTree = ""; }; + 7884248C24963FD200C2E505 /* SLReusableManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLReusableManager.h; sourceTree = ""; }; + 7884248D24963FD200C2E505 /* SLReusableManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLReusableManager.m; sourceTree = ""; }; 788ACD602390BFD400737EC2 /* SLLoadImageVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLLoadImageVC.h; sourceTree = ""; }; 788ACD612390BFD400737EC2 /* SLLoadImageVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLLoadImageVC.m; sourceTree = ""; }; 788ACD632390EA3A00737EC2 /* SLCubeViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLCubeViewController.h; sourceTree = ""; }; @@ -947,6 +950,8 @@ 78BDE04A248A6A74002ED386 /* SLUrlProtocolAddCookie.m */, 78BDE04E248E0AFB002ED386 /* SLWebNativeViewController.h */, 78BDE04F248E0AFB002ED386 /* SLWebNativeViewController.m */, + 7884248C24963FD200C2E505 /* SLReusableManager.h */, + 7884248D24963FD200C2E505 /* SLReusableManager.m */, 78842452248F863500C2E505 /* SLTableViewController.h */, 78842453248F863500C2E505 /* SLTableViewController.m */, 78E72D8324822E7500751373 /* WebTableView */, @@ -1289,6 +1294,7 @@ 7851CB362331CC87002295B5 /* SLDarkModeViewController.m in Sources */, 78D30965239688EF00DC373A /* GLESMath.c in Sources */, 788ACD652390EA3A00737EC2 /* SLCubeViewController.m in Sources */, + 7884248E24963FD200C2E505 /* SLReusableManager.m in Sources */, 7857FD4B24729E8500D3D986 /* BSBacktraceLogger.m in Sources */, 78E72D8224811F6600751373 /* SLWebCacheViewController.m in Sources */, 78E72D8F2483DC2600751373 /* SLWebCacheManager.m in Sources */, diff --git a/iOS_Tips/DarkMode/WKWebView/SLReusableManager.h b/iOS_Tips/DarkMode/WKWebView/SLReusableManager.h new file mode 100644 index 00000000..34ce7661 --- /dev/null +++ b/iOS_Tips/DarkMode/WKWebView/SLReusableManager.h @@ -0,0 +1,35 @@ +// +// SLReusableManager.h +// DarkMode +// +// Created by wsl on 2020/6/14. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface SLReusableCell : UIView +@end + +@class SLReusableManager; +@protocol SLReusableDataSource +@required +///行数 +- (NSInteger)numberOfRowsInReusableManager:(SLReusableManager *)reusableManager; +///行位置 +- (CGRect)reusableManager:(SLReusableManager *)reusableManager frameForRowAtIndex:(NSInteger)index; +///行内容 +- (SLReusableCell *)reusableManager:(SLReusableManager *)reusableManager cellForRowAtIndex:(NSInteger)index; +@end +@protocol SLReusableDelegate +///选中行 +- (void)tableView:(SLReusableManager *)reusableManager didSelectRowAtIndex:(NSInteger)index; +@end + +@interface SLReusableManager : NSObject +@property (nonatomic, weak) UIScrollView *scrollView; +@end + +NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/WKWebView/SLReusableManager.m b/iOS_Tips/DarkMode/WKWebView/SLReusableManager.m new file mode 100644 index 00000000..7d46c862 --- /dev/null +++ b/iOS_Tips/DarkMode/WKWebView/SLReusableManager.m @@ -0,0 +1,221 @@ +// +// SLReusableManager.m +// DarkMode +// +// Created by wsl on 2020/6/14. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLReusableManager.h" + +@interface SLReusableCell () +@property (nonatomic, copy) NSString *cellID; +@property (nonatomic, assign) NSInteger index; +@end +@implementation SLReusableCell +@end + +///复用管理 +@interface SLReusableManager () + +///复用池 +@property (nonatomic, strong) NSMutableDictionary *> *reusablePool; +/// 每一行的坐标位置 +@property (nonatomic, strong) NSMutableArray *frameArray; +/// 当前可见的cells +@property (nonatomic, strong) NSMutableArray *visibleCells; +///记录最后一次的偏移量,用来判断滑动方向 +@property (nonatomic, assign) CGFloat lastContentOffsetY; +///顶部即将展示的索引1 +@property (nonatomic, assign) NSInteger willDisplayIndexTop; +///底部即将展示的索引 +@property (nonatomic, assign) NSInteger willDisplayIndexBottom; +///数据源代理 +@property (nonatomic, weak) iddelegate; +///数据源代理 +@property (nonatomic, weak) iddataSource; +@end +@implementation SLReusableManager + +#pragma mark - Override +- (void)willMoveToSuperview:(UIView *)newSuperview { + if (newSuperview) { + [self addKVO]; + } +} +- (void)dealloc { + [self removeKVO]; +} +#pragma mark - Getter +- (NSMutableDictionary *)reusablePool { + if (!_reusablePool) { + _reusablePool = [NSMutableDictionary dictionary]; + } + return _reusablePool;; +} +- (NSMutableArray *)frameArray { + if (!_frameArray) { + _frameArray = [NSMutableArray array]; + } + return _frameArray; +} +- (NSMutableArray *)visibleCells { + if (!_visibleCells) { + _visibleCells = [NSMutableArray array]; + } + return _visibleCells;; +} + +#pragma mark - KVO +- (void)addKVO { + [self.scrollView addObserver:self + forKeyPath:@"contentOffset" + options:NSKeyValueObservingOptionNew + context:nil]; +} +- (void)removeKVO{ + [self.scrollView removeObserver:self forKeyPath:@"contentOffset"]; +} +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ + if(object == self.scrollView && [keyPath isEqualToString:@"contentOffset"]) { + if(self.scrollView.contentOffset.y > self.lastContentOffsetY) { + [self willDisplayCellWithDirection:NO]; + [self willDisappearCellWithDirection:YES]; + }else { + [self willDisplayCellWithDirection:YES]; + [self willDisappearCellWithDirection:NO]; + } + self.lastContentOffsetY = self.scrollView.contentOffset.y; + } +} + +#pragma mark - Help Methods +///刷新数据 +- (void)reloadData { + //清空布局信息 + [self.frameArray removeAllObjects]; + self.willDisplayIndexTop = -1; + //数据源个数 + NSInteger count = [self.dataSource numberOfRowsInReusableManager:self]; + self.willDisplayIndexBottom = count; + + CGFloat y = 0; + //获取每一行的布局信息 + for (int i = 0; i < count; i++) { + CGRect rect = [self.dataSource reusableManager:self frameForRowAtIndex:i]; + [self.frameArray addObject:[NSValue valueWithCGRect:rect]]; + + if (rect.origin.y + rect.size.height < self.scrollView.contentOffset.y) { + self.willDisplayIndexTop = i; + } + + //按需加载 只加载坐标位置是在当前窗口显示的视图 + if (rect.origin.y + rect.size.height >= self.scrollView.contentOffset.y && rect.origin.y <= self.scrollView.contentOffset.y + self.scrollView.sl_height) { + SLReusableCell *cell = [self.dataSource reusableManager:self cellForRowAtIndex:i]; + cell.frame = rect; + [self.scrollView addSubview:cell]; + [self.visibleCells addObject:cell]; + } + + if (rect.origin.y > self.scrollView.contentOffset.y + self.scrollView.sl_height && self.willDisplayIndexBottom == count) { + self.willDisplayIndexBottom = i; + } + + //下一行的起始纵坐标 + y += rect.size.height; + + //最后 确定了内容大小contentSize + if (i == count - 1) { + self.scrollView.contentSize = CGSizeMake(self.scrollView.sl_width, y); + } + } +} +///当前可见cell的索引 其实绘制cell的时候就可以先保存可见的索引,不用每次遍历查询 +- (NSArray *)indexForVisibleRows { + NSMutableArray *indexs = [NSMutableArray array]; + for (NSInteger i = self.willDisplayIndexTop+1; i < self.willDisplayIndexBottom; i++) { + [indexs addObject:@(i)]; + } + return indexs; +} +///即将显示的cell,显示时创建或从缓存池中取出调整坐标位置 top:YES上/NO下 +- (void)willDisplayCellWithDirection:(BOOL)top { + if(top) { + if (_willDisplayIndexTop < 0) return; + CGRect rect = [self.frameArray[self.willDisplayIndexTop] CGRectValue]; + //按需加载 只加载坐标位置是在当前窗口显示的视图 + if (rect.origin.y + rect.size.height >= self.scrollView.contentOffset.y && rect.origin.y <= self.scrollView.contentOffset.y + self.scrollView.sl_height) { + NSLog(@"上 第 %ld 个cell显示",self.willDisplayIndexTop); + SLReusableCell *cell = [self.dataSource reusableManager:self cellForRowAtIndex:self.willDisplayIndexTop]; + cell.frame = rect; + [self.scrollView addSubview:cell]; + self.willDisplayIndexTop -=1; + [self.visibleCells insertObject:cell atIndex:0]; + } + }else { + NSInteger count = [self.dataSource numberOfRowsInReusableManager:self]; + if (_willDisplayIndexBottom == count) return; + CGRect rect = [self.frameArray[self.willDisplayIndexBottom] CGRectValue]; + //按需加载 只加载坐标位置是在当前窗口显示的视图 + if (rect.origin.y + rect.size.height >= self.scrollView.contentOffset.y && rect.origin.y <= self.scrollView.contentOffset.y + self.scrollView.sl_height) { + NSLog(@"下 第 %ld 个cell显示",self.willDisplayIndexBottom); + SLReusableCell *cell = [self.dataSource reusableManager:self cellForRowAtIndex:self.willDisplayIndexBottom]; + cell.frame = rect; + [self.scrollView addSubview:cell]; + self.willDisplayIndexBottom +=1; + [self.visibleCells addObject:cell]; + } + } +} +//即将消失的cell,在消失时放入缓冲池里 top:YES上/NO下 +- (void)willDisappearCellWithDirection:(BOOL)top { + if(top) { + CGRect rect = [self.frameArray[self.willDisplayIndexTop+1] CGRectValue]; + if (rect.origin.y + rect.size.height < self.scrollView.contentOffset.y) { + self.willDisplayIndexTop = self.willDisplayIndexTop+1; + NSLog(@"上 第 %ld 个cell消失",self.willDisplayIndexTop); + SLReusableCell *cell = self.visibleCells.firstObject; + NSHashTable * hashTable= self.reusablePool[cell.cellID]; + [hashTable addObject:cell]; + [self.visibleCells removeObjectAtIndex:0]; + } + }else { + CGRect rect = [self.frameArray[self.willDisplayIndexBottom-1] CGRectValue]; + if (rect.origin.y > self.scrollView.contentOffset.y + self.scrollView.sl_height) { + self.willDisplayIndexBottom = self.willDisplayIndexBottom-1; + NSLog(@"下 第 %ld 个cell消失",self.willDisplayIndexBottom); + SLReusableCell *cell = self.visibleCells.lastObject; + NSHashTable * hashTable= self.reusablePool[cell.cellID]; + [hashTable addObject:cell]; + [self.visibleCells removeLastObject]; + } + } +} +///根据cellID从复用池reusablePool取可重用的view,如果没有,重新创建一个新对象返回 +- (SLReusableCell *)dequeueReusableCellWithIdentifier:(nonnull NSString *)cellID index:(NSInteger)index{ + NSHashTable *hashTable = self.reusablePool[cellID]; + SLReusableCell *cell = hashTable.allObjects.firstObject; + if (cell == nil) { + //复用池reusablePool没有可重用的,就重新创建一个新对象返回 + cell = [[SLReusableCell alloc] init]; + cell.cellID = cellID; + CGRect rect = [self.dataSource reusableManager:self frameForRowAtIndex:index]; + cell.frame = rect; + }else { + //从缓冲池中取出可重用的cell + [hashTable removeObject:cell]; + } + cell.index = index; + return cell; +} +///注册样式 +- (void)registerClass:(Class)class forCellReuseIdentifier:(NSString *)cellID { + self.reusablePool[cellID] = [NSHashTable weakObjectsHashTable]; +} + +#pragma mark - Events Handle +- (void)didSelectedAction:(SLReusableCell *)cell { + [self.delegate tableView:self didSelectRowAtIndex:cell.index]; +} +@end + diff --git a/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m b/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m index 02a1cc15..0ad5b637 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m +++ b/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m @@ -236,7 +236,7 @@ - (void)registerClass:(Class)class forCellReuseIdentifier:(NSString *)cellID { self.reusablePool[cellID] = [NSHashTable weakObjectsHashTable]; } -#pragma mark - +#pragma mark - Events Handle - (void)didSelectedAction:(SLTableViewCell *)cell { [self.delegate tableView:self didSelectRowAtIndex:cell.index]; } @@ -300,5 +300,4 @@ - (SLTableViewCell *)tableView:(SLTableView *)tableView cellForRowAtIndex:(NSInt - (void)tableView:(SLTableView *)tableView didSelectRowAtIndex:(NSInteger)index { NSLog(@"选中 %ld",(long)index); } - @end diff --git a/iOS_Tips/DarkMode/WKWebView/SLWebViewListController.m b/iOS_Tips/DarkMode/WKWebView/SLWebViewListController.m index 884ae2f0..e896adcf 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLWebViewListController.m +++ b/iOS_Tips/DarkMode/WKWebView/SLWebViewListController.m @@ -53,7 +53,7 @@ - (void)getData { @" WKWebView + UITableView(方案3)(推荐)", @" WKWebView + UITableView(方案4)(推荐) ", @" WKWebView离线缓存", - @" WKWebView渲染的部分HTML元素替换为用原生组件显示(doing)", + @" WKWebView渲染的部分HTML元素替换为用原生组件显示", @" UIScrollView的实现原理", @" UITableView的原理"]]; [self.subTitles addObjectsFromArray:@[@" WKWebView的使用、JS和OC的交互、网页内容加载进度条的实现、NSNSURLProtocol拦截、Cookies丢失、设置UserAgent", From 18b85d250ca7d099f1d54bd9105723ff8475d1e7 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sun, 14 Jun 2020 23:02:58 +0800 Subject: [PATCH 011/356] =?UTF-8?q?UITableView=E5=8E=9F=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WKWebView/SLReusableManager.h | 15 +- .../DarkMode/WKWebView/SLReusableManager.m | 83 +++++--- .../WKWebView/SLTableViewController.m | 53 +++-- .../WKWebView/SLWebNativeViewController.m | 198 +++++++++++++----- 4 files changed, 236 insertions(+), 113 deletions(-) diff --git a/iOS_Tips/DarkMode/WKWebView/SLReusableManager.h b/iOS_Tips/DarkMode/WKWebView/SLReusableManager.h index 34ce7661..a9c5714d 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLReusableManager.h +++ b/iOS_Tips/DarkMode/WKWebView/SLReusableManager.h @@ -25,11 +25,24 @@ NS_ASSUME_NONNULL_BEGIN @end @protocol SLReusableDelegate ///选中行 -- (void)tableView:(SLReusableManager *)reusableManager didSelectRowAtIndex:(NSInteger)index; +- (void)reusableManager:(SLReusableManager *)reusableManager didSelectRowAtIndex:(NSInteger)index; @end @interface SLReusableManager : NSObject +///数据源代理 +@property (nonatomic, weak) iddelegate; +///数据源代理 +@property (nonatomic, weak) iddataSource; +/// 父视图 @property (nonatomic, weak) UIScrollView *scrollView; + +///刷新数据 +- (void)reloadData; +///注册样式 +- (void)registerClass:(Class)class forCellReuseIdentifier:(NSString *)cellID; +///根据cellID从复用池reusablePool取可重用的view,如果没有,重新创建一个新对象返回 +- (SLReusableCell *)dequeueReusableCellWithIdentifier:(nonnull NSString *)cellID index:(NSInteger)index; + @end NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/WKWebView/SLReusableManager.m b/iOS_Tips/DarkMode/WKWebView/SLReusableManager.m index 7d46c862..ed0c799a 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLReusableManager.m +++ b/iOS_Tips/DarkMode/WKWebView/SLReusableManager.m @@ -20,6 +20,8 @@ @interface SLReusableManager () ///复用池 @property (nonatomic, strong) NSMutableDictionary *> *reusablePool; +///注册的类 +@property (nonatomic, strong) NSMutableDictionary *registerClasses; /// 每一行的坐标位置 @property (nonatomic, strong) NSMutableArray *frameArray; /// 当前可见的cells @@ -30,19 +32,11 @@ @interface SLReusableManager () @property (nonatomic, assign) NSInteger willDisplayIndexTop; ///底部即将展示的索引 @property (nonatomic, assign) NSInteger willDisplayIndexBottom; -///数据源代理 -@property (nonatomic, weak) iddelegate; -///数据源代理 -@property (nonatomic, weak) iddataSource; + @end @implementation SLReusableManager #pragma mark - Override -- (void)willMoveToSuperview:(UIView *)newSuperview { - if (newSuperview) { - [self addKVO]; - } -} - (void)dealloc { [self removeKVO]; } @@ -53,6 +47,12 @@ - (NSMutableDictionary *)reusablePool { } return _reusablePool;; } +- (NSMutableDictionary *)registerClasses { + if (!_registerClasses) { + _registerClasses = [NSMutableDictionary dictionary]; + } + return _registerClasses; +} - (NSMutableArray *)frameArray { if (!_frameArray) { _frameArray = [NSMutableArray array]; @@ -66,6 +66,12 @@ - (NSMutableArray *)visibleCells { return _visibleCells;; } +#pragma mark - Setter +- (void)setScrollView:(UIScrollView *)scrollView { + _scrollView =scrollView; + [self addKVO]; +} + #pragma mark - KVO - (void)addKVO { [self.scrollView addObserver:self @@ -89,7 +95,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N } } -#pragma mark - Help Methods +#pragma mark - Public ///刷新数据 - (void)reloadData { //清空布局信息 @@ -130,6 +136,33 @@ - (void)reloadData { } } } +///根据cellID从复用池reusablePool取可重用的view,如果没有,重新创建一个新对象返回 +- (SLReusableCell *)dequeueReusableCellWithIdentifier:(nonnull NSString *)cellID index:(NSInteger)index{ + NSHashTable *hashTable = self.reusablePool[cellID]; + SLReusableCell *cell = hashTable.allObjects.firstObject; + if (cell == nil) { + //复用池reusablePool没有可重用的,就重新创建一个新对象返回 + cell = [[self.registerClasses[cellID] alloc] init]; + cell.cellID = cellID; + CGRect rect = [self.dataSource reusableManager:self frameForRowAtIndex:index]; + cell.frame = rect; + cell.userInteractionEnabled = YES; + UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didSelectedAction:)]; + [cell addGestureRecognizer:tap]; + }else { + //从缓冲池中取出可重用的cell + [hashTable removeObject:cell]; + } + cell.index = index; + return cell; +} +///注册样式 +- (void)registerClass:(Class)class forCellReuseIdentifier:(NSString *)cellID { + self.reusablePool[cellID] = [NSHashTable weakObjectsHashTable]; + self.registerClasses[cellID] = class; +} + +#pragma mark - Help Methods ///当前可见cell的索引 其实绘制cell的时候就可以先保存可见的索引,不用每次遍历查询 - (NSArray *)indexForVisibleRows { NSMutableArray *indexs = [NSMutableArray array]; @@ -154,7 +187,7 @@ - (void)willDisplayCellWithDirection:(BOOL)top { } }else { NSInteger count = [self.dataSource numberOfRowsInReusableManager:self]; - if (_willDisplayIndexBottom == count) return; + if (_willDisplayIndexBottom >= count) return; CGRect rect = [self.frameArray[self.willDisplayIndexBottom] CGRectValue]; //按需加载 只加载坐标位置是在当前窗口显示的视图 if (rect.origin.y + rect.size.height >= self.scrollView.contentOffset.y && rect.origin.y <= self.scrollView.contentOffset.y + self.scrollView.sl_height) { @@ -170,6 +203,7 @@ - (void)willDisplayCellWithDirection:(BOOL)top { //即将消失的cell,在消失时放入缓冲池里 top:YES上/NO下 - (void)willDisappearCellWithDirection:(BOOL)top { if(top) { + if (self.willDisplayIndexTop+1 >= self.frameArray.count) return; CGRect rect = [self.frameArray[self.willDisplayIndexTop+1] CGRectValue]; if (rect.origin.y + rect.size.height < self.scrollView.contentOffset.y) { self.willDisplayIndexTop = self.willDisplayIndexTop+1; @@ -180,6 +214,7 @@ - (void)willDisappearCellWithDirection:(BOOL)top { [self.visibleCells removeObjectAtIndex:0]; } }else { + if (self.willDisplayIndexBottom-1 < 0) return; CGRect rect = [self.frameArray[self.willDisplayIndexBottom-1] CGRectValue]; if (rect.origin.y > self.scrollView.contentOffset.y + self.scrollView.sl_height) { self.willDisplayIndexBottom = self.willDisplayIndexBottom-1; @@ -191,31 +226,11 @@ - (void)willDisappearCellWithDirection:(BOOL)top { } } } -///根据cellID从复用池reusablePool取可重用的view,如果没有,重新创建一个新对象返回 -- (SLReusableCell *)dequeueReusableCellWithIdentifier:(nonnull NSString *)cellID index:(NSInteger)index{ - NSHashTable *hashTable = self.reusablePool[cellID]; - SLReusableCell *cell = hashTable.allObjects.firstObject; - if (cell == nil) { - //复用池reusablePool没有可重用的,就重新创建一个新对象返回 - cell = [[SLReusableCell alloc] init]; - cell.cellID = cellID; - CGRect rect = [self.dataSource reusableManager:self frameForRowAtIndex:index]; - cell.frame = rect; - }else { - //从缓冲池中取出可重用的cell - [hashTable removeObject:cell]; - } - cell.index = index; - return cell; -} -///注册样式 -- (void)registerClass:(Class)class forCellReuseIdentifier:(NSString *)cellID { - self.reusablePool[cellID] = [NSHashTable weakObjectsHashTable]; -} #pragma mark - Events Handle -- (void)didSelectedAction:(SLReusableCell *)cell { - [self.delegate tableView:self didSelectRowAtIndex:cell.index]; +- (void)didSelectedAction:(UITapGestureRecognizer *)tap { + SLReusableCell *cell = (SLReusableCell *)tap.view; + [self.delegate reusableManager:self didSelectRowAtIndex:cell.index]; } @end diff --git a/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m b/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m index 0ad5b637..1c0d5d11 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m +++ b/iOS_Tips/DarkMode/WKWebView/SLTableViewController.m @@ -33,6 +33,8 @@ - (void)tableView:(SLTableView *)tableView didSelectRowAtIndex:(NSInteger)index; @interface SLTableView : UIScrollView ///复用池 @property (nonatomic, strong) NSMutableDictionary *> *reusablePool; +///注册的类 +@property (nonatomic, strong) NSMutableDictionary *registerClasses; /// 每一行的坐标位置 @property (nonatomic, strong) NSMutableArray *frameArray; /// 当前可见的cells @@ -72,6 +74,12 @@ - (NSMutableDictionary *)reusablePool { } return _reusablePool;; } +- (NSMutableDictionary *)registerClasses { + if (!_registerClasses) { + _registerClasses = [NSMutableDictionary dictionary]; + } + return _registerClasses; +} - (NSMutableArray *)frameArray { if (!_frameArray) { _frameArray = [NSMutableArray array]; @@ -154,6 +162,27 @@ - (void)reloadData { } } } +///根据cellID从复用池reusablePool取可重用的view,如果没有,重新创建一个新对象返回 +- (SLTableViewCell *)dequeueReusableCellWithIdentifier:(nonnull NSString *)cellID index:(NSInteger)index{ + NSHashTable *hashTable = self.reusablePool[cellID]; + SLTableViewCell *cell = hashTable.allObjects.firstObject; + if (cell == nil) { + //复用池reusablePool没有可重用的,就重新创建一个新对象返回 + cell = [[self.registerClasses[cellID] alloc] init]; + [cell addTarget:self action:@selector(didSelectedAction:) forControlEvents:UIControlEventTouchUpInside]; + cell.cellID = cellID; + }else { + //从缓冲池中取出可重用的cell + [hashTable removeObject:cell]; + } + cell.index = index; + return cell; +} +///注册样式 +- (void)registerClass:(Class)class forCellReuseIdentifier:(NSString *)cellID { + self.reusablePool[cellID] = [NSHashTable weakObjectsHashTable]; + self.registerClasses[cellID] = class; +} ///当前可见cell的索引 其实绘制cell的时候就可以先保存可见的索引,不用每次遍历查询 - (NSArray *)indexForVisibleRows { NSMutableArray *indexs = [NSMutableArray array]; @@ -178,7 +207,7 @@ - (void)willDisplayCellWithDirection:(BOOL)top { } }else { NSInteger count = [self.dataSource numberOfRowsInTableView:self]; - if (_willDisplayIndexBottom == count) return; + if (_willDisplayIndexBottom >= count) return; CGRect rect = [self.frameArray[self.willDisplayIndexBottom] CGRectValue]; //按需加载 只加载坐标位置是在当前窗口显示的视图 if (rect.origin.y + rect.size.height >= self.contentOffset.y && rect.origin.y <= self.contentOffset.y + self.sl_height) { @@ -194,6 +223,7 @@ - (void)willDisplayCellWithDirection:(BOOL)top { //即将消失的cell,在消失时放入缓冲池里 top:YES上/NO下 - (void)willDisappearCellWithDirection:(BOOL)top { if(top) { + if (self.willDisplayIndexTop+1 >= self.frameArray.count) return; CGRect rect = [self.frameArray[self.willDisplayIndexTop+1] CGRectValue]; if (rect.origin.y + rect.size.height < self.contentOffset.y) { self.willDisplayIndexTop = self.willDisplayIndexTop+1; @@ -204,6 +234,7 @@ - (void)willDisappearCellWithDirection:(BOOL)top { [self.visibleCells removeObjectAtIndex:0]; } }else { + if (self.willDisplayIndexBottom-1 < 0) return; CGRect rect = [self.frameArray[self.willDisplayIndexBottom-1] CGRectValue]; if (rect.origin.y > self.contentOffset.y + self.sl_height) { self.willDisplayIndexBottom = self.willDisplayIndexBottom-1; @@ -215,26 +246,6 @@ - (void)willDisappearCellWithDirection:(BOOL)top { } } } -///根据cellID从复用池reusablePool取可重用的view,如果没有,重新创建一个新对象返回 -- (SLTableViewCell *)dequeueReusableCellWithIdentifier:(nonnull NSString *)cellID index:(NSInteger)index{ - NSHashTable *hashTable = self.reusablePool[cellID]; - SLTableViewCell *cell = hashTable.allObjects.firstObject; - if (cell == nil) { - //复用池reusablePool没有可重用的,就重新创建一个新对象返回 - cell = [[SLTableViewCell alloc] init]; - [cell addTarget:self action:@selector(didSelectedAction:) forControlEvents:UIControlEventTouchUpInside]; - cell.cellID = cellID; - }else { - //从缓冲池中取出可重用的cell - [hashTable removeObject:cell]; - } - cell.index = index; - return cell; -} -///注册样式 -- (void)registerClass:(Class)class forCellReuseIdentifier:(NSString *)cellID { - self.reusablePool[cellID] = [NSHashTable weakObjectsHashTable]; -} #pragma mark - Events Handle - (void)didSelectedAction:(SLTableViewCell *)cell { diff --git a/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.m b/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.m index 467ae836..5f6019c5 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.m +++ b/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.m @@ -12,7 +12,7 @@ #import #import "SLAvPlayer.h" #import - +#import "SLReusableManager.h" @interface SLWebNativeModel : NSObject @property (nonatomic, copy) NSString *tagID; //标签ID @@ -26,23 +26,61 @@ @interface SLWebNativeModel : NSObject @implementation SLWebNativeModel @end + +@interface SLWebNativeCell : SLReusableCell +@property (nonatomic, strong) YYAnimatedImageView *imageView; +@end +@implementation SLWebNativeCell +- (instancetype)init { + self = [super init]; + if (self) { + [self setupUI]; + } + return self; +} + +- (void)setupUI { + _imageView = [[YYAnimatedImageView alloc] init]; + [self addSubview:_imageView]; + [_imageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.left.right.bottom.mas_equalTo(0); + }]; +} + +- (void)updateDataWith:(SLWebNativeModel *)model { + // if ([model.type isEqualToString:@"image"]) { + //图片 + [_imageView yy_setImageWithURL:[NSURL URLWithString:model.imgUrl] placeholder:nil]; + // } + +} +@end + /* - HTML中部分非文本元素,替换为用native组件来实现展示,来达到个性化自定义、灵活、提高渲染效率、简化web和OC交互的处理流程。 - 本示例 仅以用native组件替换HTML中的img、video、audio 内容来做展示,当然你也可以替换HTML中其它的标签元素。 - 注意:1.用native组件替换时,我们也需要进行一些native组件复用、按需加载的优化处理,类似于tableView的机制。 - 2.html界面调整时,要去重新调用JS方法获取原生标签的位置并更新native组件的位置。 - 3.如果仅需要处理HTML的图片元素,也可以不用原生组件imageView展示,原生下载处理图片,然后通过oc调用JS设置图片 + HTML中部分非文本元素,替换为用native组件来实现展示,来达到个性化自定义、灵活、提高渲染效率、简化web和OC交互的处理流程。 + 本示例 仅以用native组件替换HTML中的img、video、audio 内容来做展示,当然你也可以替换HTML中其它的标签元素。 + 注意:1.用native组件替换时,我们也需要进行一些native组件复用、按需加载的优化处理,类似于tableView的机制。 + 2.html界面调整时,要去重新调用JS方法获取原生标签的位置并更新native组件的位置。 + 3.如果仅需要处理HTML的图片元素,也可以不用原生组件imageView展示,原生下载处理图片,然后通过oc调用JS设置图片 */ -@interface SLWebNativeViewController () +@interface SLWebNativeViewController () + +@property (nonatomic, strong) dispatch_semaphore_t semaphore; @property (nonatomic, strong) WKWebView * webView; /// 网页加载进度视图 @property (nonatomic, strong) UIProgressView * progressView; /// WKWebView 内容的高度 @property (nonatomic, assign) CGFloat webContentHeight; /// 原生组件所需的HTML中元素的数据 -@property (nonatomic, strong) NSMutableArray *dataSource; +@property (nonatomic, strong) NSMutableArray *dataSource; /// 音视频播放 @property (nonatomic, strong) SLAvPlayer *avPlayer; + +///复用管理 +@property (nonatomic, strong) SLReusableManager *reusableManager; +/// 每一行的坐标位置 +@property (nonatomic, strong) NSMutableArray *frameArray; + @end @implementation SLWebNativeViewController @@ -67,6 +105,7 @@ - (void)setupUI { self.navigationItem.title = @"Html非文本元素替换为native组件展示"; [self.view addSubview:self.webView]; + _semaphore = dispatch_semaphore_create(1); NSString *path = [[NSBundle mainBundle] pathForResource:@"WebNative.html" ofType:nil]; NSString *htmlString = [[NSString alloc]initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; [_webView loadHTMLString:htmlString baseURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]]; @@ -117,6 +156,22 @@ - (SLAvPlayer *)avPlayer { } return _avPlayer; } +- (SLReusableManager *)reusableManager { + if (!_reusableManager) { + _reusableManager = [[SLReusableManager alloc] init]; + _reusableManager.delegate = self; + _reusableManager.dataSource = self; + _reusableManager.scrollView = self.webView.scrollView; + [_reusableManager registerClass:[SLWebNativeCell class] forCellReuseIdentifier:@"cellID"]; + } + return _reusableManager; +} +- (NSMutableArray *)frameArray { + if (!_frameArray) { + _frameArray = [NSMutableArray array]; + } + return _frameArray; +} #pragma mark - KVO ///添加键值对监听 @@ -193,70 +248,99 @@ -(void)rotateAnimate:(UIView *)view{ } #pragma mark - WKNavigationDelegate -// 根据WebView对于即将跳转的HTTP请求头信息和相关信息来决定是否跳转 -- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { - decisionHandler(WKNavigationActionPolicyAllow); -} -// 根据客户端收到的服务器响应头以及response相关信息来决定是否可以继续响应 -- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{ - //允许跳转 - decisionHandler(WKNavigationResponsePolicyAllow); -} // 页面加载完成之后调用 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { //根据服务器下发的标签相关的数据,用原生组件展示,这里原生组件的创建要注意按需加载和复用,类似于tableView,否则对内存还是有不小的消耗的。目前还没做处理 int i = 0; + SL_WeakSelf; for (SLWebNativeModel *model in self.dataSource) { NSString *jsString = [NSString stringWithFormat:@"getElementFrame('%@')",model.tagID]; [_webView evaluateJavaScript:jsString completionHandler:^(id _Nullable data, NSError * _Nullable error) { + dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER); //获取标签位置坐标 NSDictionary *frameDict = (NSDictionary *)data; CGRect frame = CGRectMake( [frameDict[@"x"] floatValue], [frameDict[@"y"] floatValue], [frameDict[@"width"] floatValue], [frameDict[@"height"] floatValue]); - if ([model.type isEqualToString:@"image"]) { - //图片 - YYAnimatedImageView *imageView = [[YYAnimatedImageView alloc] init]; - imageView.frame = frame; - imageView.tag = i; - [imageView yy_setImageWithURL:[NSURL URLWithString:model.imgUrl] placeholder:nil]; - [self.webView.scrollView addSubview:imageView]; - }else if ([model.type isEqualToString:@"video"]) { - //视频 - YYAnimatedImageView *imageView = [[YYAnimatedImageView alloc] init]; - imageView.frame = frame; - [imageView yy_setImageWithURL:[NSURL URLWithString:model.imgUrl ] placeholder:nil]; - [self.webView.scrollView addSubview:imageView]; - UIButton *playBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 80, 80)]; - playBtn.center = CGPointMake(frame.size.width/2.0, frame.size.height/2.0); - [playBtn setImage:[UIImage imageNamed:@"play"] forState:UIControlStateNormal]; - [playBtn addTarget:self action:@selector(playVideoAction:) forControlEvents:UIControlEventTouchUpInside]; - playBtn.tag = i; - imageView.userInteractionEnabled = YES; - [imageView addSubview:playBtn]; - }else if ([model.type isEqualToString:@"audio"]) { - //音频 - YYAnimatedImageView *imageView = [[YYAnimatedImageView alloc] init]; - imageView.frame = frame; - imageView.layer.cornerRadius = frame.size.height/2.0; - imageView.layer.masksToBounds = YES; - [imageView yy_setImageWithURL:[NSURL URLWithString:model.imgUrl ] placeholder:nil]; - [self.webView.scrollView addSubview:imageView]; - UIButton *playBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 40, 40)]; - playBtn.center = CGPointMake(frame.size.width/2.0, frame.size.height/2.0); - [playBtn setImage:[UIImage imageNamed:@"play"] forState:UIControlStateNormal]; - [playBtn addTarget:self action:@selector(playAudioAction:) forControlEvents:UIControlEventTouchUpInside]; - playBtn.tag = i; - imageView.userInteractionEnabled = YES; - [imageView addSubview:playBtn]; + [weakSelf.frameArray addObject:[NSValue valueWithCGRect:frame]]; + dispatch_semaphore_signal(weakSelf.semaphore); + if (i == weakSelf.dataSource.count - 1) { + [weakSelf.reusableManager reloadData]; } - // NSLog(@" %@",data) }]; i++; } - } -//进程被终止时调用 -- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView{ - + +#pragma mark - SLReusableDataSource +- (NSInteger)numberOfRowsInReusableManager:(SLReusableManager *)reusableManager { + return self.frameArray.count; +} +- (CGRect)reusableManager:(SLReusableManager *)reusableManager frameForRowAtIndex:(NSInteger)index { + CGRect rect = [self.frameArray[index] CGRectValue]; + return rect; +} +- (SLReusableCell *)reusableManager:(SLReusableManager *)reusableManager cellForRowAtIndex:(NSInteger)index { + SLWebNativeCell *cell = (SLWebNativeCell *)[reusableManager dequeueReusableCellWithIdentifier:@"cellID" index:index]; + SLWebNativeModel *model = self.dataSource[index]; + [cell updateDataWith:model]; + return cell; } + +#pragma mark - SLReusableDelegate +- (void)reusableManager:(SLReusableManager *)reusableManager didSelectRowAtIndex:(NSInteger)index { + NSLog(@"点击了 %ld", index); + SLWebNativeModel *model = self.dataSource[index]; + if ([model.type isEqualToString:@"image"]) { + //图片 + + }else if ([model.type isEqualToString:@"video"]) { + //视频 + + }else if ([model.type isEqualToString:@"audio"]) { + //音频 + + } +} + + +/* + if ([model.type isEqualToString:@"image"]) { + //图片 + YYAnimatedImageView *imageView = [[YYAnimatedImageView alloc] init]; + imageView.frame = frame; + imageView.tag = i; + [imageView yy_setImageWithURL:[NSURL URLWithString:model.imgUrl] placeholder:nil]; + [self.webView.scrollView addSubview:imageView]; + }else if ([model.type isEqualToString:@"video"]) { + //视频 + YYAnimatedImageView *imageView = [[YYAnimatedImageView alloc] init]; + imageView.frame = frame; + [imageView yy_setImageWithURL:[NSURL URLWithString:model.imgUrl ] placeholder:nil]; + [self.webView.scrollView addSubview:imageView]; + UIButton *playBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 80, 80)]; + playBtn.center = CGPointMake(frame.size.width/2.0, frame.size.height/2.0); + [playBtn setImage:[UIImage imageNamed:@"play"] forState:UIControlStateNormal]; + [playBtn addTarget:self action:@selector(playVideoAction:) forControlEvents:UIControlEventTouchUpInside]; + playBtn.tag = i; + imageView.userInteractionEnabled = YES; + [imageView addSubview:playBtn]; + }else if ([model.type isEqualToString:@"audio"]) { + //音频 + YYAnimatedImageView *imageView = [[YYAnimatedImageView alloc] init]; + imageView.frame = frame; + imageView.layer.cornerRadius = frame.size.height/2.0; + imageView.layer.masksToBounds = YES; + [imageView yy_setImageWithURL:[NSURL URLWithString:model.imgUrl ] placeholder:nil]; + [self.webView.scrollView addSubview:imageView]; + UIButton *playBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 40, 40)]; + playBtn.center = CGPointMake(frame.size.width/2.0, frame.size.height/2.0); + [playBtn setImage:[UIImage imageNamed:@"play"] forState:UIControlStateNormal]; + [playBtn addTarget:self action:@selector(playAudioAction:) forControlEvents:UIControlEventTouchUpInside]; + playBtn.tag = i; + imageView.userInteractionEnabled = YES; + [imageView addSubview:playBtn]; + } + */ + + @end From 217637dcf392a515882d01a4912d60536d8cefc8 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 15 Jun 2020 00:18:14 +0800 Subject: [PATCH 012/356] =?UTF-8?q?UITableView=E5=8E=9F=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WKWebView/SLWebNativeViewController.m | 118 +++++------------- iOS_Tips/DarkMode/WKWebView/WebNative.html | 52 +++++--- iOS_Tips/DarkMode/WKWebView/WebNativeJson.txt | 34 ++++- 3 files changed, 95 insertions(+), 109 deletions(-) diff --git a/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.m b/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.m index 5f6019c5..2568540b 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.m +++ b/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.m @@ -29,6 +29,7 @@ @implementation SLWebNativeModel @interface SLWebNativeCell : SLReusableCell @property (nonatomic, strong) YYAnimatedImageView *imageView; +@property (nonatomic, strong) UIImageView *playIcon; @end @implementation SLWebNativeCell - (instancetype)init { @@ -38,21 +39,42 @@ - (instancetype)init { } return self; } - - (void)setupUI { _imageView = [[YYAnimatedImageView alloc] init]; [self addSubview:_imageView]; [_imageView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.left.right.bottom.mas_equalTo(0); }]; + + _playIcon = [[UIImageView alloc] init]; + _playIcon.image = [UIImage imageNamed:@"play"]; + _playIcon.hidden = YES; + [_imageView addSubview:_playIcon]; + [_playIcon mas_makeConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(CGSizeMake(80, 80)); + make.centerX.mas_equalTo(_imageView.mas_centerX); + make.centerY.mas_equalTo(_imageView.mas_centerY); + }]; } - (void)updateDataWith:(SLWebNativeModel *)model { - // if ([model.type isEqualToString:@"image"]) { - //图片 [_imageView yy_setImageWithURL:[NSURL URLWithString:model.imgUrl] placeholder:nil]; - // } - + if ([model.type isEqualToString:@"image"]) { + //图片 + _playIcon.hidden = YES; + }else if ([model.type isEqualToString:@"video"]) { + //视频 + _playIcon.hidden = NO; + [_playIcon mas_updateConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(CGSizeMake(60, 60)); + }]; + }else if ([model.type isEqualToString:@"audio"]) { + //音频 + _playIcon.hidden = NO; + [_playIcon mas_updateConstraints:^(MASConstraintMaker *make) { + make.size.mas_equalTo(CGSizeMake(40, 40)); + }]; + } } @end @@ -73,8 +95,6 @@ @interface SLWebNativeViewController ()*dataSource; -/// 音视频播放 -@property (nonatomic, strong) SLAvPlayer *avPlayer; ///复用管理 @property (nonatomic, strong) SLReusableManager *reusableManager; @@ -150,12 +170,6 @@ - (NSMutableArray *)dataSource { } return _dataSource; } -- (SLAvPlayer *)avPlayer { - if (!_avPlayer) { - _avPlayer = [[SLAvPlayer alloc] init]; - } - return _avPlayer; -} - (SLReusableManager *)reusableManager { if (!_reusableManager) { _reusableManager = [[SLReusableManager alloc] init]; @@ -219,34 +233,6 @@ -(void)observeValueForKeyPath:(NSString *)keyPath } } -#pragma mark - Events Handle -- (void)playVideoAction:(UIButton *)btn { - SLWebNativeModel *model = self.dataSource[btn.tag]; - self.avPlayer.url = [NSURL URLWithString:model.videoUrl]; - self.avPlayer.monitor = btn.superview; - [self.avPlayer play]; - [btn removeFromSuperview]; -} -- (void)playAudioAction:(UIButton *)btn { - NSString *myBundlePath = [[NSBundle mainBundle] pathForResource:@"Resources" ofType:@"bundle"]; - NSBundle *myBundle = [NSBundle bundleWithPath:myBundlePath]; - NSString *audioPath = [myBundle pathForResource:@"The love of one's life" ofType:@"mp3" inDirectory:@"Audio"]; - NSURL *bgsoundUrl = [NSURL fileURLWithPath:audioPath]; - self.avPlayer.url = bgsoundUrl; - self.avPlayer.monitor = nil; - [self.avPlayer play]; - [self rotateAnimate:btn.superview]; - [btn removeFromSuperview]; -} --(void)rotateAnimate:(UIView *)view{ - //0.5秒旋转50度 - [UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{ - view.transform = CGAffineTransformRotate(view.transform, 50); - } completion:^(BOOL finished) { - [self rotateAnimate:view]; - }]; -} - #pragma mark - WKNavigationDelegate // 页面加载完成之后调用 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { @@ -254,7 +240,7 @@ - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigat int i = 0; SL_WeakSelf; for (SLWebNativeModel *model in self.dataSource) { - NSString *jsString = [NSString stringWithFormat:@"getElementFrame('%@')",model.tagID]; + NSString *jsString = [NSString stringWithFormat:@"getElementFrame('%@',%f, %f)",model.tagID,model.width,model.height]; [_webView evaluateJavaScript:jsString completionHandler:^(id _Nullable data, NSError * _Nullable error) { dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER); //获取标签位置坐标 @@ -288,59 +274,17 @@ - (SLReusableCell *)reusableManager:(SLReusableManager *)reusableManager cellFor #pragma mark - SLReusableDelegate - (void)reusableManager:(SLReusableManager *)reusableManager didSelectRowAtIndex:(NSInteger)index { - NSLog(@"点击了 %ld", index); SLWebNativeModel *model = self.dataSource[index]; if ([model.type isEqualToString:@"image"]) { //图片 - + NSLog(@"点击了 %ld 图片", index); }else if ([model.type isEqualToString:@"video"]) { //视频 - + NSLog(@"点击了 %ld 视频", index); }else if ([model.type isEqualToString:@"audio"]) { //音频 - + NSLog(@"点击了 %ld 音频", index); } } - -/* - if ([model.type isEqualToString:@"image"]) { - //图片 - YYAnimatedImageView *imageView = [[YYAnimatedImageView alloc] init]; - imageView.frame = frame; - imageView.tag = i; - [imageView yy_setImageWithURL:[NSURL URLWithString:model.imgUrl] placeholder:nil]; - [self.webView.scrollView addSubview:imageView]; - }else if ([model.type isEqualToString:@"video"]) { - //视频 - YYAnimatedImageView *imageView = [[YYAnimatedImageView alloc] init]; - imageView.frame = frame; - [imageView yy_setImageWithURL:[NSURL URLWithString:model.imgUrl ] placeholder:nil]; - [self.webView.scrollView addSubview:imageView]; - UIButton *playBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 80, 80)]; - playBtn.center = CGPointMake(frame.size.width/2.0, frame.size.height/2.0); - [playBtn setImage:[UIImage imageNamed:@"play"] forState:UIControlStateNormal]; - [playBtn addTarget:self action:@selector(playVideoAction:) forControlEvents:UIControlEventTouchUpInside]; - playBtn.tag = i; - imageView.userInteractionEnabled = YES; - [imageView addSubview:playBtn]; - }else if ([model.type isEqualToString:@"audio"]) { - //音频 - YYAnimatedImageView *imageView = [[YYAnimatedImageView alloc] init]; - imageView.frame = frame; - imageView.layer.cornerRadius = frame.size.height/2.0; - imageView.layer.masksToBounds = YES; - [imageView yy_setImageWithURL:[NSURL URLWithString:model.imgUrl ] placeholder:nil]; - [self.webView.scrollView addSubview:imageView]; - UIButton *playBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 40, 40)]; - playBtn.center = CGPointMake(frame.size.width/2.0, frame.size.height/2.0); - [playBtn setImage:[UIImage imageNamed:@"play"] forState:UIControlStateNormal]; - [playBtn addTarget:self action:@selector(playAudioAction:) forControlEvents:UIControlEventTouchUpInside]; - playBtn.tag = i; - imageView.userInteractionEnabled = YES; - [imageView addSubview:playBtn]; - } - */ - - @end diff --git a/iOS_Tips/DarkMode/WKWebView/WebNative.html b/iOS_Tips/DarkMode/WKWebView/WebNative.html index bf4c34a3..769701bb 100755 --- a/iOS_Tips/DarkMode/WKWebView/WebNative.html +++ b/iOS_Tips/DarkMode/WKWebView/WebNative.html @@ -47,37 +47,49 @@

Welcome To You

掘金

-
原生组件UIImageView
+
原生组件UIImageView
-
原生组件UIImageView
+
原生组件UIImageView
-
原生组件UIImageView
+
原生组件UIImageView
-
原生组件UIImageView
+
原生组件UIImageView
-
原生组件UIImageView
+
原生组件UIImageView
-
原生组件UIImageView
+
原生组件UIImageView
-
原生组件UIImageView
+
原生组件UIImageView
-
原生组件UIImageView
+
原生组件UIImageView
-
原生组件AVPlayer播放视频
-
+
原生组件UIImageView
+ +
+
原生组件UIImageView
+
+
+
原生组件UIImageView
+
- -
原生组件AVPlayer播放音频
+
原生组件UIImageView
+
+
+
原生组件AVPlayer播放视频
+
+ +
原生组件AVPlayer播放音频
+

以上图片来源于网络

@@ -85,19 +97,19 @@

Welcome To You

diff --git a/iOS_Tips/DarkMode/WKWebView/WebNativeJson.txt b/iOS_Tips/DarkMode/WKWebView/WebNativeJson.txt index b434c6ad..131bd25d 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebNativeJson.txt +++ b/iOS_Tips/DarkMode/WKWebView/WebNativeJson.txt @@ -40,7 +40,7 @@ "type": "image", "imgUrl": "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1590574444194&di=3f1d5730bc757a866ebba2aef6248367&imgtype=0&src=http%3A%2F%2Fhiphotos.baidu.com%2F_pennsylvania%2Fpic%2Fitem%2Ff939292bf63db47f1f3089ad.jpg", "width": "320", - "height": "240" + "height": "300" }, { "tagID": "image7", @@ -54,7 +54,35 @@ "type": "image", "imgUrl": "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1590574473190&di=a6d3a0e1cf189e5222d4fb8d21ee0475&imgtype=0&src=http%3A%2F%2Fupload.mnw.cn%2F2016%2F0414%2F1460606040792.jpg", "width": "320", - "height": "240" + "height": "320" + }, + { + "tagID": "image9", + "type": "image", + "imgUrl": "http://img.mp.itc.cn/upload/20170427/b78c6b85d3a1491fa6f5d3b671429d99_th.gif", + "width": "320", + "height": "320" + }, + { + "tagID": "image10", + "type": "image", + "imgUrl": "http://b-ssl.duitang.com/uploads/blog/201401/08/20140108182739_kFHxN.gif", + "width": "320", + "height": "320" + }, + { + "tagID": "image11", + "type": "image", + "imgUrl": "http://b-ssl.duitang.com/uploads/item/201601/15/20160115140217_HeJAm.jpeg", + "width": "320", + "height": "320" + }, + { + "tagID": "image12", + "type": "image", + "imgUrl": "http://www.3dmgame.com/uploads/allimg/180409/369_180409203945_1.jpg", + "width": "320", + "height": "320" }, { "tagID": "video1", @@ -74,3 +102,5 @@ } ] } + + From 4b7cc24e38290d01ad9dff5c11f964efbcf7c5cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Mon, 15 Jun 2020 09:17:13 +0800 Subject: [PATCH 013/356] Update README.md --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4056c0be..99c9d808 100644 --- a/README.md +++ b/README.md @@ -24,11 +24,11 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git > 7、iOS Crash防护 > 8、WKWebView相关 >> 8.1、WKWebView的使用 ->> 8.2、WKWebView+UITableView混排 ->> 8.3、UIScrollView实现原理 ->> 8.4、WKWebView离线缓存功能 ->> 8.5、Html非文本元素替换为原生组件展示 ->> +>> 8.2、WKWebView+UITableView混排 +>> 8.3、WKWebView离线缓存功能 +>> 8.4、Html非文本元素替换为原生组件展示 +>> 8.5、UIScrollView实现原理 +>> 8.6、UITableView的实现原理 > 问题说明 @@ -124,7 +124,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git ## 8、[WKWebView相关](https://juejin.im/post/5ed999fd51882542f9389949) -> [WKWebView的使用](https://juejin.im/post/5c0e1e2ae51d451d971743a1)、[WKWebView+UITableView混排](https://juejin.im/post/5ed999fd51882542f9389949)、UIScrollView实现原理、WKWebView离线缓存功能、Html非文本元素替换为原生组件展示 +> [WKWebView的使用](https://juejin.im/post/5c0e1e2ae51d451d971743a1)、[WKWebView+UITableView混排](https://juejin.im/post/5ed999fd51882542f9389949)、UIScrollView实现原理、WKWebView离线缓存功能、Html非文本元素替换为原生组件展示 、UITableView的实现原理 ![WKWebView相关](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/12、WKWebView.gif) From 69df6c6d2ee31df9d32016e48317355202c3b3cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Mon, 15 Jun 2020 09:17:51 +0800 Subject: [PATCH 014/356] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 99c9d808..fdffdd6d 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,8 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git >> 8.2、WKWebView+UITableView混排 >> 8.3、WKWebView离线缓存功能 >> 8.4、Html非文本元素替换为原生组件展示 ->> 8.5、UIScrollView实现原理 ->> 8.6、UITableView的实现原理 +>> 8.5、UIScrollView实现原理 +>> 8.6、UITableView的实现原理 > 问题说明 From 195e7835522073a778f847c6139aca2c52fb4458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Mon, 15 Jun 2020 09:18:15 +0800 Subject: [PATCH 015/356] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fdffdd6d..ba714ec4 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,8 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git >> 8.3、WKWebView离线缓存功能 >> 8.4、Html非文本元素替换为原生组件展示 >> 8.5、UIScrollView实现原理 ->> 8.6、UITableView的实现原理 +>> 8.6、UITableView的实现原理 + > 问题说明 From 2035e4c918a0a9bacd8cd19978cdce35e599d486 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 15 Jun 2020 19:48:13 +0800 Subject: [PATCH 016/356] =?UTF-8?q?=E9=92=A5=E5=8C=99=E4=B8=B2=E4=BF=9D?= =?UTF-8?q?=E5=AD=98=E7=94=A8=E6=88=B7=E5=AF=86=E7=A0=81=E5=92=8C=E8=B4=A6?= =?UTF-8?q?=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 6 + iOS_Tips/DarkMode/General/Tool/SLKeyChain.h | 40 ++++++ iOS_Tips/DarkMode/General/Tool/SLKeyChain.m | 141 ++++++++++++++++++++ 3 files changed, 187 insertions(+) create mode 100644 iOS_Tips/DarkMode/General/Tool/SLKeyChain.h create mode 100644 iOS_Tips/DarkMode/General/Tool/SLKeyChain.m diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index f9abfff4..bb1bd15c 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -101,6 +101,7 @@ 788424822492159F00C2E505 /* SLNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 788424812492159F00C2E505 /* SLNavigationController.m */; }; 7884248B2493851B00C2E505 /* SLViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7884248A2493851B00C2E505 /* SLViewController.m */; }; 7884248E24963FD200C2E505 /* SLReusableManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 7884248D24963FD200C2E505 /* SLReusableManager.m */; }; + 788424C724978E9200C2E505 /* SLKeyChain.m in Sources */ = {isa = PBXBuildFile; fileRef = 788424C624978E9200C2E505 /* SLKeyChain.m */; }; 788ACD622390BFD400737EC2 /* SLLoadImageVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 788ACD612390BFD400737EC2 /* SLLoadImageVC.m */; }; 788ACD652390EA3A00737EC2 /* SLCubeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 788ACD642390EA3A00737EC2 /* SLCubeViewController.m */; }; 788ADB382441F48F00302CD9 /* SLCrashViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 788ADB362441F48F00302CD9 /* SLCrashViewController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; @@ -327,6 +328,8 @@ 7884248A2493851B00C2E505 /* SLViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLViewController.m; sourceTree = ""; }; 7884248C24963FD200C2E505 /* SLReusableManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLReusableManager.h; sourceTree = ""; }; 7884248D24963FD200C2E505 /* SLReusableManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLReusableManager.m; sourceTree = ""; }; + 788424C524978E9200C2E505 /* SLKeyChain.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLKeyChain.h; sourceTree = ""; }; + 788424C624978E9200C2E505 /* SLKeyChain.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLKeyChain.m; sourceTree = ""; }; 788ACD602390BFD400737EC2 /* SLLoadImageVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLLoadImageVC.h; sourceTree = ""; }; 788ACD612390BFD400737EC2 /* SLLoadImageVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLLoadImageVC.m; sourceTree = ""; }; 788ACD632390EA3A00737EC2 /* SLCubeViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLCubeViewController.h; sourceTree = ""; }; @@ -703,6 +706,8 @@ 788424812492159F00C2E505 /* SLNavigationController.m */, 788424892493851B00C2E505 /* SLViewController.h */, 7884248A2493851B00C2E505 /* SLViewController.m */, + 788424C524978E9200C2E505 /* SLKeyChain.h */, + 788424C624978E9200C2E505 /* SLKeyChain.m */, ); path = Tool; sourceTree = ""; @@ -1332,6 +1337,7 @@ 7884248B2493851B00C2E505 /* SLViewController.m in Sources */, 78E72D5124766E4B00751373 /* SLWebViewController.m in Sources */, 78B10493232F57C50051579F /* main.m in Sources */, + 788424C724978E9200C2E505 /* SLKeyChain.m in Sources */, 78E179372351A40D0007E4BB /* SLShotFocusView.m in Sources */, 787C7DC8245D77D9005DF7ED /* SLZombieCatcher.m in Sources */, 78A4BD45236C5DF20021AE32 /* SLEditVideoController.m in Sources */, diff --git a/iOS_Tips/DarkMode/General/Tool/SLKeyChain.h b/iOS_Tips/DarkMode/General/Tool/SLKeyChain.h new file mode 100644 index 00000000..fafe9f4b --- /dev/null +++ b/iOS_Tips/DarkMode/General/Tool/SLKeyChain.h @@ -0,0 +1,40 @@ +// +// SLKeyChain.h +// DarkMode +// +// Created by wsl on 2020/6/15. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +FOUNDATION_EXTERN NSString* const SLkeychainService; + +///存储管理用户账号和密码到钥匙串 +@interface SLKeyChain : NSObject + +/// 保存用户信息到钥匙串中 +/// @param service 存储服务的key,一个service可以存储多个account/password键值对 +/// @param account 账号 +/// @param password 密码 ++ (NSError *)saveKeychainWithService:(NSString *)service + account:(NSString *)account + password:(NSString *)password; +///从钥匙串中删除这条用户信息 ++ (NSError *)deleteWithService:(NSString *)service + account:(NSString *)account; + +///查询用户信息 查到的结果存在NSError中 ++ (NSError *)queryKeychainWithService:(NSString *)service + account:(NSString *)account; + +///更新钥匙串中的用户名和密码 ++ (NSError *)updateKeychainWithService:(NSString *)service + account:(NSString *)account + password:(NSString *)password; + +@end + +NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/General/Tool/SLKeyChain.m b/iOS_Tips/DarkMode/General/Tool/SLKeyChain.m new file mode 100644 index 00000000..d3cd1acf --- /dev/null +++ b/iOS_Tips/DarkMode/General/Tool/SLKeyChain.m @@ -0,0 +1,141 @@ +// +// SLKeyChain.m +// DarkMode +// +// Created by wsl on 2020/6/15. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLKeyChain.h" +#import +#import + +NSString* const SLkeychainService = @"com.wsl.ios.keychain"; +static NSString* const keychainErrorDomain = @"com.wsl.ios.keychain.errorDomain"; +static NSInteger const kErrorCodeKeychainSomeArgumentsInvalid = 1000; //! 传入的部分参数无效 + +@implementation SLKeyChain + +///更新钥匙串中的用户名和密码 ++ (NSError *)updateKeychainWithService:(NSString *)service account:(NSString *)account password:(NSString *)password { + + if (!account || !password || !service) { + NSError *error = [self errorWithErrorCode:kErrorCodeKeychainSomeArgumentsInvalid]; + return error; + } + NSDictionary *queryItems = @{(id)kSecClass: (id)kSecClassGenericPassword, + (id)kSecAttrService: service, + (id)kSecAttrAccount: account + }; + NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; + NSDictionary *updatedItems = @{ + (id)kSecValueData: passwordData, + }; + OSStatus updateStatus = SecItemUpdate((CFDictionaryRef)queryItems, (CFDictionaryRef)updatedItems); + return [self errorWithErrorCode:updateStatus]; +} +///删除用户信息 ++ (NSError *)deleteWithService:(NSString *)service account:(NSString *)account { + + if (!service || !account) { + return [self errorWithErrorCode:kErrorCodeKeychainSomeArgumentsInvalid]; + } + NSDictionary *deleteSecItems = @{ + (id)kSecClass: (id)kSecClassGenericPassword, + (id)kSecAttrService: service, + (id)kSecAttrAccount: account + }; + OSStatus errorCode = SecItemDelete((CFDictionaryRef)deleteSecItems); + return [self errorWithErrorCode:errorCode]; +} +///查询用户信息 查到的结果存在NSError中 ++ (NSError *)queryKeychainWithService:(NSString *)service account:(NSString *)account { + + if (!service || !account) { + return [self errorWithErrorCode:kErrorCodeKeychainSomeArgumentsInvalid]; + } + NSDictionary *matchSecItems = @{ + (id)kSecClass: (id)kSecClassGenericPassword, + (id)kSecAttrService: service, + (id)kSecAttrAccount: account, + (id)kSecMatchLimit: (id)kSecMatchLimitOne, + (id)kSecReturnData: @(YES) + }; + CFTypeRef dataRef = nil; + OSStatus errorCode = SecItemCopyMatching((CFDictionaryRef)matchSecItems, (CFTypeRef *)&dataRef); + if (errorCode == errSecSuccess) { + NSString *password = [[NSString alloc] initWithData:CFBridgingRelease(dataRef) encoding:NSUTF8StringEncoding]; + return [self errorWithErrorCode:errSecSuccess errorMessage:password]; + } + return [self errorWithErrorCode:errorCode]; +} +///保存用户信息 ++ (NSError *)saveKeychainWithService:(NSString *)service account:(NSString *)account password:(NSString *)password { + + if (!account || !password || !service) { + NSError *error = [self errorWithErrorCode:kErrorCodeKeychainSomeArgumentsInvalid]; + return error; + } + + NSError *queryError = [self queryKeychainWithService:service account:account]; + if (queryError.code == errSecSuccess) { + // update + return [self updateKeychainWithService:service account:account password:password]; + } + + NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; + // save + NSDictionary *saveSecItems = @{(id)kSecClass: (id)kSecClassGenericPassword, + (id)kSecAttrService: service, + (id)kSecAttrAccount: account, + (id)kSecValueData: passwordData + }; + OSStatus saveStatus = SecItemAdd((CFDictionaryRef)saveSecItems, NULL); + return [self errorWithErrorCode:saveStatus]; +} +///错误信息 ++ (NSError *)errorWithErrorCode:(OSStatus)errorCode { + + NSString *errorMsg = nil; + + switch (errorCode) { + case errSecSuccess: { + NSLog(@"操作成功"); + return nil; + break; + } + case kErrorCodeKeychainSomeArgumentsInvalid: + errorMsg = NSLocalizedString(@"参数无效", nil); + break; + case errSecDuplicateItem: // -25299 + errorMsg = NSLocalizedString(@"The specified item already exists in the keychain. ", nil); + break; + case errSecItemNotFound: // -25300 + errorMsg = NSLocalizedString(@"The specified item could not be found in the keychain. ", nil); + break; + default: { + if (@available(iOS 11.3, *)) { + errorMsg = (__bridge_transfer NSString *)SecCopyErrorMessageString(errorCode, NULL); + } + break; + } + } + NSDictionary *errorUserInfo = nil; + if (errorMsg) { + errorUserInfo = @{NSLocalizedDescriptionKey: errorMsg}; + NSLog(@"%s--Line:%d--错误码:%d--错误信息:%@", __FUNCTION__, __LINE__, errorCode, errorMsg); + } + return [NSError errorWithDomain:keychainErrorDomain code:kErrorCodeKeychainSomeArgumentsInvalid userInfo:errorUserInfo]; +} + ++ (NSError *)errorWithErrorCode:(OSStatus)errCode errorMessage:(NSString *)errorMsg { + + if (errCode == errSecSuccess && errorMsg) { + NSLog(@"操作成功"); + return [NSError errorWithDomain:keychainErrorDomain code:errSecSuccess userInfo:@{NSLocalizedDescriptionKey: errorMsg}]; + } else { + return [self errorWithErrorCode:errCode]; + } +} + +@end From 8bff3718bd3b322d9dbc5c65069ae9510a89f84c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Tue, 16 Jun 2020 18:24:24 +0800 Subject: [PATCH 017/356] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ba714ec4..fd3c98c1 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git ## 8、[WKWebView相关](https://juejin.im/post/5ed999fd51882542f9389949) -> [WKWebView的使用](https://juejin.im/post/5c0e1e2ae51d451d971743a1)、[WKWebView+UITableView混排](https://juejin.im/post/5ed999fd51882542f9389949)、UIScrollView实现原理、WKWebView离线缓存功能、Html非文本元素替换为原生组件展示 、UITableView的实现原理 +> [WKWebView的使用](https://juejin.im/post/5c0e1e2ae51d451d971743a1)、[WKWebView+UITableView混排](https://juejin.im/post/5ed999fd51882542f9389949)、WKWebView离线缓存功能、HTML非文本元素替换为原生组件展示、UIScrollView实现原理、UITableView的实现原理 ![WKWebView相关](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/12、WKWebView.gif) From 2a55244e230636f831efa6ff40d1bc845eb60eb3 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 17 Jun 2020 13:47:13 +0800 Subject: [PATCH 018/356] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/WKWebView/SLReusableManager.m | 7 +++++++ iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.m | 6 +++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/iOS_Tips/DarkMode/WKWebView/SLReusableManager.m b/iOS_Tips/DarkMode/WKWebView/SLReusableManager.m index ed0c799a..1ed2d971 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLReusableManager.m +++ b/iOS_Tips/DarkMode/WKWebView/SLReusableManager.m @@ -100,6 +100,13 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N - (void)reloadData { //清空布局信息 [self.frameArray removeAllObjects]; + for (UIView *subView in self.scrollView.subviews) { + if ([subView isKindOfClass:[SLReusableCell class]]) { + [subView removeFromSuperview]; + } + } + [self.visibleCells removeAllObjects]; + self.willDisplayIndexTop = -1; //数据源个数 NSInteger count = [self.dataSource numberOfRowsInReusableManager:self]; diff --git a/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.m b/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.m index 2568540b..8bbe8feb 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.m +++ b/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.m @@ -134,6 +134,7 @@ - (void)setupUI { #pragma mark - Data /// 获取原生组件所需的HTML中元素的数据 - (void)getData { + [self.dataSource removeAllObjects]; NSData *contentData = [[NSFileManager defaultManager] contentsAtPath:[[NSBundle mainBundle] pathForResource:@"WebNativeJson" ofType:@"txt"]]; NSDictionary * dataDict = [NSJSONSerialization JSONObjectWithData:contentData options:kNilOptions error:nil]; for (NSDictionary *dict in dataDict[@"dataList"]) { @@ -236,6 +237,7 @@ -(void)observeValueForKeyPath:(NSString *)keyPath #pragma mark - WKNavigationDelegate // 页面加载完成之后调用 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { + [self.frameArray removeAllObjects]; //根据服务器下发的标签相关的数据,用原生组件展示,这里原生组件的创建要注意按需加载和复用,类似于tableView,否则对内存还是有不小的消耗的。目前还没做处理 int i = 0; SL_WeakSelf; @@ -247,7 +249,9 @@ - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigat NSDictionary *frameDict = (NSDictionary *)data; CGRect frame = CGRectMake( [frameDict[@"x"] floatValue], [frameDict[@"y"] floatValue], [frameDict[@"width"] floatValue], [frameDict[@"height"] floatValue]); - [weakSelf.frameArray addObject:[NSValue valueWithCGRect:frame]]; + if(!CGRectEqualToRect(frame, CGRectZero)) { + [weakSelf.frameArray addObject:[NSValue valueWithCGRect:frame]]; + } dispatch_semaphore_signal(weakSelf.semaphore); if (i == weakSelf.dataSource.count - 1) { [weakSelf.reusableManager reloadData]; From 009668d9538042cee7272607da678db4d60f08b2 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 18 Jun 2020 10:56:38 +0800 Subject: [PATCH 019/356] =?UTF-8?q?add=20=E8=BE=85=E5=8A=A9=E6=96=B9?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 6 +++ .../DarkMode/General/Tool/PrefixHeader.pch | 11 ++++ .../SLCategory/NSDictionary+SLExtension.m | 50 +++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 iOS_Tips/DarkMode/SLCategory/NSDictionary+SLExtension.m diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index bb1bd15c..7d4d6857 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -106,6 +106,7 @@ 788ACD652390EA3A00737EC2 /* SLCubeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 788ACD642390EA3A00737EC2 /* SLCubeViewController.m */; }; 788ADB382441F48F00302CD9 /* SLCrashViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 788ADB362441F48F00302CD9 /* SLCrashViewController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 788ADB392441F48F00302CD9 /* SLCrashViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 788ADB372441F48F00302CD9 /* SLCrashViewController.xib */; }; + 78A179A8249B0AA8006F52E3 /* NSDictionary+SLExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A179A6249B0AA8006F52E3 /* NSDictionary+SLExtension.m */; }; 78A1998C2451BEE7005B2B4B /* UIButton+SLTitleImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A1998B2451BEE7005B2B4B /* UIButton+SLTitleImage.m */; }; 78A1998F2451C049005B2B4B /* SLButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A1998E2451C049005B2B4B /* SLButton.m */; }; 78A35B1C23978A5D004BCCB7 /* SLShaderCubeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A35B1B23978A5D004BCCB7 /* SLShaderCubeViewController.m */; }; @@ -337,6 +338,8 @@ 788ADB352441F48F00302CD9 /* SLCrashViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLCrashViewController.h; sourceTree = ""; }; 788ADB362441F48F00302CD9 /* SLCrashViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLCrashViewController.m; sourceTree = ""; }; 788ADB372441F48F00302CD9 /* SLCrashViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SLCrashViewController.xib; sourceTree = ""; }; + 78A179A6249B0AA8006F52E3 /* NSDictionary+SLExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+SLExtension.m"; sourceTree = ""; }; + 78A179A7249B0AA8006F52E3 /* NSDictionary+SLExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+SLExtension.h"; sourceTree = ""; }; 78A1998A2451BEE7005B2B4B /* UIButton+SLTitleImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIButton+SLTitleImage.h"; sourceTree = ""; }; 78A1998B2451BEE7005B2B4B /* UIButton+SLTitleImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIButton+SLTitleImage.m"; sourceTree = ""; }; 78A1998D2451C049005B2B4B /* SLButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLButton.h; sourceTree = ""; }; @@ -585,6 +588,8 @@ 7851CB41233222E2002295B5 /* UIView+SLFrame.m */, 7830A5A22358904600BC79BA /* UIView+SLImage.h */, 7830A5A32358904600BC79BA /* UIView+SLImage.m */, + 78A179A7249B0AA8006F52E3 /* NSDictionary+SLExtension.h */, + 78A179A6249B0AA8006F52E3 /* NSDictionary+SLExtension.m */, 786147F823630C4D00C5424C /* UIImage+SLCommon.h */, 786147F923630C4D00C5424C /* UIImage+SLCommon.m */, 78A1998A2451BEE7005B2B4B /* UIButton+SLTitleImage.h */, @@ -1277,6 +1282,7 @@ 78A1998F2451C049005B2B4B /* SLButton.m in Sources */, 78B10488232F57C30051579F /* ViewController.m in Sources */, 78FA0FA02354141E003E456B /* SLAvEditExport.m in Sources */, + 78A179A8249B0AA8006F52E3 /* NSDictionary+SLExtension.m in Sources */, 78BDE050248E0AFB002ED386 /* SLWebNativeViewController.m in Sources */, 78F42023237915730093497C /* SLGPUImageController.m in Sources */, 7860D791239922B4008C53EC /* SLGLKPyramidVC.m in Sources */, diff --git a/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch b/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch index f7ae648f..d71171db 100644 --- a/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch +++ b/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch @@ -105,6 +105,17 @@ #define TICK NSDate *startTime = [NSDate date]; #define TOCK NSLog(@"Time:%f", -[startTime timeIntervalSinceNow]); +// STRING容错机制 +#define SL_IS_NULL(x) (!x || [x isKindOfClass:[NSNull class]]) +#define SL_IS_EMPTY_STRING(x) (SL_IS_NULL(x) || [x isEqual:@""] || [x isEqual:@"(null)"]) +#define SL_DEFUSE_EMPTY_STRING(x) (!SL_IS_EMPTY_STRING(x) ? x : @"") + +// 字典Value值类型容错机制 +#define SL_IntegerFormDict(dict,key) [[dict decodeStringFormDictWithKey:key] integerValue] +#define SL_StringFormDict(dict,key) [dict decodeStringFormDictWithKey:key] +#define SL_ArrayFormDict(dict,key) [dict decodeArrayFormDictWithKey:key] +#define SL_DictionaryFormDict(dict,key) [dict decodeDictionaryFormDictWithKey:key] + //---------------------- About Color 颜色 ---------------------------- /// 随机颜色 #define SL_UIColorFromRandomColor [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:1.0] diff --git a/iOS_Tips/DarkMode/SLCategory/NSDictionary+SLExtension.m b/iOS_Tips/DarkMode/SLCategory/NSDictionary+SLExtension.m new file mode 100644 index 00000000..b31ae435 --- /dev/null +++ b/iOS_Tips/DarkMode/SLCategory/NSDictionary+SLExtension.m @@ -0,0 +1,50 @@ +// +// NSDictionary+SLExtension.m +// +// +// Created by wsl on 2020/6/18. +// Copyright © 2020 wsl. All rights reserved. +// + +#import "NSDictionary+SLExtension.h" + +@implementation NSDictionary (SLExtension) + +///value 为NSString +- (NSString *)decodeStringFormDictWithKey:(NSString *)key { + NSString *string = @""; + if (self && [self isKindOfClass:[NSDictionary class]]) { + NSDictionary *dict = (NSDictionary *)self; + if ([dict[key] isKindOfClass:[NSString class]]) { + string = dict[key]; + } + else if ([dict[key] isKindOfClass:[NSNumber class]]) { + string = [dict[key] stringValue]; + } + } + return string; +} +///value 为NSArray +- (NSArray *)decodeArrayFormDictWithKey:(NSString *)key { + + NSArray *array = [NSArray array]; + if (self && [self isKindOfClass:[NSDictionary class]]) { + NSDictionary *dict = (NSDictionary *)self; + if ([dict[key] isKindOfClass:[NSArray class]]) { + array = dict[key]; + } + } + return array; +} +///容错处理 value 为NSDictionary +- (NSDictionary *)decodeDictionaryFormDictWithKey:(NSString *)key { + NSDictionary *dictionary = [NSDictionary dictionary]; + if (self && [self isKindOfClass:[NSDictionary class]]) { + NSDictionary *dict = (NSDictionary *)self; + if ([dict[key] isKindOfClass:[NSDictionary class]]) { + dictionary = dict[key]; + } + } + return dictionary; +} +@end From da37203e643b764beb05454a8efd8b7cf12b08a4 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 18 Jun 2020 10:56:51 +0800 Subject: [PATCH 020/356] =?UTF-8?q?add=20=E8=BE=85=E5=8A=A9=E6=96=B9?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SLCategory/NSDictionary+SLExtension.h | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 iOS_Tips/DarkMode/SLCategory/NSDictionary+SLExtension.h diff --git a/iOS_Tips/DarkMode/SLCategory/NSDictionary+SLExtension.h b/iOS_Tips/DarkMode/SLCategory/NSDictionary+SLExtension.h new file mode 100644 index 00000000..dfc344c1 --- /dev/null +++ b/iOS_Tips/DarkMode/SLCategory/NSDictionary+SLExtension.h @@ -0,0 +1,24 @@ +// +// NSDictionary+SLExtension.h +// +// +// Created by wsl on 2020/6/18. +// Copyright © 2020 wsl. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSDictionary (SLExtension) + +///容错处理 value 应为NSString +- (NSString *)decodeStringFormDictWithKey:(NSString *)key; +///容错处理 value 为NSArray +- (NSArray *)decodeArrayFormDictWithKey:(NSString *)key; +///容错处理 value 为NSDictionary +- (NSDictionary *)decodeDictionaryFormDictWithKey:(NSString *)key; + +@end + +NS_ASSUME_NONNULL_END From e294a0134b2a1747827e681d48985b6e87e20484 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 18 Jun 2020 11:05:58 +0800 Subject: [PATCH 021/356] =?UTF-8?q?add=20=E8=BE=85=E5=8A=A9=E6=96=B9?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch | 6 ------ iOS_Tips/DarkMode/SLCategory/NSDictionary+SLExtension.h | 6 +++--- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch b/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch index d71171db..2af90eae 100644 --- a/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch +++ b/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch @@ -110,12 +110,6 @@ #define SL_IS_EMPTY_STRING(x) (SL_IS_NULL(x) || [x isEqual:@""] || [x isEqual:@"(null)"]) #define SL_DEFUSE_EMPTY_STRING(x) (!SL_IS_EMPTY_STRING(x) ? x : @"") -// 字典Value值类型容错机制 -#define SL_IntegerFormDict(dict,key) [[dict decodeStringFormDictWithKey:key] integerValue] -#define SL_StringFormDict(dict,key) [dict decodeStringFormDictWithKey:key] -#define SL_ArrayFormDict(dict,key) [dict decodeArrayFormDictWithKey:key] -#define SL_DictionaryFormDict(dict,key) [dict decodeDictionaryFormDictWithKey:key] - //---------------------- About Color 颜色 ---------------------------- /// 随机颜色 #define SL_UIColorFromRandomColor [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:1.0] diff --git a/iOS_Tips/DarkMode/SLCategory/NSDictionary+SLExtension.h b/iOS_Tips/DarkMode/SLCategory/NSDictionary+SLExtension.h index dfc344c1..c434d8e3 100644 --- a/iOS_Tips/DarkMode/SLCategory/NSDictionary+SLExtension.h +++ b/iOS_Tips/DarkMode/SLCategory/NSDictionary+SLExtension.h @@ -13,11 +13,11 @@ NS_ASSUME_NONNULL_BEGIN @interface NSDictionary (SLExtension) ///容错处理 value 应为NSString -- (NSString *)decodeStringFormDictWithKey:(NSString *)key; +- (NSString *)sl_decodeStringFormDictWithKey:(NSString *)key; ///容错处理 value 为NSArray -- (NSArray *)decodeArrayFormDictWithKey:(NSString *)key; +- (NSArray *)sl_decodeArrayFormDictWithKey:(NSString *)key; ///容错处理 value 为NSDictionary -- (NSDictionary *)decodeDictionaryFormDictWithKey:(NSString *)key; +- (NSDictionary *)sl_decodeDictionaryFormDictWithKey:(NSString *)key; @end From 084ed04285ab3095857c00cede9d3ce2b56ca032 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 18 Jun 2020 11:06:13 +0800 Subject: [PATCH 022/356] =?UTF-8?q?add=20=E8=BE=85=E5=8A=A9=E6=96=B9?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/SLCategory/NSDictionary+SLExtension.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/iOS_Tips/DarkMode/SLCategory/NSDictionary+SLExtension.m b/iOS_Tips/DarkMode/SLCategory/NSDictionary+SLExtension.m index b31ae435..2f85564d 100644 --- a/iOS_Tips/DarkMode/SLCategory/NSDictionary+SLExtension.m +++ b/iOS_Tips/DarkMode/SLCategory/NSDictionary+SLExtension.m @@ -11,7 +11,7 @@ @implementation NSDictionary (SLExtension) ///value 为NSString -- (NSString *)decodeStringFormDictWithKey:(NSString *)key { +- (NSString *)sl_decodeStringFormDictWithKey:(NSString *)key { NSString *string = @""; if (self && [self isKindOfClass:[NSDictionary class]]) { NSDictionary *dict = (NSDictionary *)self; @@ -25,7 +25,7 @@ - (NSString *)decodeStringFormDictWithKey:(NSString *)key { return string; } ///value 为NSArray -- (NSArray *)decodeArrayFormDictWithKey:(NSString *)key { +- (NSArray *)sl_decodeArrayFormDictWithKey:(NSString *)key { NSArray *array = [NSArray array]; if (self && [self isKindOfClass:[NSDictionary class]]) { @@ -37,7 +37,7 @@ - (NSArray *)decodeArrayFormDictWithKey:(NSString *)key { return array; } ///容错处理 value 为NSDictionary -- (NSDictionary *)decodeDictionaryFormDictWithKey:(NSString *)key { +- (NSDictionary *)sl_decodeDictionaryFormDictWithKey:(NSString *)key { NSDictionary *dictionary = [NSDictionary dictionary]; if (self && [self isKindOfClass:[NSDictionary class]]) { NSDictionary *dict = (NSDictionary *)self; From 6638077b83d00aa1371a1c2551e25a721f6d8500 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 19 Jun 2020 18:28:49 +0800 Subject: [PATCH 023/356] =?UTF-8?q?add=E5=8D=9A=E5=AE=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/SLWorkIssuesViewController.m | 42 ++++++++++++++----- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m index b4f478d7..b85e984d 100644 --- a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m @@ -11,7 +11,8 @@ #import "SLWebViewController.h" @interface SLWorkIssuesViewController () -@property (nonatomic, strong) NSMutableArray *dataSource; +@property (nonatomic, strong) NSMutableArray *titlesArray; +@property (nonatomic, strong) NSMutableArray *urlArray; @property (nonatomic, strong) NSMutableArray *classArray; @end @@ -40,20 +41,37 @@ - (void)setupUI { #pragma mark - Data - (void)getData { - [self.dataSource addObjectsFromArray:@[ + [self.titlesArray addObjectsFromArray:@[ @"键盘和UIMenuController不能同时存在的问题", - @"全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突"]]; + @"全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突", + @"UITableView/UICollectionView获取特定位置的cell", + @"UIScrollView视觉差动画", + @"iOS 传感器集锦"]]; + [self.urlArray addObjectsFromArray:@[@"", + @"https://juejin.im/post/5c0e1e73f265da616413d828", + @"https://juejin.im/post/5c0e1df95188250d2722a3bc", + @"https://juejin.im/post/5c088b45f265da610e7fe156", + @"https://juejin.im/post/5c088a1051882517165dd15d"]]; [self.classArray addObjectsFromArray:@[[SLMenuViewController class], + [SLWebViewController class], + [SLWebViewController class], + [SLWebViewController class], [SLWebViewController class]]]; [self.tableView reloadData]; } #pragma mark - Getter -- (NSMutableArray *)dataSource { - if (_dataSource == nil) { - _dataSource = [NSMutableArray array]; +- (NSMutableArray *)titlesArray { + if (_titlesArray == nil) { + _titlesArray = [NSMutableArray array]; } - return _dataSource; + return _titlesArray; +} +- (NSMutableArray *)urlArray { + if (!_urlArray) { + _urlArray = [NSMutableArray array]; + } + return _urlArray;; } - (NSMutableArray *)classArray { if (_classArray == nil) { @@ -64,21 +82,23 @@ - (NSMutableArray *)classArray { #pragma mark - UITableViewDelegate, UITableViewDataSource - (NSInteger)tableView:(nonnull UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.dataSource.count; + return self.titlesArray.count; } - (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath { UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cellID" forIndexPath:indexPath]; cell.textLabel.numberOfLines = 0; - cell.textLabel.text = [NSString stringWithFormat:@"%ld、%@",(long)indexPath.row + 1,self.dataSource[indexPath.row]]; + cell.textLabel.text = [NSString stringWithFormat:@"%ld、%@",(long)indexPath.row,self.titlesArray[indexPath.row]]; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:NO]; UIViewController *nextVc = [[self.classArray[indexPath.row] alloc] init]; + NSString *urlString = self.urlArray[indexPath.row]; switch (indexPath.row) { - case 1: - ((SLWebViewController *)nextVc).urlString = @"https://juejin.im/post/5c0e1e73f265da616413d828"; default: + if (urlString.length > 0) { + ((SLWebViewController *)nextVc).urlString = urlString; + } [self.navigationController pushViewController:nextVc animated:YES]; break; } From b7114583982fca444d83654c9c790e66d8597911 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 19 Jun 2020 19:36:00 +0800 Subject: [PATCH 024/356] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 8196 -> 8196 bytes iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 8 ++----- .../DarkMode/Crash/SLCrashViewController.xib | 22 ------------------ .../WKWebView/SLWebViewListController.m | 3 +-- 4 files changed, 3 insertions(+), 30 deletions(-) delete mode 100644 iOS_Tips/DarkMode/Crash/SLCrashViewController.xib diff --git a/.DS_Store b/.DS_Store index 6702a13f40249250b4401664897ab48a3077d2dd..b6c8dc09bf6328012e038c07687211517fb88b78 100644 GIT binary patch delta 32 mcmZp1XmOa}&nUJrU^hRb*k&Gq*=!rj5*RnLODq5~Vi^IhoC;O| delta 364 zcmZp1XmOa}&nUSuU^hRb - - - - - - - - - - - - - - - - - - - - - diff --git a/iOS_Tips/DarkMode/WKWebView/SLWebViewListController.m b/iOS_Tips/DarkMode/WKWebView/SLWebViewListController.m index e896adcf..4a4b7b90 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLWebViewListController.m +++ b/iOS_Tips/DarkMode/WKWebView/SLWebViewListController.m @@ -75,6 +75,7 @@ - (void)getData { [SLTableViewController class]]]; [self.tableView reloadData]; } + #pragma mark - Getter - (UITableView *)tableView { if (_tableView == nil) { @@ -85,8 +86,6 @@ - (UITableView *)tableView { } return _tableView; } - -#pragma mark - Getter - (NSMutableArray *)titles { if (_titles == nil) { _titles = [NSMutableArray array]; From 546e7966952020794762d2c10f96afcbfab81255 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sat, 27 Jun 2020 10:42:15 +0800 Subject: [PATCH 025/356] =?UTF-8?q?=E5=B0=81=E8=A3=85GCD=E8=AE=A1=E6=97=B6?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 6 ++ iOS_Tips/DarkMode/General/Tool/SLMethod.h | 1 + iOS_Tips/DarkMode/General/Tool/SLTimer.m | 90 +++++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 iOS_Tips/DarkMode/General/Tool/SLTimer.m diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 8ae670ad..7714bfda 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 2CEBE85D24A6E65600BA21F3 /* SLTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CEBE85B24A6E65600BA21F3 /* SLTimer.m */; }; 780F5303236D8462000D0EA8 /* SLGridView.m in Sources */ = {isa = PBXBuildFile; fileRef = 780F5302236D8462000D0EA8 /* SLGridView.m */; }; 780F5306236D8570000D0EA8 /* SLImageClipController.m in Sources */ = {isa = PBXBuildFile; fileRef = 780F5305236D8570000D0EA8 /* SLImageClipController.m */; }; 7822CCF8235B054200E70C29 /* SLPaddingLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 7822CCF7235B054200E70C29 /* SLPaddingLabel.m */; }; @@ -179,6 +180,8 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 2CEBE85B24A6E65600BA21F3 /* SLTimer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLTimer.m; sourceTree = ""; }; + 2CEBE85C24A6E65600BA21F3 /* SLTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLTimer.h; sourceTree = ""; }; 780F5301236D845B000D0EA8 /* SLGridView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLGridView.h; sourceTree = ""; }; 780F5302236D8462000D0EA8 /* SLGridView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLGridView.m; sourceTree = ""; }; 780F5304236D8570000D0EA8 /* SLImageClipController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLImageClipController.h; sourceTree = ""; }; @@ -711,6 +714,8 @@ 7884248A2493851B00C2E505 /* SLViewController.m */, 788424C524978E9200C2E505 /* SLKeyChain.h */, 788424C624978E9200C2E505 /* SLKeyChain.m */, + 2CEBE85C24A6E65600BA21F3 /* SLTimer.h */, + 2CEBE85B24A6E65600BA21F3 /* SLTimer.m */, ); path = Tool; sourceTree = ""; @@ -1323,6 +1328,7 @@ 78E72D8C2482958300751373 /* WKWebView+SLExtension.m in Sources */, 7884247F2492102900C2E505 /* SLWorkIssuesViewController.m in Sources */, 78E72D542477A4E700751373 /* SLWebTableViewController.m in Sources */, + 2CEBE85D24A6E65600BA21F3 /* SLTimer.m in Sources */, 783504642452C20B0071283E /* SLMethod.m in Sources */, 787C7E4524656524005DF7ED /* UIView+SLMLeakFinder.m in Sources */, 7862533F24599D420017F8F1 /* NSObject+SLCrashProtector.m in Sources */, diff --git a/iOS_Tips/DarkMode/General/Tool/SLMethod.h b/iOS_Tips/DarkMode/General/Tool/SLMethod.h index bae8385b..616e0520 100644 --- a/iOS_Tips/DarkMode/General/Tool/SLMethod.h +++ b/iOS_Tips/DarkMode/General/Tool/SLMethod.h @@ -54,6 +54,7 @@ static NSString * const SLUserDefaultsKey = @"SLUserDefaultsKey"; @return 返回属性字符串的size */ + (CGSize)sizeFromAttributedText:(NSAttributedString *)attributedText maxSize:(CGSize)maxSize; + /// 切四个不同半径圆角的函数 /// @param bounds 区域 /// @param cornerRadii 四个圆角的半径 diff --git a/iOS_Tips/DarkMode/General/Tool/SLTimer.m b/iOS_Tips/DarkMode/General/Tool/SLTimer.m new file mode 100644 index 00000000..449dfeaa --- /dev/null +++ b/iOS_Tips/DarkMode/General/Tool/SLTimer.m @@ -0,0 +1,90 @@ +// +// SLTimer.m +// +// Created by wsl on 2020/6/15. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLTimer.h" + +@implementation SLTimer + +static NSMutableDictionary *timers_; +dispatch_semaphore_t semaphore_; ++ (void)initialize +{ + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + timers_ = [NSMutableDictionary dictionary]; + semaphore_ = dispatch_semaphore_create(1); + }); +} + ++ (NSString *)execTask:(void (^)(void))task start:(NSTimeInterval)start interval:(NSTimeInterval)interval repeats:(BOOL)repeats async:(BOOL)async +{ + if (!task || start < 0 || (interval <= 0 && repeats)) return nil; + + // 队列 + dispatch_queue_t queue = async ? dispatch_get_global_queue(0, 0) : dispatch_get_main_queue(); + + // 创建定时器 + dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); + + // 设置时间 + dispatch_source_set_timer(timer, + dispatch_time(DISPATCH_TIME_NOW, start * NSEC_PER_SEC), + interval * NSEC_PER_SEC, 0); + + + dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER); + // 定时器的唯一标识 + NSString *name = [NSString stringWithFormat:@"%zd", timers_.count]; + // 存放到字典中 + timers_[name] = timer; + dispatch_semaphore_signal(semaphore_); + + // 设置回调 + dispatch_source_set_event_handler(timer, ^{ + task(); + + if (!repeats) { // 不重复的任务 + [self cancelTask:name]; + } + }); + + // 启动定时器 + dispatch_resume(timer); + + return name; +} + ++ (NSString *)execTask:(id)target selector:(SEL)selector start:(NSTimeInterval)start interval:(NSTimeInterval)interval repeats:(BOOL)repeats async:(BOOL)async +{ + if (!target || !selector) return nil; + + return [self execTask:^{ + if ([target respondsToSelector:selector]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [target performSelector:selector]; +#pragma clang diagnostic pop + } + } start:start interval:interval repeats:repeats async:async]; +} + ++ (void)cancelTask:(NSString *)taskName; +{ + if (taskName.length == 0) return; + + dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER); + + dispatch_source_t timer = timers_[taskName]; + if (timer) { + dispatch_source_cancel(timer); + [timers_ removeObjectForKey:taskName]; + } + + dispatch_semaphore_signal(semaphore_); +} + +@end From b61070b1657609f9699ff8e6e0f2851c6d526846 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sat, 27 Jun 2020 10:42:36 +0800 Subject: [PATCH 026/356] =?UTF-8?q?GCD=E8=AE=A1=E6=97=B6=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/General/Tool/SLTimer.h | 44 ++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 iOS_Tips/DarkMode/General/Tool/SLTimer.h diff --git a/iOS_Tips/DarkMode/General/Tool/SLTimer.h b/iOS_Tips/DarkMode/General/Tool/SLTimer.h new file mode 100644 index 00000000..3026c295 --- /dev/null +++ b/iOS_Tips/DarkMode/General/Tool/SLTimer.h @@ -0,0 +1,44 @@ +// +// SLTimer.h +// +// Created by wsl on 2020/6/15. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + + +#import + +///计时器 比NSTimer和CADisplayLink计时准确 +@interface SLTimer : NSObject + +/// 执行任务 返回任务名称 +/// @param task 任务Block +/// @param start 开始时间 +/// @param interval 时间间隔 +/// @param repeats 是否重复 +/// @param async 是否异步 ++ (NSString *)execTask:(void(^)(void))task + start:(NSTimeInterval)start + interval:(NSTimeInterval)interval + repeats:(BOOL)repeats + async:(BOOL)async; + +/// 执行任务 返回任务名称 +/// @param target 选择器执行者 +/// @param selector 选择器 +/// @param start 开始时间 +/// @param interval 时间间隔 +/// @param repeats 是否重复 +/// @param async 是否异步 ++ (NSString *)execTask:(id)target + selector:(SEL)selector + start:(NSTimeInterval)start + interval:(NSTimeInterval)interval + repeats:(BOOL)repeats + async:(BOOL)async; + +/// 取消任务 +/// @param taskName 任务名称 ++ (void)cancelTask:(NSString *)taskName; + +@end From d7dd113a7eb89cc6c15d4f88f675538a6a7ccb82 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sat, 27 Jun 2020 19:32:32 +0800 Subject: [PATCH 027/356] add icon --- .../AppIcon.appiconset/120-1.png | Bin 0 -> 16166 bytes .../AppIcon.appiconset/120.png | Bin 0 -> 16166 bytes .../AppIcon.appiconset/180.png | Bin 0 -> 26576 bytes .../Assets.xcassets/AppIcon.appiconset/20.png | Bin 0 -> 4592 bytes .../Assets.xcassets/AppIcon.appiconset/29.png | Bin 0 -> 5089 bytes .../AppIcon.appiconset/40-1.png | Bin 0 -> 5863 bytes .../Assets.xcassets/AppIcon.appiconset/40.png | Bin 0 -> 5863 bytes .../AppIcon.appiconset/58-1.png | Bin 0 -> 8056 bytes .../Assets.xcassets/AppIcon.appiconset/58.png | Bin 0 -> 8056 bytes .../Assets.xcassets/AppIcon.appiconset/60.png | Bin 0 -> 8276 bytes .../AppIcon.appiconset/80-1.png | Bin 0 -> 11885 bytes .../Assets.xcassets/AppIcon.appiconset/80.png | Bin 0 -> 10651 bytes .../AppIcon.appiconset/Contents.json | 90 ++++++++++-------- .../Base.lproj/LaunchScreen.storyboard | 23 ++++- 14 files changed, 69 insertions(+), 44 deletions(-) create mode 100644 iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/120-1.png create mode 100644 iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/120.png create mode 100644 iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/180.png create mode 100644 iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/20.png create mode 100644 iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/29.png create mode 100644 iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/40-1.png create mode 100644 iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/40.png create mode 100644 iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/58-1.png create mode 100644 iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/58.png create mode 100644 iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/60.png create mode 100644 iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/80-1.png create mode 100644 iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/80.png diff --git a/iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/120-1.png b/iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/120-1.png new file mode 100644 index 0000000000000000000000000000000000000000..ca22535dd9c91c8a60d28af1faab57663337696a GIT binary patch literal 16166 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 literal 0 HcmV?d00001 diff --git a/iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/120.png b/iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/120.png new file mode 100644 index 0000000000000000000000000000000000000000..ca22535dd9c91c8a60d28af1faab57663337696a GIT binary patch literal 16166 zcmbWeW0)q-vM<`UZ5wafoVIP-wmogzwr$(?w0ov)yU+aBT6gb#&pqeM&3dvjG9rEv z8Cm&MWmRTHD9DM!!{ERG0Rh2FN{A@^Ej|9pP!NC5Tqf*`KtOOtmcqgclET773QqQB zmNuq9KoSut>W~`B6BxPLN|F|VP!iBR5hQE@$w*pYz!gE|A!P9iMlw(|ZZ4YOYk)$H z1yy8Gb#=kjpm1wlH1Ayv1;y17Rh#l|Xy}v9I-hHw-K|&WqiKIBv#T6nLHUuii91DK zAeiExcOl~ntL@D$7^lcYAovDgp&-`1g2aczV`D&6pr5;cX4nGC->2-XYW-us)tS&D z(LjLW;li6jV157(&j9U_gJg6g0U2Q}|B|Cmu4uqABISZZI>@lfE*h9x=9CU@d;CR4 z?m%n@79ewY|A!0cq*aKoN+KTA(}nQI1pr;D80ZB12Ob&H{ZAyyAH3E128}p#Ki8o* zr-*i-nRw1=XS4fm&EfCvU%7%clGOX+hsa>-)7$ztGEZj7-v z?!v)pda4DP;u+LvQg4h}+8Y(J(Ml>1Tc!K2<95Lgyb_X=c>76}qNA|KMX6w5*M7&g zL=;bK`ZRbq4$gyJZrN%2b*~aoM%|IFc;SZ6povCocD$4ewR5t4ctlq-@=Kyp=4MP0 z;@3q$GJr4zzzzbzQW;KxB>e!yH@mXA4CrSjK=ng9#e<6U%T{5hCu|Ck{G1a}fcpxN z07DDD7kU>L&4)S@fVX0k=ZN1H&{`HCMdS@_2NDVPdC}ewkmf$22j>mKnGooPHK=~A zuNeEPI24qPRx85WGd+dZKpBcK9Hue?TfpWR3cdm2h2R%9xbNR+-xX}uzkrT|z6^m3 zsRBdaKO&Qi_{h>21w#KFH*c2x=sMaC`uky2_*QTnA;Xcv4r0rJ;Up{=Qh07hVQOWx zW;W;1{tj&JD{Ni0%SwH9Ti5w)}Pv$7{JS6r!8_VJr#KlkEFuZ0$`&U1?wM zeCPB_kp}`sbO~k!H=0M2T^BHcjM>O}LrY|ITO71Mq(N{+a0OJ}N1eI0Ol$Vt24a}| zS(t_R?3CYJS9g7bsrvv4=7mpAAB5geyx>2D_FkB+#UjP`$D}2y`MY4J+NN7Z)m=dzP0@N{;hr~U&Np1 zZ+sAN!3hwK5a19|@NU@IOdeJe%r1;@9B4QI#w{z4!5d;w<8|hCIACLbW86csqM>k$ z-xk9xlWa5`o5ss#%eFQa7pB=pyff{SFX0W55lr~$yk`8))XoC;IQK(HQN-EAg~U;z z%kUknziTEGl8{gnBr_)TlBy^OWi(6oOFc`cWN~G#GxyB^X2vt6nYOGvmaA;b78d;q z1M`gq?_oR4;xoF_sMF@@_G|+7JI02V$d<%S8rF`3g;R-^*hU%F9g}zEre)|uG~-f6 zEt6;ID=eu@QA3mFs*PHj+p9;bimOuR^sBb3J?ydU6YS*d-nLhpO12xV8?99~+BRL6 z)fc1dGtE^kU8eF4=D(sY*VgkI{m=JK;?Hh+goB5a#Zkp`jT?+>4)G~FmFt(#%B;$0 zXGP3gopbLYj-vqOQEgG{C6j-GXwS|LX&krrHu<9&r|r{SG#=~E?N~WtwG*^!etqsw z?=uZahjPIAGY#5_yoLWEm5X_~xVp@}?w$F3k{C)T5>Jh`!Ff#!iwf&6nmml8+-4bc zjx{ejmS#|ANLUlA!`*?qX4={HZu9WJyM0V}Uw(CY+k7>9t9|a7Wj7jY!fcX%NB$7{ zJbJ-@^1i-4)IaIl{hkAA3+N8e1(p}*ibaXpWIr>^mn9N#kj|$GM^DCX=8{0S!JkH~ zMesv1!X<&*Ah-)ToSyh|anudvikK2c0OvdPcszT+9%g8mU}$P+yC1qgv41{zExIo9 zTVz?xMchk#HrytbL_}1aKCW}NX%E_it@~=Bx5zxkE~ZqJQmih@59ttvG|mzyI2N1F z>`yvR!&AfJdMGE-Sd=!lJI4-_pVS9~afI>Vm|Bc)HY2m4*uL-NDrDc|AHSRKJ`!hVio zrlW1pVTdK_tPE>by1?x?S&!t0BqTF*Mny&!v%uZq%gRSCo!;tOwH>f}z1WQo7Ksk| z1sZsyT6nGrq*>j#UnXjL6LXm|9$hVxyJUN!Yhqf5Vn>$K?$OAf%klFm`I%j9LBKd2 zCmCDvk)$@Iwp=cIhwc##ZAwMyi@YXZi8cZKZml31Dq74>v6~w|z0=|kInO?-^76`) z?d9YO$Wm;XBsm^|ZPT~HQ~5~JNdN4>IizWe3`;)eo$2=`&ZgFBF*EZSy9{F<^MUNx zjs$1-*`nF0tY_^A?}^C7wR`1b4*GfxM)!fCYm&Yy`W5<=G`(;By?0sI+nD@Z~ zNl$sK(x{qL>(S%0e9VBUihLDv~%Zckmt19l*jDf*(%`WKLz|0 z*qL|fuje1{SYJ(0k*Bx2O=PFQR?5~&h~rycLY;rQ$1vo-;kf?hu!4L@Djla32jJXv zuYS>xZ>sJ%_n5s6qfgSZ%foU%kUC#qZB1IBl>f%LJ&#b%Rvwds%;onP{hlspx@dww z_L*JDd*=7Q;ke#KXnk#7(ZA`L_gJ_#QhqOgDoP7t!0*FzdtIaLrai75)wAtO^|>5< zj6Sc#9mJKlKic*2tU6J1$_11A8 zlYX7*?ZfC}_H8+ASvyb7eaZE}vpe>FdRHb?65u_}c}sX`xJ$Y(E1g@& zyM91_c$|1~^7~c<3WlGVh1jdZ2by03GSCS*4!h0d(eES5^tKWJ`G&T>`uTYPDu{ov zJmzZ00`zX+oDSPzs7$z$Bm{JJ%C+8HIR5l7@362J6LwQucbx(bR7?THKk@$N#qsdy z8|1EXK>;+Q%<3-Ng0#PF;2e*m%Z5A)z8ii-@TMBO`y_}Ti22g`joI!Rfmn?JzWMj1 zBh^$x(o9wsh~_U11q2R^0tEV(0{(jd0pkFH|BD6!k^;v4FIowh>OVRlKtN%ZKw$sT z(fV8dlj8s8zv%yzpoyVCkbi3^e{)Da$bV^j||XT$ zL`1w!CT849B4Yo6|E=+nSh%=2a5FHtySoG2SpfD<<_t_+TwDx{%nZ!T^nW$zojvVb z3_a-WoJs#}UjLk6l9}dsi1e5|V!${a5;TJ54<-|J#$D^MAtn z8z93!5(Xv!Bg6j*=3;5~e}VlY`8VueasAsJ??1-4Rh>Ix|GUR||K;ib zCH(Jp{u`)Z>0xT4A!7L#>HIe)ekM-F|DgVN$^Q|l`F}TGZ0`j5J*ouvyu^M4@!8~Z;fUWR`z%m27c{~iPX;{F{3{4l%> z|23faVYrf0u7Q9UBqc?DsCWQh`a%Zij3hj9aM{Lg5?Pk0B0!l2g^&wE88Z$T?BQ`{ z*T-90TuEuo z4Ca1WTAJ^8Z`XBpR#tWXP2!lQLd-cWX!Ch3^wR7y1%inK=APmb%$yT@P1zvkp7)6; z*(Nuda)C|Vo|4dV%rA6h{hB-7#bA`!KB>xkboP2mK}m4@Q`8Qr91PS0k`Q@+&^V{E z(vtte2S%H^efegh#FkC%bM)5k>AnixHFY4j`$Z3;XxCswUJYKAeg1%9k$wugi@|<< z8iUKFFhg6VFp9b-a{p}bO_vH42{H^p`XeA%w>D&fRQl9-V&Y)Td$|NdEQ%M-?@4$( zb3?9SY099OEEerTYkWgmz*x2P!+zPA(QMpVa&Sw6Dk!w5<%G)q$MzS6MyF7DUPhE# z6tLSDHk}vRadAE;2l^|Q<+wx(?KQ#^am^EC(8&cH3Dznx)V5+tw+5Mpi32JfUJ2KVEtt`duI`Q@F(Z zM1@HcWVlf^hOV3jFc2@CO9#}q!{-OYM3hLNnp+1G)3Q9MV_hrb*TP!cT8Z|c3*T3Q z=hv|2o$_H0Q>RZ9@t7Nx01ekQd=hi=L&KsaobCHmI;ME`^m+=oqz94x7f-|{thdAl zD5%th;v9n(2oQVwy9(4e%LR8HP`bVBCnP`8i;zV+eH+xp(hB)~p;t2pY8UP%-I_ma zNI^{fLVkfjxw=$zlx@byw`8l82>|V`8bjGs2~Ku!)hl?>vj=BN6Ijx;Tq%%d#x~PV z`#xv5zI-+c^dCqFzawCFTU+f39E2qtmaP~Fa!QE3`kpwwI+nM<{?WCQ$%?PD2porg zX+WXispb^Is@XQFT?uz6f~2U^9x+b#MbHkSe?4{Rb4BB3SJBUe{l4OUp|#pi=RRE? z+gnmO-nXNqGv=IyEP`r-NbpS9L6KkrWe zu$QjCiL@N20)#BsiG`eTVId6tfzR(*is^0zOk-sQV;_!EF+K+GVInj{G!N0K+$NMm z2i`%PU}&oHilqS^K44FaO=(!mw2(Y5DKEI5%ZX5GAy>$UnM;E*tBd5bWa}`6N9hEX^VBX4c8OO@jy>Sr$_-pmKeRgy7?vH*c(;}5*{?6xk@s3;#CtBb6F&ZA4Z+9%cZ@{awbu!4k7B-z%&Qv?She~9(y8wkC=!jmK(PfMuan}Fb!(K?M|7|~6M ze1$0BO81lQ9?k@M7KcWqilThQfdAfV78_S)IELD4umk1dq+Dtg@Z@?Yxo3s>!WY?L zw1*gD3TWsLm&26Neky`?lh%oMXGgwr?nZ|qKeiXl$pp`C@?2TY!b?Y@YdT-fyM_wd zSnT5}JW9a3_4UFM>nj*GGHSg>Ragbq#Y{NysU$i9Kbfnv4!XCa|LBoD%?8D`7an*m zzYCo)khP!#KV{TS3zASr^70BNv0s|EQt#pR#UW;h=j`nfpP<7rb9uqNBtB`1R_WMw zAmrUF^Z3pZwC30&Gd+Ee34LVzV-gW36j+f=?!%N{ol!xh#g81?qla}$xC*`v#lX5B ze9mzY!_XIv=+}n)zD6jtvP0wIWO3u-fkXn>Os@{Y)2J+gUd$M}LfZO8gB*?(9*j-R z<(4jUhD9frx{w@dj}7%>g3%dcY!DV^??Vn-M!l@z)<3mW6`d%%hdX|N{}ro-$mLV_x-^ZyE-eoTd3p{h+TuVmF0Q|K)G!Sw zg$_I6nDVZ;IwMF_1Wn47_@O9ubM3E%x9@R{*hQ6{bl#P)YVaiFP8SqLCj6wRC8l1g zC|D#j@XGoQ#4a!f{#%vS{zog?3-#YW#LdI##|HMTUW%jbg$nD!=m%g(U`T;}Mf)Vu z_6slvVDEg!NVPtANW$p8TyiOZuH|KIKyyBMQb7}VCF=YLnNgGqg8e$vD)GsS(-2?u zoo|wBDWfY>EK7AfR zi)lEKiHo!`55LxR35DXfK3))*+8xnrBE1Y$w-9S!1#}8b2y-b`tV!q41)|Y&%J|j! z7=Q2wrGAh*#@7&l>J`o~V}`YLa3K*kH6!QVimkcmVB6h*?v&~9gCgjWU*taKW^rN9 z_9UJp5(l#oQmg&#K@A^H+8JrfRE(7carLJ%SD0Cb8TWG!1djF?a=ChmKJt6|N!Tf6 z?6QXene&4l!v$*OxXol*DNb^x5uwjCo5CNnvp=vm8AbY|A7dDU=_3eFy{P!OIS#f? zLTy>QF**iN?}nDo#4B^Ll8B*t=EE=1OzTsx_g_VqH1q9VB&?vka$6kcMn~5PP zerc=MLV(y^mB_(sx-jY)2*ee`siHauw$N3k?~Z4@AXghjLaUHpUC4B>gBnI8RFzvk zjsRw8LP(PGL7yM=kz0#Q?GLlG^*2WV7j~DzOAp#kYo2i($}?Inx(j!b8!yoQTMlkg zNJA-ZA+PDlaZzhstbvH;2d+<44JFNxP@Qq>5Vo)cBFhTaWuVzDu}jv|X)HQcv#y`H zv6>_0!|YOsr@}(*ac#uMBn1(ZfmbtQ$QhC#w$G%O4b(8sBf+M5ycn%fNBu2lpy_5N zgH48rN|GWvvg>-e{Xl_WCBFycghy? zWeXb%@Kq_WvDscRqb_E~_03ePfHBU>oqLwOgL)jQmV95tAHxLwPrkvG2wkrg0KnUZL;yHH+mP9Ew%&R&>hWR+21n1%Ywx|i+i9&oIAI%03;bZ1=F09A=`_g5 zF7TK}TPYAceI`!CILAsXs#H_WL^q2{A{~XJrg)7!PcU6lvY<-L1D=gCjZSm*Pp}|| z)+vP|-<9wlFpv$Lz5Ek^{2Pg_A0|8_fD=%U-2 zp1=KF6|cvhR;Y<{hXA3!H6P2%@ndRThGepB%e*>0=H}f^tHbSuW39;g697`0S#2MB zjg)qH$C5973?(DWWRmzL*4~JQ4XqG7%)KXgEs^^B+=T|4*VfK-7O!*#;HXa!JBG4| znnyN=RZlc&O3(6n1~J(YaqlVV_(}7X68HEPJ+|j@0c(cY*r8MPh+81fF}Q{;cnlj; zFMr%gorB5^XyhrytgI_%Jyo1=(9h49r zS4$_<{}ZsLoAp#^JmZEVjBMg}maCPt88> zNvu>;jMYml_Z|HMV9vNZ+2J40Y;*FMju1XK_R2_%BEzMy87~Q;!Qje>6#J#czGd&y zFF#blVi!3JacH$G>?2TOFOsX}9 zUMwRwwy2!)EGqS0oc_{2SvmjFB0#cvCUWCIYGwBVs-v3i-{cb_mX+Gfq^XGNqtRd~ zpo4p6K&c!Iw{f!sn>xU>X?RULfLv)y+7iv5&q<$>pd~IIlL!X+O4zk>_Qu(VI%rVP zf;63LD7<6Zal$?BVVH!Vhca=#LTccYe+hLQlNKG8kw6r=Mj0!B^J6hBInf{+AX*ch zoL@FBsGKSXmJ=6QA1bEiR(poBtcMlg;Ha&Qmi%#3C&fL| zD)lzq`5g2bf3S3}T1+eynxfADDR2&Ruw95nM(Uzv^(PmEb1j}3T4@FgkYP_F-UK?G zWMrv%*V{86dDCtf>kkX|MQTGDEr*m)^t`07ZO-WWz(fhPNJS7nXfdbXPSI+KP)a&$ zi_ta9)ZmP}nPW)lasZ)pWG7}P(!qHG-0e{O2b@0$OyB5Q4Swe@K0&d9LP0J%xa{a9 zg^z98`(P zCn?ooxOkW5VV11NDDh4!9ABdGNy(;UE*KL-Hc*7f{3BBj(nvO$u4v~X9N=vK#Ot1`4B#oh$djLL^#;Q?#Hd>QE=RWLy@_1>Yc6BH)@71q?Pt1B18k@sWa;*gv6I;2+j=lKrs1T?q%0s zt7!228e}e*o0mRMS8=f<>cla4RQ1#_)N_Q^kE=?WW}{qY;RY`}GBPOWI=mn#5`71kWEHotQ?MK=V_S+A*o1QoN51Ti%=?Ujs4*&E86n}E0bX)(qjV>SAVt2_Zo zsxB!OGj=X`DMRPrN2{4U!%F==VA85|@y1cQkirj!cYddZqDC;}7Mgak z3%SIrko_plK$0OJy60k}-Fv(7z{mUh05o+7nEXQ`0%*~sp}(3ClW8YHU&R(HmSZG6 zPC{tshbuUchyuyBh?9^?2OBfy_$-WA|Jifn-WbM0L=a5~;Nm#aCkQax>_SPRtev=s zDl2^I_0=h87!)Ff+*VvaaypObragQ{Vq`r!*6j=c%&0Vf8={hU>q4bDaRiG%JD)&h zoFd;V(ubWSb0LLxafb&npdSvdtQmiNSi*1%-J~lm&MWseQEpmld+ccrjiAPI)&gNt z7wUkvweK5tYgCEk{9bA|DPu0p*yjk_vw|v&nJN@}`z1U5?D)~@L}g)a+<1DI%&MR( zHHz&AXMew;kRl~d2I|(+0r|`Sk+?1FrQu?SJiSAuH7&dR4gv(d;IZeN19#qI3}B)l ziOI`~ih89r5Wk^(5f{l?jtApVQ1}=ee6r;RM{i1B&igxvCG6Iq70v`>Bf(dWf0RBm zAaTRkun?XR%UG3nWmMJ9Za9}Cc5vu6N7NqlT+aE|?WWJvslZ!_;XX!i!DEgek!RHk>aKCKxt8Tw z;ETH;sQA1#NNV4T!?X! ziNl~IcP9`9HgD%kf`d&WoE)blDy+gi`LOWix6EV7NZLscfdc_uEgP^CGi3lCDCZWL z9Efec{)g+DQqwfSg>{*LB{99v*qwH8ytq0A(E=6S+{d z7AsBHogCrquz|yyLh~#YzWjM{&oufdjLa(*f$*F0^2WwQzn7iEVcs&T(TfD*_zG1h znI!#YPt0@T8>~p)A8h!A%uF0S0lk62X^iN@9-Hozy%xIAUYR_8wRC-S4|j3UOm(oPubuP2Tzzjuy^W&(8dv3j>l?j8TA=gcFN)hbIth&sJb z7_0MG!-?0Vj)h3d)sqfMZR)vt96*0p$IzGf_dSK4@8#V11pb^@UXZ>ja6a>Min`wD zn{3L;6W~*zK}?u9#Hig)zp5cLXz%jp0?LYL$YT8bVf1 z!N68;qr-yGmcu8yg}wa{qTh`%?@iM6;mw!%O;er^bR7RJ8YbCj<8>1sWgwq|FAo1# zK05oMV*9Vw!-`$-g{}2)+h6V^d(KQ`G>|JRuIo+aJe{6?6P}p0!*`~~j}?uG!7Y)| zqpVwRBY)EQ%7XS`M3g|r$eM!9-MLABVM;zL%PK(SDTkJbwajMpz*qr21R zD6R03xh%!M;Dy?glWn$KhCF0)M|02%Zo$ybH-ZF=3%l_v$}0}^sGm97J6?Yr2vk9~ zF7qJyfR;RDTGt8NuBd%{1g3cGl?e!Y;mDIi)r`see`x!hTDu#~c3?A#eISdDS4$+G z>@LUrfxl9D5fOu8(6=n@@krl-dVVu_KWBIdDSkUz6<73hlT=>yd@v|2P}OVO8?qbq zO1Ve@moQ7>A3_*0B6Kg8Slv)5xmT4#^Cb8h>2O`Q>mITOixgRF0!@%U=r6kHyPHfQ#OR}lRt1EX=c}QLT5?hRu`NLNi?3S$oi|li3nt5y zn#PlVJo*(SzysP{)g`}@eem6AXD$KX`D0au?VaUXPC{)|>GNSA&*;`OFDT8ikXy4u z%~LeOXc@%)SDUkN#(=`OyD>HmCNdOQz2hOo6Mz=b?La*R<>7`TwS91(x|gaAFz3AR zKghM;j=Sd7k$Y^!bajQV*C2Nj4!Xd4n_RD9#QgXSNg3U~zsCxv3=4;$jte~0!B{povMC@C^U0<^%0So|8{!Km&)bo=-)pE- zzZ^#C_sPibf4_En|9~=`>n#h{tE4&?w)}e4g=>KtQvY!vEy~rHJ&D(}5y~o#yP1h# z@P34;5Z^)I@4Xb4`G!{Q88#-L-0U1iK{e2y+2?LBN=6W6C_Ru^BHdrUoBISeZh*ki z{_5Ojc$@775y0U{x8RV-q*6Q-JeF5!q!NrJo~OXfhVt%_yMpij#X~ziQ1~;>IZ2HP z`nN*RWvP5#P`dy5I{we$LC#RCGAZ%B`>B9L|pbfSqd3QKq%ybB_Ml;43evjC#LLl~GNtZWjiL z=Gf%(UWPvY53f~GkKYAZ^V@e+emC3iOjlcJw>ez^@xz5KgNb&0h8n*ZZ9U5msISzj zVvMgxH<66l&zmrT{!-boJ=f1*^E5Oj{S~!AA49hgVnGD4FdW&#g+Xk)}Z9{1Ux zGHZN!K8;{%^4E0NIm-E+2X7HwG&n-xpR(lDViwHdV364FJib=Yqw>a7mL>_@5U_TM zCR>NtiWt)L8KXsTMu++Ac$=5(AEz*`XkT1@4j2_d+a*y zs?=JQ*F%@PJ{XAnxAwz<#90-HOJ-b1OR_!Fa}Ju! zG-l9IXLeRNZtnZTl>5uJ$etr9_b1ep#1hLZP=R$r%;8I2XugRCSm6 zJuq`hP5A76%d=H3S=F4-dFlFku#xs-z zPp8y#l0&YGlNCoDqH>i~T8acYNsK6XQBevL44M6HW=}L}rXVHJGERk{iM`c-8JK~G01{OE$SN?easmP1c>;NGF^y~TU=D8j>PNd`O8_C@P$rB zX^O)!#j`Eb?x66m>{?cC?hw7f_1?=Nd&G1$M0Aq9dGF~Oo$ZxO>y-tiYWFtmood5@Zw>fS!g9*)sCIp-D11IatU`p1B5E96-Rk3ZgfIl26DM22g%@Y^ zVDtP)6`}JJ%p2#oHe?>Ri-7_d*wG`x-|ZZ*Bjk$B99Ls`YPxZ|J>78noxZ5O-YY5u zYHzS^U_8;-0%RJJ#B=)XEOPWt}<}r@47rs<0w}c+~+=2#{5JYn7meM=$9_fu0*7lC& zL^!rX*zoMz8jEE2Ts~Ps$cN(g$SkQmtReyhNIl#S0Wx&u{q2iDlX1Er?#~F*biO~s za+dn~k=2eKZRuw$%6H;^!k#p_^NMzymS}D{5vL?fqo0PFz-r`K*#D@uk2{HiiYR6k zQUN^n$rbOJNOHrLP!H!`?Mh2Oa_@|}!hBPBHMHw)HAK&Whqd$Wz~`!%PIjQ`J2s?q zgJrLCWt0RapMsGm;VOosl*w>=n%|J&tL&Zr=6jM#vGqAR)WCIexL)?01POp4UY#8n z$YB+44mAn^pK5=!q;wbYi@kP;Job#pwB)Lj6mOUxaYI?<+BNj=iFkgX9LB*O+e=za zs|N{cm!bluu4ECTK~dmx(kGymJPdIY$m}Jj5;`UPbif#u@?K`op&q5Fp%VN+j<-lI zdyg+TwxzP2&D|ot{$ygQ ztMekn^bTSmr6Ku|OQImK??agK8N5lRLoeOya3%6f#dNUL)*ZK|EkdAtOLr)re1$Yx zB$PNfIOvwAM-$FtvG}S&Ud4frkMI^YVHx&9i*p z%ReGVJ9os}es@Yvfwr@+%vb{ZlrwR2le^yid}zJxUew0#SkK1W-xV?G+$zpsJ4?WP z%#art`(|`%*O-dNkm=R4S+V_IQ3dZ;*-N0Ct!IV+SdaDu>|_CL&fMNf!E^F^j`nvD zU)O4dr_P^^<}Z%&x+;~c9^PZ-u(46Ist`RQ~1uT-k0Z9ezC3IIK-U} z#OrF);mAZDhcMN~&{w8HMzOKgQ*yh440-bgYh}NG9)_(J*59ZdNz{^v z^N}g6DtU%1OoQtm7KY;TtnCKJo=&A0xR4@Cq>;juutwx$Ozw4Qa2(Sg=0!Su^hb?j z-xJ+6E_FOr1*P;02NPqqi02-IOo7z4mMFojSRkFMZ(!dYYCHfW4?w$Wu;9nk9ZRg3 z8effdoqP(4k%FP!eQ!wA>x49(DkwFR%f`+}bZIK=d6LD=Uzmj8)R0YCUaR)z28+H~ zG3fg+Ti3bNg^(agfx5CaN_&;G`qz*c1{6po7b;EIg z4_GkW5*Lt`TTdG>>aoS9*&ief^6qNIo1(be`+~+%!ZnlnUv$BJUF*VNrr?s`U7`tq z#;sUe{DyWfU^hwW8TyG<0Ho$JL?O0u{zI5#Epmto^+;F@AFzf&GQP6 zzD?9ZJ@!FmG0UMGNx7BjIQbqJ8rRX;vF2@sNt%77Q&Luis2U1O7)`t=-m7bO2>hXZ z*_fX@Ssrm3)fn&N99b)lXcw~UBTb|b$JVOs=Qa4CBBq1?ohxV0r z8@B$j=KTd!>0;6*+(m`K--5Ku0O5#UFCtpT^-=hsJ_wFNVvY~e8KYWIj@>^%OVfzV z89O8`LxAv@;gi)Yr>R{XA0eQrTv?!s+k9a~0{dRHS-r2!0+`y0`Tj!69b3zitc7iD z$k40yD|dHeg17{%gPfL$_#Ix#_4+I+FlMoo zn%jMQBJQ6tC{VRZ}x3v^KtKQ zFoQd%Z1gF$>-LWIaFv2U@?fw*oG78~jrmM`JAJkRt7f!Y`^cIaOKp#aCNHRWD!cx2 z#<%{l_O8Ht7zG!Y;%ZQli(#L|O);D9O}&|8%w<;T3O#!%C+7CDl`eLP%={hI7)pN~ zana&_+kL`m-BXfeZpfVPdscn#srKZ`XF9^K(R|^21GaRt3forjHe~J@LL!{L{*(}Z zfSd#A?&j8D=ogxN3D7nA17=qKGjF5EJ9RZqwXw1t-dw6F1Xh*BGfXk7Uj{Aa!aZr_-N>f( ztRjhw9A8?wmd{S~lIK8_-nA*pyEq@pdlsf_>6<;>Z1XIa9clmqv2WgvIC&V}Cv021 zt8Y6W%}Xyvyyg!PpE#;u)IbB2(F{cck(g>0Vft4$5~_F;2a0A+l^b>m`3XW()63iZGER@LQte-{w{v}7*T{Ho!C>H i&KAi}{r~6u3$vQGHlFDBwA4R;Zb*vCiPQ=i1pO~oE5T?0 literal 0 HcmV?d00001 diff --git a/iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/180.png b/iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/180.png new file mode 100644 index 0000000000000000000000000000000000000000..6327000a83a202159b4728616c3616d35c45255e GIT binary patch literal 26576 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 l$M7GX|G)Ns4amP|{k(?!Ivrh@O)&CV19 zv)cAG=HFO&($8lkWi0RiIF<|}`zxOjz(R?R(-^f3p|KiWl`%@pgST<3fop#dUo6uC(F$ zq~Xdw>z#ZNeB3cXzlV1&%3k`)RkKB$8EsduER(nPK-Qv&&ST$;c?f1P_aWWV1gixU zd2Nv?3v=

r&Ug_F2WK7;#y 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 H*5UsHCm9#` literal 0 HcmV?d00001 diff --git a/iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/40-1.png b/iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/40-1.png new file mode 100644 index 0000000000000000000000000000000000000000..586d20f5c2e0174c469b1fedbf803c54965105ce GIT binary patch literal 5863 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 F{{U_rt#kkY literal 0 HcmV?d00001 diff --git a/iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/40.png b/iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/40.png new file mode 100644 index 0000000000000000000000000000000000000000..586d20f5c2e0174c469b1fedbf803c54965105ce GIT binary patch literal 5863 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 F{{U_rt#kkY literal 0 HcmV?d00001 diff --git a/iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/58-1.png b/iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/58-1.png new file mode 100644 index 0000000000000000000000000000000000000000..c9ea4568e639d3b0f6f4b5cc20fb029488de3483 GIT binary patch literal 8056 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 p3T{Qpz literal 0 HcmV?d00001 diff --git a/iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/80-1.png b/iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/80-1.png new file mode 100644 index 0000000000000000000000000000000000000000..7e4bc7468049fbfa67ef30a776953eb013c99c41 GIT binary patch literal 11885 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 literal 0 HcmV?d00001 diff --git a/iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/80.png b/iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/80.png new file mode 100644 index 0000000000000000000000000000000000000000..0d8ad8dcb9f84c54998827379411aaaf5d4a3ad2 GIT binary patch literal 10651 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 literal 0 HcmV?d00001 diff --git a/iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/Contents.json b/iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/Contents.json index d8db8d65..4d575c16 100644 --- a/iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/iOS_Tips/DarkMode/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,98 +1,110 @@ { "images" : [ { + "filename" : "40.png", "idiom" : "iphone", - "size" : "20x20", - "scale" : "2x" + "scale" : "2x", + "size" : "20x20" }, { + "filename" : "60.png", "idiom" : "iphone", - "size" : "20x20", - "scale" : "3x" + "scale" : "3x", + "size" : "20x20" }, { + "filename" : "58.png", "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" + "scale" : "2x", + "size" : "29x29" }, { + "filename" : "80-1.png", "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" + "scale" : "3x", + "size" : "29x29" }, { + "filename" : "80.png", "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" + "scale" : "2x", + "size" : "40x40" }, { + "filename" : "120-1.png", "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" + "scale" : "3x", + "size" : "40x40" }, { + "filename" : "120.png", "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" + "scale" : "2x", + "size" : "60x60" }, { + "filename" : "180.png", "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" + "scale" : "3x", + "size" : "60x60" }, { + "filename" : "20.png", "idiom" : "ipad", - "size" : "20x20", - "scale" : "1x" + "scale" : "1x", + "size" : "20x20" }, { + "filename" : "40-1.png", "idiom" : "ipad", - "size" : "20x20", - "scale" : "2x" + "scale" : "2x", + "size" : "20x20" }, { + "filename" : "29.png", "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" + "scale" : "1x", + "size" : "29x29" }, { + "filename" : "58-1.png", "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" + "scale" : "2x", + "size" : "29x29" }, { "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" + "scale" : "1x", + "size" : "40x40" }, { "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" + "scale" : "2x", + "size" : "40x40" }, { "idiom" : "ipad", - "size" : "76x76", - "scale" : "1x" + "scale" : "1x", + "size" : "76x76" }, { "idiom" : "ipad", - "size" : "76x76", - "scale" : "2x" + "scale" : "2x", + "size" : "76x76" }, { "idiom" : "ipad", - "size" : "83.5x83.5", - "scale" : "2x" + "scale" : "2x", + "size" : "83.5x83.5" }, { "idiom" : "ios-marketing", - "size" : "1024x1024", - "scale" : "1x" + "scale" : "1x", + "size" : "1024x1024" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/iOS_Tips/DarkMode/Base.lproj/LaunchScreen.storyboard b/iOS_Tips/DarkMode/Base.lproj/LaunchScreen.storyboard index 3962dc99..36cf6dc9 100644 --- a/iOS_Tips/DarkMode/Base.lproj/LaunchScreen.storyboard +++ b/iOS_Tips/DarkMode/Base.lproj/LaunchScreen.storyboard @@ -1,9 +1,9 @@ - + - + @@ -20,7 +20,7 @@ + + + + + + + + - + + + - + + + + From a39017b7c3b185e7cbead80be11fb49d338f99a6 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sun, 28 Jun 2020 09:21:34 +0800 Subject: [PATCH 028/356] =?UTF-8?q?UI=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/Crash/SLCrashViewController.h | 2 +- iOS_Tips/DarkMode/Crash/SLCrashViewController.m | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/iOS_Tips/DarkMode/Crash/SLCrashViewController.h b/iOS_Tips/DarkMode/Crash/SLCrashViewController.h index e32441a4..90149940 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashViewController.h +++ b/iOS_Tips/DarkMode/Crash/SLCrashViewController.h @@ -11,7 +11,7 @@ NS_ASSUME_NONNULL_BEGIN //iOS Crash防护 -@interface SLCrashViewController : UIViewController +@interface SLCrashViewController : SLViewController @end diff --git a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m index e7d561f5..1b073d87 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m @@ -28,13 +28,11 @@ - (void)viewDidLoad { [super viewDidLoad]; [self setupUI]; } -- (void)dealloc { - NSLog(@"SLCrashViewController 释放"); -} #pragma mark - UI - (void)setupUI { self.navigationItem.title = @"iOS Crash防护"; + self.view.backgroundColor = [UIColor whiteColor]; [SLCrashHandler defaultCrashHandler].crashHandlerBlock = ^(SLCrashError * _Nonnull crashError) { // NSLog(@"%@/%@" ,crashError.errorDesc, [BSBacktraceLogger bs_backtraceOfCurrentThread]); }; From b70723bde2b0fb5223e58b19b188d161680762af Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sun, 28 Jun 2020 20:29:05 +0800 Subject: [PATCH 029/356] =?UTF-8?q?=E5=9B=BE=E9=9B=86=E6=B5=8F=E8=A7=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 32 +- .../WebNative/SLPictureBrowseController.h | 24 + .../WebNative/SLPictureBrowseController.m | 494 ++++++++++++++++++ .../WebNative/SLPictureTransitionAnimation.h | 30 ++ .../WebNative/SLPictureTransitionAnimation.m | 95 ++++ .../{ => WebNative}/SLReusableManager.h | 4 +- .../{ => WebNative}/SLReusableManager.m | 25 +- .../SLWebNativeViewController.h | 0 .../SLWebNativeViewController.m | 21 +- .../WKWebView/{ => WebNative}/WebNative.html | 0 .../{ => WebNative}/WebNativeJson.txt | 0 .../WorkIssues/SLWorkIssuesViewController.m | 6 +- 12 files changed, 712 insertions(+), 19 deletions(-) create mode 100644 iOS_Tips/DarkMode/WKWebView/WebNative/SLPictureBrowseController.h create mode 100644 iOS_Tips/DarkMode/WKWebView/WebNative/SLPictureBrowseController.m create mode 100644 iOS_Tips/DarkMode/WKWebView/WebNative/SLPictureTransitionAnimation.h create mode 100644 iOS_Tips/DarkMode/WKWebView/WebNative/SLPictureTransitionAnimation.m rename iOS_Tips/DarkMode/WKWebView/{ => WebNative}/SLReusableManager.h (90%) rename iOS_Tips/DarkMode/WKWebView/{ => WebNative}/SLReusableManager.m (95%) rename iOS_Tips/DarkMode/WKWebView/{ => WebNative}/SLWebNativeViewController.h (100%) rename iOS_Tips/DarkMode/WKWebView/{ => WebNative}/SLWebNativeViewController.m (90%) rename iOS_Tips/DarkMode/WKWebView/{ => WebNative}/WebNative.html (100%) rename iOS_Tips/DarkMode/WKWebView/{ => WebNative}/WebNativeJson.txt (100%) diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 7714bfda..41e054ba 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -77,6 +77,8 @@ 78665C70246D4B9F0001B749 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 78665C6F246D4B9F0001B749 /* SystemConfiguration.framework */; }; 78665C72246D4BB10001B749 /* libicucore.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 78665C71246D4BB10001B749 /* libicucore.tbd */; }; 78665C74246D4BBB0001B749 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 78665C73246D4BBB0001B749 /* libsqlite3.tbd */; }; + 7869C72224A8B6D200527546 /* SLPictureBrowseController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7869C71E24A8B6D100527546 /* SLPictureBrowseController.m */; }; + 7869C72324A8B6D200527546 /* SLPictureTransitionAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 7869C72124A8B6D200527546 /* SLPictureTransitionAnimation.m */; }; 78777CE0238FEA48006FA671 /* SLOpenGLController.m in Sources */ = {isa = PBXBuildFile; fileRef = 78777CDF238FEA48006FA671 /* SLOpenGLController.m */; }; 78777CE6238FF65C006FA671 /* SLDelayPerform.m in Sources */ = {isa = PBXBuildFile; fileRef = 78777CE5238FF65C006FA671 /* SLDelayPerform.m */; }; 787C7DBE245D74E4005DF7ED /* NSMutableArray+SLCrashProtector.m in Sources */ = {isa = PBXBuildFile; fileRef = 787C7DB2245D74E3005DF7ED /* NSMutableArray+SLCrashProtector.m */; }; @@ -281,6 +283,10 @@ 78665C6F246D4B9F0001B749 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; 78665C71246D4BB10001B749 /* libicucore.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libicucore.tbd; path = usr/lib/libicucore.tbd; sourceTree = SDKROOT; }; 78665C73246D4BBB0001B749 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; }; + 7869C71E24A8B6D100527546 /* SLPictureBrowseController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLPictureBrowseController.m; sourceTree = ""; }; + 7869C71F24A8B6D100527546 /* SLPictureBrowseController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLPictureBrowseController.h; sourceTree = ""; }; + 7869C72024A8B6D200527546 /* SLPictureTransitionAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLPictureTransitionAnimation.h; sourceTree = ""; }; + 7869C72124A8B6D200527546 /* SLPictureTransitionAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLPictureTransitionAnimation.m; sourceTree = ""; }; 78777CDE238FEA48006FA671 /* SLOpenGLController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLOpenGLController.h; sourceTree = ""; }; 78777CDF238FEA48006FA671 /* SLOpenGLController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLOpenGLController.m; sourceTree = ""; }; 78777CE4238FF65C006FA671 /* SLDelayPerform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLDelayPerform.h; sourceTree = ""; }; @@ -654,6 +660,23 @@ path = SLCrashProtector; sourceTree = ""; }; + 7869C71D24A8B5CA00527546 /* WebNative */ = { + isa = PBXGroup; + children = ( + 78BDE051248E0BEB002ED386 /* WebNative.html */, + 78BDE057248E541E002ED386 /* WebNativeJson.txt */, + 78BDE04E248E0AFB002ED386 /* SLWebNativeViewController.h */, + 78BDE04F248E0AFB002ED386 /* SLWebNativeViewController.m */, + 7884248C24963FD200C2E505 /* SLReusableManager.h */, + 7884248D24963FD200C2E505 /* SLReusableManager.m */, + 7869C71F24A8B6D100527546 /* SLPictureBrowseController.h */, + 7869C71E24A8B6D100527546 /* SLPictureBrowseController.m */, + 7869C72024A8B6D200527546 /* SLPictureTransitionAnimation.h */, + 7869C72124A8B6D200527546 /* SLPictureTransitionAnimation.m */, + ); + path = WebNative; + sourceTree = ""; + }; 78777CDB238FEA15006FA671 /* OpenGL */ = { isa = PBXGroup; children = ( @@ -952,20 +975,15 @@ children = ( 78BDE04C248BFBD7002ED386 /* wsl.png */, 78E72D58247BA29600751373 /* WebTableView.html */, - 78BDE051248E0BEB002ED386 /* WebNative.html */, - 78BDE057248E541E002ED386 /* WebNativeJson.txt */, 78E72D71247E861300751373 /* SLWebViewListController.h */, 78E72D72247E861300751373 /* SLWebViewListController.m */, 78E72D4F24766E4B00751373 /* SLWebViewController.h */, 78E72D5024766E4B00751373 /* SLWebViewController.m */, 78BDE049248A6A74002ED386 /* SLUrlProtocolAddCookie.h */, 78BDE04A248A6A74002ED386 /* SLUrlProtocolAddCookie.m */, - 78BDE04E248E0AFB002ED386 /* SLWebNativeViewController.h */, - 78BDE04F248E0AFB002ED386 /* SLWebNativeViewController.m */, - 7884248C24963FD200C2E505 /* SLReusableManager.h */, - 7884248D24963FD200C2E505 /* SLReusableManager.m */, 78842452248F863500C2E505 /* SLTableViewController.h */, 78842453248F863500C2E505 /* SLTableViewController.m */, + 7869C71D24A8B5CA00527546 /* WebNative */, 78E72D8324822E7500751373 /* WebTableView */, 78E72D9324852C2F00751373 /* WebCache */, ); @@ -1293,6 +1311,7 @@ 782E3EB42373D8C7001E0DF9 /* SLAvWriterInput.m in Sources */, 78804A7E237D5E3E0087E152 /* SLWaterMarkController.m in Sources */, 78EF8B6024162B96008D0CD7 /* SLMenuViewController.m in Sources */, + 7869C72224A8B6D200527546 /* SLPictureBrowseController.m in Sources */, 78D30964239688EF00DC373A /* GLESUtils.m in Sources */, 784B720923348241006AEE47 /* SLAvCaptureTool.m in Sources */, 786147F42362D79000C5424C /* SLMosaicView.m in Sources */, @@ -1346,6 +1365,7 @@ 78E72D5124766E4B00751373 /* SLWebViewController.m in Sources */, 78B10493232F57C50051579F /* main.m in Sources */, 788424C724978E9200C2E505 /* SLKeyChain.m in Sources */, + 7869C72324A8B6D200527546 /* SLPictureTransitionAnimation.m in Sources */, 78E179372351A40D0007E4BB /* SLShotFocusView.m in Sources */, 787C7DC8245D77D9005DF7ED /* SLZombieCatcher.m in Sources */, 78A4BD45236C5DF20021AE32 /* SLEditVideoController.m in Sources */, diff --git a/iOS_Tips/DarkMode/WKWebView/WebNative/SLPictureBrowseController.h b/iOS_Tips/DarkMode/WKWebView/WebNative/SLPictureBrowseController.h new file mode 100644 index 00000000..c054d022 --- /dev/null +++ b/iOS_Tips/DarkMode/WKWebView/WebNative/SLPictureBrowseController.h @@ -0,0 +1,24 @@ +// +// SLPictureBrowseController.h +// TELiveClass +// +// Created by wsl on 2020/2/28. +// Copyright © 2020 offcn_c. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol SLPictureAnimationViewDelegate +//用于转场的动画视图 +- (UIView *)animationViewOfPictureTransition:(NSIndexPath *)indexPath; +@end + +/// 图集浏览控制器 +@interface SLPictureBrowseController : UIViewController +@property (nonatomic, strong) NSMutableArray *imagesArray; +@property (nonatomic, strong) NSIndexPath *indexPath; //数据来源索引 +@end + +NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/WKWebView/WebNative/SLPictureBrowseController.m b/iOS_Tips/DarkMode/WKWebView/WebNative/SLPictureBrowseController.m new file mode 100644 index 00000000..e1e3520e --- /dev/null +++ b/iOS_Tips/DarkMode/WKWebView/WebNative/SLPictureBrowseController.m @@ -0,0 +1,494 @@ +// +// SLPictureBrowseController.m +// TELiveClass +// +// Created by wsl on 2020/2/28. +// Copyright © 2020 offcn_c. All rights reserved. +// + +#import "SLPictureBrowseController.h" +#import + +/// 图片缩放视图 +@interface SLPictureZoomView : UIScrollView +@property (nonatomic, strong) UIImageView *imageView; +@property (nonatomic, strong) UIActivityIndicatorView *indicatorView; //下载指示器 +@property (nonatomic, assign) CGSize imageNormalSize; //图片原尺寸 +@end +@implementation SLPictureZoomView + +#pragma mark - Override +- (id)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self setupUI]; + } + return self; +} + +#pragma mark - UI +- (void)setupUI { + self.delegate = self; + if (@available(iOS 11.0, *)) { + self.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } else { + } + self.minimumZoomScale = 1.0; + self.maximumZoomScale = 2.0; + self.clipsToBounds = NO; + [self addSubview:self.imageView]; +} + +#pragma mark - Getter +- (UIImageView *)imageView { + if (!_imageView) { + _imageView = [[UIImageView alloc] init]; + _imageView.userInteractionEnabled = YES; + } + return _imageView; +} +- (UIActivityIndicatorView *)indicatorView { + if (!_indicatorView) { + _indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; + _indicatorView.frame = CGRectMake(0, 0, 30, 30); + _indicatorView.center = CGPointMake([UIScreen mainScreen].bounds.size.width/2.0, [UIScreen mainScreen].bounds.size.height/2.0); + } + return _indicatorView; +} +- (CGSize)imageNormalSize { + if (_imageNormalSize.width == 0) { + _imageNormalSize = CGSizeMake(self.frame.size.width, self.frame.size.height); + } + return _imageNormalSize; +} + +#pragma mark - HelpMethods +- (void)setImageUrl:(NSURL *)url { + + [[YYImageCache sharedCache] getImageForKey:[url absoluteString] withType:YYImageCacheTypeAll withBlock:^(UIImage * _Nullable image, YYImageCacheType type) { + if (!image) { + [self.indicatorView startAnimating]; + [self addSubview:self.indicatorView]; + }else { + [self.indicatorView stopAnimating]; + [self.indicatorView removeFromSuperview]; + } + }]; + + __weak typeof(self) weakSelf = self; + [self.imageView yy_setImageWithURL:url placeholder:nil options:YYWebImageOptionShowNetworkActivity completion:^(UIImage * _Nullable image, NSURL * _Nonnull url, YYWebImageFromType from, YYWebImageStage stage, NSError * _Nullable error) { + [weakSelf.indicatorView stopAnimating]; + [weakSelf.indicatorView removeFromSuperview]; + if (image == nil) { + return ; + } + weakSelf.imageNormalSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.width*image.size.height/image.size.width); + weakSelf.imageView.frame = CGRectMake(0, 0, weakSelf.imageNormalSize.width, weakSelf.imageNormalSize.height); + weakSelf.contentSize = weakSelf.imageNormalSize; + if (weakSelf.imageNormalSize.height <= [UIScreen mainScreen].bounds.size.height) { + weakSelf.imageView.center = CGPointMake([UIScreen mainScreen].bounds.size.width/2.0, [UIScreen mainScreen].bounds.size.height/2.0); + } + }]; +} + +#pragma mark - UIScrollViewDelegate +//返回缩放的视图 +- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { + return self.imageView; +} +//缩放过程中 +- (void)scrollViewDidZoom:(UIScrollView *)scrollView { + CGFloat imageSclaeW = scrollView.zoomScale * self.imageNormalSize.width; + CGFloat imageSclaeH = scrollView.zoomScale * self.imageNormalSize.height; + CGFloat imageX = 0; + CGFloat imageY = 0; + if (imageSclaeW < self.frame.size.width) { + imageX = (self.frame.size.width - imageSclaeW)/2.0; + } + if (imageSclaeH < self.frame.size.height) { + imageY = (self.frame.size.height - imageSclaeH)/2.0; + } + self.imageView.frame = CGRectMake(imageX, imageY, imageSclaeW, imageSclaeH); +} + +@end + + +#define KSLPictureBrowseSpace 8 // 浏览的图片间隔1/2 +/// 图片浏览单元 +@interface SLPictureBrowsingCell: UICollectionViewCell +@property (nonatomic, strong) SLPictureZoomView *zoomView; +@end +@implementation SLPictureBrowsingCell + +#pragma mark - Override +- (id)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self setupUI]; + } + return self; +} + +#pragma mark - UI +- (void)setupUI { + [self.contentView addSubview:self.zoomView]; + [self.zoomView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(self.contentView.mas_left).offset(KSLPictureBrowseSpace); + make.top.bottom.mas_equalTo(self.contentView); + make.right.mas_equalTo(self.contentView).offset(-KSLPictureBrowseSpace); + }]; + //解决 self.pictureZoomView 和UICollectionView 手势冲突 + self.zoomView.userInteractionEnabled = NO; + [self.contentView addGestureRecognizer:self.zoomView.panGestureRecognizer]; + [self.contentView addGestureRecognizer:self.zoomView.pinchGestureRecognizer]; +} + +#pragma mark - Getter +- (SLPictureZoomView *)zoomView { + if (!_zoomView) { + _zoomView = [[SLPictureZoomView alloc] init]; + _zoomView.backgroundColor = [UIColor clearColor]; + } + return _zoomView; +} +@end + +#import +#import +#import "SLPictureTransitionAnimation.h" + +/// 图集浏览控制器 +@interface SLPictureBrowseController (){ + UIViewController *_fromViewController; +} +@property (nonatomic, strong) UICollectionView *collectionView; +@property (nonatomic, strong) UIPageControl *pageControl; +@property (nonatomic, strong) UIButton *saveButton; +@property (nonatomic, strong) SLPictureTransitionAnimation *transitionAnimation; //转场动画 +@property (nonatomic, assign) NSInteger currentPage; //图片当前页码 +@end + +@implementation SLPictureBrowseController + +#pragma mark - Override +- (id)init { + self = [super init]; + if (self) { + self.transitionAnimation = [[SLPictureTransitionAnimation alloc] init]; + self.transitionAnimation.transitionType = SLTransitionTypePresent; + self.transitioningDelegate = self; //设置了这个属性之后,在present转场动画处理时,转场前的视图fromVC的view一直都在管理转场动画视图的容器containerView中,会被转场后,后加入到containerView中视图toVC的View遮住,类似于入栈出栈的原理;如果没有设置的话,present转场时,fromVC.view就会先出栈从containerView移除,然后toVC.View入栈,那之后再进行disMiss转场返回时,需要重新把fromVC.view加入containerView中。 + //在push转场动画处理时,设置这个属性是没有效果的,也就是没用的。 + self.modalPresentationStyle = UIModalPresentationOverFullScreen; + } + return self; +} +- (void)viewDidLoad { + [super viewDidLoad]; + [self setupUI]; +} +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; +} +- (void)dealloc { +} +- (void)viewSafeAreaInsetsDidChange { + [super viewSafeAreaInsetsDidChange]; +} + +#pragma mark - UI +- (void)setupUI { + self.view.backgroundColor = [UIColor blackColor]; + self.view.clipsToBounds = YES; + [self.view addSubview:self.collectionView]; + [self.view addSubview:self.pageControl]; + [self.view addSubview:self.saveButton]; + [self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(0); + make.bottom.mas_equalTo(0); + make.left.mas_equalTo(-KSLPictureBrowseSpace); + make.right.mas_equalTo(KSLPictureBrowseSpace); + }]; + [self.pageControl mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.mas_equalTo(self.view); + make.top.mas_equalTo(self.view).offset(SL_TopSafeAreaHeight); + }]; + if (self.imagesArray.count > 1) { + self.pageControl.numberOfPages = self.imagesArray.count; + self.pageControl.currentPage = self.currentPage; + self.pageControl.hidden = NO; + }else { + self.pageControl.hidden = YES; + } + if(self.imagesArray.count == 1) self.collectionView.scrollEnabled = NO; + self.collectionView.contentSize = CGSizeMake(self.imagesArray.count * (self.view.frame.size.width + 2 * KSLPictureBrowseSpace), self.view.frame.size.height); + self.collectionView.contentOffset = CGPointMake(self.currentPage * (self.view.frame.size.width + 2 * KSLPictureBrowseSpace), 0); + [self.saveButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.mas_equalTo(self.view); + make.bottom.mas_equalTo(-25-SL_BottomSafeAreaHeight); + make.size.mas_equalTo(CGSizeMake(120, 38)); + }]; + + //添加拖拽手势 拖拽图片退出图集浏览界面 + self.view.userInteractionEnabled = YES; + UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panPicture:)]; + [self.view addGestureRecognizer:pan]; + //单击手势 退出浏览 + UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTap:)]; + singleTap.numberOfTouchesRequired = 1; + singleTap.numberOfTapsRequired = 1; + [self.view addGestureRecognizer:singleTap]; + //双击手势放大 + UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTap:)]; + doubleTap.numberOfTouchesRequired = 1; + doubleTap.numberOfTapsRequired = 2; + [self.view addGestureRecognizer:doubleTap]; + [singleTap requireGestureRecognizerToFail:doubleTap]; +} + +#pragma mark - Getter +- (UICollectionView *)collectionView { + if (!_collectionView) { + UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; + layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; + _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; + if (@available(iOS 11.0, *)) { + _collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } else { + } + _collectionView.backgroundColor = [UIColor clearColor]; + _collectionView.delegate = self; + _collectionView.dataSource = self; + _collectionView.pagingEnabled = YES; + _collectionView.allowsSelection = NO; + [_collectionView registerClass:[SLPictureBrowsingCell class] forCellWithReuseIdentifier:@"SLPictureBrowsingCell"]; + } + return _collectionView; +} +- (UIPageControl *)pageControl { + if (!_pageControl) { + _pageControl = [[UIPageControl alloc] init]; + _pageControl.pageIndicatorTintColor = [UIColor grayColor]; + _pageControl.currentPageIndicatorTintColor = [UIColor whiteColor]; + } + return _pageControl; +} +- (UIButton *)saveButton { + if (!_saveButton) { + _saveButton = [[UIButton alloc] init]; + [_saveButton setTitle:@"保存" forState:UIControlStateNormal]; + [_saveButton setTitleColor:SL_UIColorFromHex(0xffffff,1.0) forState:UIControlStateNormal]; + _saveButton.titleLabel.font = [UIFont systemFontOfSize:14]; + [_saveButton setImage:[UIImage imageNamed:@"message_img_download"] forState:UIControlStateNormal]; + _saveButton.backgroundColor = SL_UIColorFromHex(0x393939,1.0); + _saveButton.layer.masksToBounds = YES; + _saveButton.layer.cornerRadius = 4; + [_saveButton addTarget:self action:@selector(saveButtonAction:) forControlEvents:UIControlEventTouchUpInside]; + } + return _saveButton; +} + +#pragma mark - HelpMethods +//返回当前页面用于转场动画的视图 +- (UIView *)currentAnimatonView { + SLPictureBrowsingCell *cell = [self.collectionView visibleCells].firstObject; + if (cell == nil) { + cell = [[SLPictureBrowsingCell alloc] initWithFrame: CGRectMake(0,0, self.view.frame.size.width, self.view.frame.size.height)]; + NSURL *imgUrl = self.imagesArray[self.currentPage]; + [cell.zoomView setImageUrl:imgUrl]; + UIView *tempView = cell.zoomView.imageView; + return tempView; + }else { + UIView *imageView = cell.zoomView.imageView; + UIView *tempView = [imageView snapshotViewAfterScreenUpdates:YES]; + tempView.frame = [imageView convertRect:imageView.bounds toView:self.view]; + return tempView; + } +} + +#pragma mark - EventsHandle +//拖拽即将推出图片浏览模式 +- (void)panPicture:(UIPanGestureRecognizer *)pan { + SLPictureBrowsingCell *cell = [self.collectionView visibleCells].firstObject; + SLPictureZoomView *zoomView = cell.zoomView; + CGPoint translation = [pan translationInView:cell]; + zoomView.center = CGPointMake(zoomView.center.x+translation.x, zoomView.center.y+translation.y); + [pan setTranslation:CGPointZero inView:cell]; + //滑动的距离百分比 + CGFloat percentComplete = 0; + percentComplete = (zoomView.center.y - [UIScreen mainScreen].bounds.size.height/2.0)/([UIScreen mainScreen].bounds.size.height/2.0); + percentComplete = fabs(percentComplete); + switch (pan.state) { + case UIGestureRecognizerStateBegan: + self.saveButton.hidden = YES; + break; + case UIGestureRecognizerStateChanged: + if (zoomView.center.y > [UIScreen mainScreen].bounds.size.height/2.0 && percentComplete > 0.01 && percentComplete < 1.0) { + self.view.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1 - percentComplete]; + zoomView.transform = CGAffineTransformMakeScale(1 - percentComplete/2.0, 1 - percentComplete/2.0); + } + break; + case UIGestureRecognizerStateEnded: + if (percentComplete >= 0.5 && zoomView.center.y > [UIScreen mainScreen].bounds.size.height/2.0) { + [self dismissViewControllerAnimated:YES completion:nil]; + }else { + self.view.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1]; + [UIView animateWithDuration:0.3 animations:^{ + zoomView.center = CGPointMake(([UIScreen mainScreen].bounds.size.width+KSLPictureBrowseSpace * 2)/2.0, [UIScreen mainScreen].bounds.size.height/2.0); + zoomView.transform = CGAffineTransformMakeScale(1, 1); + } completion:^(BOOL finished) { + self.saveButton.hidden = NO; + }]; + } + break; + default: + break; + } + +} +//单击退出出图片浏览模式 +- (void)singleTap:(UITapGestureRecognizer *)singleTap { + [self dismissViewControllerAnimated:YES completion:nil]; +} +//双击放大点击点 +- (void)doubleTap:(UITapGestureRecognizer *)doubleTap { + SLPictureBrowsingCell *cell = [self.collectionView visibleCells].firstObject; + SLPictureZoomView *zoomView = cell.zoomView; + //获得触摸点在imageView上的位置 + CGPoint tapPosionOfPicture = [doubleTap locationInView:zoomView.imageView]; + //获得触摸点在zoomView上的位置 + CGPoint tapPosionOfScreen = [doubleTap locationInView:zoomView]; + [UIView animateWithDuration:0.3 animations:^{ + if(zoomView.zoomScale != 1) { + zoomView.zoomScale = 1; + [zoomView scrollViewDidZoom:zoomView]; + zoomView.contentOffset = CGPointZero; + }else { + //获得点击的图片位置放大后的坐标 相对于ImageView + CGPoint newTapPosionOfPicture = CGPointMake(tapPosionOfPicture.x*zoomView.maximumZoomScale, tapPosionOfPicture.y*zoomView.maximumZoomScale); + zoomView.zoomScale = zoomView.maximumZoomScale; + [zoomView scrollViewDidZoom:zoomView]; + + if (newTapPosionOfPicture.y < zoomView.frame.size.height || zoomView.imageView.frame.size.height < zoomView.frame.size.height) { + // 放大后对应的点击点在图片上的位置 处在前一屏当中 + zoomView.contentOffset = CGPointMake(newTapPosionOfPicture.x - tapPosionOfScreen.x, 0); + } else { // 点击点在图片上的位置超过一屏时 + if (newTapPosionOfPicture.y > zoomView.imageView.frame.size.height - zoomView.frame.size.height){ + // 点击点在图片最底部一屏中 + zoomView.contentOffset = CGPointMake(newTapPosionOfPicture.x - tapPosionOfScreen.x, zoomView.imageView.frame.size.height - zoomView.frame.size.height); + }else{ + //点击点在图片中间层 + zoomView.contentOffset = CGPointMake(newTapPosionOfPicture.x - tapPosionOfScreen.x, newTapPosionOfPicture.y - tapPosionOfScreen.y); + } + } + } + } completion:^(BOOL finished) { + + }]; +} +//保存 +- (void)saveButtonAction:(UIButton *)btn { + PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus]; + if (status == PHAuthorizationStatusNotDetermined) { // 用户还没有做出选择 + // 弹框请求用户授权 + [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) { + if (status == PHAuthorizationStatusAuthorized) { + // 用户第一次同意了访问相册权限 + [self saveImageToPhotosAlbum]; + } + }]; + return; + }else if (status == PHAuthorizationStatusRestricted || status == PHAuthorizationStatusDenied) { + // [self showOnlyTextWithHint:@"App需要经过您的同意,才能保存图片到相册"]; + return; + } + [self saveImageToPhotosAlbum]; +} +//保存图片到相册 +- (void)saveImageToPhotosAlbum { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + NSURL *url = self.imagesArray[self.currentPage]; + [[YYImageCache sharedCache] getImageDataForKey:[url absoluteString] withBlock:^(NSData * _Nullable imageData) { + if (imageData) { + ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; + [library writeImageDataToSavedPhotosAlbum:imageData metadata:nil completionBlock:^(NSURL *assetURL, NSError *error) { + dispatch_async(dispatch_get_main_queue(), ^{ + if (error) { + // [self showOnlyTextWithHint:@"保存失败"]; + }else { + // [self showOnlyTextWithHint:@"保存成功"]; + } + }); + }]; + } + + }]; + + }); +} + +#pragma mark - UIScrollViewDelegate +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + //四舍五入 + self.currentPage = roundf(scrollView.contentOffset.x/(self.view.frame.size.width + 2 * KSLPictureBrowseSpace)); + self.pageControl.currentPage = self.currentPage; +} +- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { + self.currentPage = scrollView.contentOffset.x / scrollView.frame.size.width; + self.pageControl.currentPage = self.currentPage; +} + +#pragma mark - UICollectionViewDelegate, UICollectionViewDataSource +- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { + return 1; +} +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + return self.imagesArray.count; +} +- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath { + SLPictureBrowsingCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"SLPictureBrowsingCell" forIndexPath:indexPath]; + NSURL *imgUrl = self.imagesArray[indexPath.row]; + [cell.zoomView setImageUrl:imgUrl]; + return cell; +} +- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { +} + +#pragma mark - UICollectionViewDelegateFlowLayout +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { + return CGSizeMake([UIScreen mainScreen].bounds.size.width + 2 * KSLPictureBrowseSpace, self.collectionView.frame.size.height); +} +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { + return 0; +} +- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { + return UIEdgeInsetsMake(0, 0, 0, 0); +} + +#pragma mark - UIViewControllerTransitioningDelegate +// 自定义转场动画 +//返回一个处理presente动画过渡的对象 +- (id )animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source { + _fromViewController = source; + self.transitionAnimation.transitionType = SLTransitionTypePresent; + if([source conformsToProtocol:@protocol(SLPictureAnimationViewDelegate)]) { + if ([source respondsToSelector:@selector(animationViewOfPictureTransition:)]) { + self.transitionAnimation.fromAnimatonView = [source performSelector:@selector(animationViewOfPictureTransition:) withObject:self.indexPath]; + } + } + self.transitionAnimation.toAnimatonView = [self currentAnimatonView]; + return self.transitionAnimation; +} +//返回一个处理dismiss动画过渡的对象 +- (id )animationControllerForDismissedController:(UIViewController *)dismissed { + self.transitionAnimation.transitionType = SLTransitionTypeDissmiss; + if([_fromViewController conformsToProtocol:@protocol(SLPictureAnimationViewDelegate)]) { + if ([_fromViewController respondsToSelector:@selector(animationViewOfPictureTransition:)]) { + self.transitionAnimation.toAnimatonView = [_fromViewController performSelector:@selector(animationViewOfPictureTransition:) withObject:self.indexPath]; + } + } + self.transitionAnimation.fromAnimatonView = [self currentAnimatonView];; + return self.transitionAnimation; +} + +@end diff --git a/iOS_Tips/DarkMode/WKWebView/WebNative/SLPictureTransitionAnimation.h b/iOS_Tips/DarkMode/WKWebView/WebNative/SLPictureTransitionAnimation.h new file mode 100644 index 00000000..b9f67fb8 --- /dev/null +++ b/iOS_Tips/DarkMode/WKWebView/WebNative/SLPictureTransitionAnimation.h @@ -0,0 +1,30 @@ +// +// SLPictureTransitionAnimation.h +// TELiveClass +// +// Created by wsl on 2020/2/28. +// Copyright © 2020 offcn_c. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +//定义枚举 转场类型 +typedef enum : NSUInteger { + SLTransitionTypePush, + SLTransitionTypePop, + SLTransitionTypePresent, + SLTransitionTypeDissmiss +} SLTransitionType; + +/// 图片浏览转场动画 +@interface SLPictureTransitionAnimation : NSObject +@property (nonatomic, assign) SLTransitionType transitionType; +@property (nonatomic, strong) UIView *toAnimatonView; //动画前的视图 +@property (nonatomic, strong) UIView *fromAnimatonView; //动画后的视图 +//@property (nonatomic, assign) CGRect animatonRect; +//@property (nonatomic, strong) UIView *animatonView; +@end + +NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/WKWebView/WebNative/SLPictureTransitionAnimation.m b/iOS_Tips/DarkMode/WKWebView/WebNative/SLPictureTransitionAnimation.m new file mode 100644 index 00000000..dc38fe0b --- /dev/null +++ b/iOS_Tips/DarkMode/WKWebView/WebNative/SLPictureTransitionAnimation.m @@ -0,0 +1,95 @@ +// +// SLPictureTransitionAnimation.m +// TELiveClass +// +// Created by wsl on 2020/2/28. +// Copyright © 2020 offcn_c. All rights reserved. +// + +#import "SLPictureTransitionAnimation.h" + +@interface SLPictureTransitionAnimation () +@end + +@implementation SLPictureTransitionAnimation + +#pragma mark - UIViewControllerAnimatedTransitioning +//返回动画时间 +- (NSTimeInterval)transitionDuration:(nullable id )transitionContext { + return 0.3; +} +//所有的过渡动画事务都在这个代理方法里面完成 +- (void)animateTransition:(id )transitionContext { + switch (self.transitionType) { + case SLTransitionTypePush: + [self pushAnimation:transitionContext]; + break; + case SLTransitionTypePop: + [self popAnimation:transitionContext]; + break; + case SLTransitionTypePresent: + [self presentAnimation:transitionContext]; + break; + case SLTransitionTypeDissmiss: + [self dissmissAnimation:transitionContext]; + break; + } +} + +#pragma mark - Push/Pop +- (void)pushAnimation:(id )transitionContext { + [transitionContext completeTransition:YES]; +} +- (void)popAnimation:(id )transitionContext { + [transitionContext completeTransition:YES]; +} + +#pragma mark - Present/Dissmiss +- (void)presentAnimation:(id )transitionContext { + //转场后视图控制器上的视图view + UIView *toView = [transitionContext viewForKey: UITransitionContextToViewKey]; + toView.hidden = true; + //这里有个重要的概念containerView,如果要对视图做转场动画,视图就必须要加入containerView中才能进行,可以理解containerView管理着所有做转场动画的视图 + UIView *containerView = transitionContext.containerView; + //黑色背景视图 + UIView *bgView = [[UIView alloc] initWithFrame: CGRectMake(0,0, containerView.frame.size.width, containerView.frame.size.height)]; + bgView.backgroundColor = [UIColor blackColor]; + [containerView addSubview:toView]; + [containerView addSubview:bgView]; + [containerView addSubview:self.fromAnimatonView]; + //动画 + [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{ + if(!CGRectEqualToRect(self.toAnimatonView.frame, CGRectZero)) { + self.fromAnimatonView.frame = self.toAnimatonView.frame; + self.fromAnimatonView.layer.contentsRect = self.toAnimatonView.layer.contentsRect; + } + } completion:^(BOOL finished) { + toView.hidden = NO; + [bgView removeFromSuperview]; + [self.fromAnimatonView removeFromSuperview]; + [transitionContext completeTransition:YES]; + }]; +} +- (void)dissmissAnimation:(id )transitionContext { + //转场前视图控制器上的视图view + UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey]; + fromView.hidden = YES; + UIView *containerView = transitionContext.containerView; + //黑色背景视图 + UIView *bgView = [[UIView alloc] initWithFrame:CGRectMake( 0,0, containerView.frame.size.width, containerView.frame.size.height)]; + bgView.backgroundColor = fromView.backgroundColor; + [containerView addSubview:bgView]; + [containerView addSubview:self.fromAnimatonView]; + //动画 + [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{ + self.fromAnimatonView.frame = self.toAnimatonView.frame; + self.fromAnimatonView.layer.contentsRect = self.toAnimatonView.layer.contentsRect; + bgView.alpha = 0; + } completion:^(BOOL finished) { + [bgView removeFromSuperview]; + [self.fromAnimatonView removeFromSuperview]; + [transitionContext completeTransition:YES]; + }]; +} + +@end diff --git a/iOS_Tips/DarkMode/WKWebView/SLReusableManager.h b/iOS_Tips/DarkMode/WKWebView/WebNative/SLReusableManager.h similarity index 90% rename from iOS_Tips/DarkMode/WKWebView/SLReusableManager.h rename to iOS_Tips/DarkMode/WKWebView/WebNative/SLReusableManager.h index a9c5714d..d0f4ee5b 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLReusableManager.h +++ b/iOS_Tips/DarkMode/WKWebView/WebNative/SLReusableManager.h @@ -29,7 +29,7 @@ NS_ASSUME_NONNULL_BEGIN @end @interface SLReusableManager : NSObject -///数据源代理 +///事件代理 @property (nonatomic, weak) iddelegate; ///数据源代理 @property (nonatomic, weak) iddataSource; @@ -42,6 +42,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)registerClass:(Class)class forCellReuseIdentifier:(NSString *)cellID; ///根据cellID从复用池reusablePool取可重用的view,如果没有,重新创建一个新对象返回 - (SLReusableCell *)dequeueReusableCellWithIdentifier:(nonnull NSString *)cellID index:(NSInteger)index; +///获取索引为index的cell,如果第index的cell不在可见范围内,返回nil +- (SLReusableCell *)cellForRowAtIndex:(NSInteger)index; @end diff --git a/iOS_Tips/DarkMode/WKWebView/SLReusableManager.m b/iOS_Tips/DarkMode/WKWebView/WebNative/SLReusableManager.m similarity index 95% rename from iOS_Tips/DarkMode/WKWebView/SLReusableManager.m rename to iOS_Tips/DarkMode/WKWebView/WebNative/SLReusableManager.m index 1ed2d971..269c3082 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLReusableManager.m +++ b/iOS_Tips/DarkMode/WKWebView/WebNative/SLReusableManager.m @@ -75,9 +75,9 @@ - (void)setScrollView:(UIScrollView *)scrollView { #pragma mark - KVO - (void)addKVO { [self.scrollView addObserver:self - forKeyPath:@"contentOffset" - options:NSKeyValueObservingOptionNew - context:nil]; + forKeyPath:@"contentOffset" + options:NSKeyValueObservingOptionNew + context:nil]; } - (void)removeKVO{ [self.scrollView removeObserver:self forKeyPath:@"contentOffset"]; @@ -143,6 +143,11 @@ - (void)reloadData { } } } +///注册样式 +- (void)registerClass:(Class)class forCellReuseIdentifier:(NSString *)cellID { + self.reusablePool[cellID] = [NSHashTable weakObjectsHashTable]; + self.registerClasses[cellID] = class; +} ///根据cellID从复用池reusablePool取可重用的view,如果没有,重新创建一个新对象返回 - (SLReusableCell *)dequeueReusableCellWithIdentifier:(nonnull NSString *)cellID index:(NSInteger)index{ NSHashTable *hashTable = self.reusablePool[cellID]; @@ -163,10 +168,14 @@ - (SLReusableCell *)dequeueReusableCellWithIdentifier:(nonnull NSString *)cellID cell.index = index; return cell; } -///注册样式 -- (void)registerClass:(Class)class forCellReuseIdentifier:(NSString *)cellID { - self.reusablePool[cellID] = [NSHashTable weakObjectsHashTable]; - self.registerClasses[cellID] = class; +///获取索引为index的cell,如果第index的cell不在可见范围内,返回nil +- (SLReusableCell *)cellForRowAtIndex:(NSInteger)index { + for (SLReusableCell *cell in self.visibleCells) { + if (cell.index == index) { + return cell; + } + } + return nil; } #pragma mark - Help Methods @@ -221,7 +230,7 @@ - (void)willDisappearCellWithDirection:(BOOL)top { [self.visibleCells removeObjectAtIndex:0]; } }else { - if (self.willDisplayIndexBottom-1 < 0) return; + if (self.willDisplayIndexBottom-1 < 0) return; CGRect rect = [self.frameArray[self.willDisplayIndexBottom-1] CGRectValue]; if (rect.origin.y > self.scrollView.contentOffset.y + self.scrollView.sl_height) { self.willDisplayIndexBottom = self.willDisplayIndexBottom-1; diff --git a/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.h b/iOS_Tips/DarkMode/WKWebView/WebNative/SLWebNativeViewController.h similarity index 100% rename from iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.h rename to iOS_Tips/DarkMode/WKWebView/WebNative/SLWebNativeViewController.h diff --git a/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.m b/iOS_Tips/DarkMode/WKWebView/WebNative/SLWebNativeViewController.m similarity index 90% rename from iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.m rename to iOS_Tips/DarkMode/WKWebView/WebNative/SLWebNativeViewController.m index 8bbe8feb..9bdf9ad7 100644 --- a/iOS_Tips/DarkMode/WKWebView/SLWebNativeViewController.m +++ b/iOS_Tips/DarkMode/WKWebView/WebNative/SLWebNativeViewController.m @@ -13,6 +13,7 @@ #import "SLAvPlayer.h" #import #import "SLReusableManager.h" +#import "SLPictureBrowseController.h" @interface SLWebNativeModel : NSObject @property (nonatomic, copy) NSString *tagID; //标签ID @@ -85,7 +86,7 @@ - (void)updateDataWith:(SLWebNativeModel *)model { 2.html界面调整时,要去重新调用JS方法获取原生标签的位置并更新native组件的位置。 3.如果仅需要处理HTML的图片元素,也可以不用原生组件imageView展示,原生下载处理图片,然后通过oc调用JS设置图片 */ -@interface SLWebNativeViewController () +@interface SLWebNativeViewController () @property (nonatomic, strong) dispatch_semaphore_t semaphore; @property (nonatomic, strong) WKWebView * webView; @@ -250,7 +251,7 @@ - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigat CGRect frame = CGRectMake( [frameDict[@"x"] floatValue], [frameDict[@"y"] floatValue], [frameDict[@"width"] floatValue], [frameDict[@"height"] floatValue]); if(!CGRectEqualToRect(frame, CGRectZero)) { - [weakSelf.frameArray addObject:[NSValue valueWithCGRect:frame]]; + [weakSelf.frameArray addObject:[NSValue valueWithCGRect:frame]]; } dispatch_semaphore_signal(weakSelf.semaphore); if (i == weakSelf.dataSource.count - 1) { @@ -282,6 +283,11 @@ - (void)reusableManager:(SLReusableManager *)reusableManager didSelectRowAtIndex if ([model.type isEqualToString:@"image"]) { //图片 NSLog(@"点击了 %ld 图片", index); + SLPictureBrowseController *pictureBrowseController = [[SLPictureBrowseController alloc] init]; + pictureBrowseController.imagesArray = [NSMutableArray arrayWithArray:@[[NSURL URLWithString:model.imgUrl]]]; + pictureBrowseController.indexPath = [NSIndexPath indexPathForRow:index inSection:0]; + [self presentViewController:pictureBrowseController animated:YES completion:nil]; + }else if ([model.type isEqualToString:@"video"]) { //视频 NSLog(@"点击了 %ld 视频", index); @@ -291,4 +297,15 @@ - (void)reusableManager:(SLReusableManager *)reusableManager didSelectRowAtIndex } } +#pragma mark - SLPictureAnimationViewDelegate +//用于转场的动画视图 +- (UIView *)animationViewOfPictureTransition:(NSIndexPath *)indexPath { + SLWebNativeCell *imageCell = (SLWebNativeCell *)[self.reusableManager cellForRowAtIndex:indexPath.row]; + UIImageView *tempView = [UIImageView new]; + tempView.image = imageCell.imageView.image; + tempView.layer.contentsRect = imageCell.imageView.layer.contentsRect; + tempView.frame = [imageCell.imageView convertRect:imageCell.imageView.bounds toView:self.view]; + return imageCell; +} + @end diff --git a/iOS_Tips/DarkMode/WKWebView/WebNative.html b/iOS_Tips/DarkMode/WKWebView/WebNative/WebNative.html similarity index 100% rename from iOS_Tips/DarkMode/WKWebView/WebNative.html rename to iOS_Tips/DarkMode/WKWebView/WebNative/WebNative.html diff --git a/iOS_Tips/DarkMode/WKWebView/WebNativeJson.txt b/iOS_Tips/DarkMode/WKWebView/WebNative/WebNativeJson.txt similarity index 100% rename from iOS_Tips/DarkMode/WKWebView/WebNativeJson.txt rename to iOS_Tips/DarkMode/WKWebView/WebNative/WebNativeJson.txt diff --git a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m index b85e984d..d2b47986 100644 --- a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m @@ -46,16 +46,18 @@ - (void)getData { @"全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突", @"UITableView/UICollectionView获取特定位置的cell", @"UIScrollView视觉差动画", - @"iOS 传感器集锦"]]; + @"iOS 传感器集锦", @"iOS 自定义转场动画"]]; [self.urlArray addObjectsFromArray:@[@"", @"https://juejin.im/post/5c0e1e73f265da616413d828", @"https://juejin.im/post/5c0e1df95188250d2722a3bc", @"https://juejin.im/post/5c088b45f265da610e7fe156", - @"https://juejin.im/post/5c088a1051882517165dd15d"]]; + @"https://juejin.im/post/5c088a1051882517165dd15d", + @"https://juejin.im/post/5c088ba36fb9a049fb43737b"]]; [self.classArray addObjectsFromArray:@[[SLMenuViewController class], [SLWebViewController class], [SLWebViewController class], [SLWebViewController class], + [SLWebViewController class], [SLWebViewController class]]]; [self.tableView reloadData]; } From 5396e9f780657be14ca6dcd7c85850d1a4d261bf Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 29 Jun 2020 10:19:46 +0800 Subject: [PATCH 030/356] =?UTF-8?q?=E5=9B=BE=E9=9B=86=E6=B5=8F=E8=A7=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WebNative/SLPictureBrowseController.m | 6 ++--- .../WebNative/SLWebNativeViewController.m | 26 +++++++++++++++++-- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/iOS_Tips/DarkMode/WKWebView/WebNative/SLPictureBrowseController.m b/iOS_Tips/DarkMode/WKWebView/WebNative/SLPictureBrowseController.m index e1e3520e..1ca831d7 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebNative/SLPictureBrowseController.m +++ b/iOS_Tips/DarkMode/WKWebView/WebNative/SLPictureBrowseController.m @@ -11,7 +11,7 @@ /// 图片缩放视图 @interface SLPictureZoomView : UIScrollView -@property (nonatomic, strong) UIImageView *imageView; +@property (nonatomic, strong) YYAnimatedImageView *imageView; @property (nonatomic, strong) UIActivityIndicatorView *indicatorView; //下载指示器 @property (nonatomic, assign) CGSize imageNormalSize; //图片原尺寸 @end @@ -40,9 +40,9 @@ - (void)setupUI { } #pragma mark - Getter -- (UIImageView *)imageView { +- (YYAnimatedImageView *)imageView { if (!_imageView) { - _imageView = [[UIImageView alloc] init]; + _imageView = [[YYAnimatedImageView alloc] init]; _imageView.userInteractionEnabled = YES; } return _imageView; diff --git a/iOS_Tips/DarkMode/WKWebView/WebNative/SLWebNativeViewController.m b/iOS_Tips/DarkMode/WKWebView/WebNative/SLWebNativeViewController.m index 9bdf9ad7..30ffa9ec 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebNative/SLWebNativeViewController.m +++ b/iOS_Tips/DarkMode/WKWebView/WebNative/SLWebNativeViewController.m @@ -30,6 +30,7 @@ @implementation SLWebNativeModel @interface SLWebNativeCell : SLReusableCell @property (nonatomic, strong) YYAnimatedImageView *imageView; +@property (nonatomic, assign) CGSize imageViewSize; @property (nonatomic, strong) UIImageView *playIcon; @end @implementation SLWebNativeCell @@ -59,7 +60,27 @@ - (void)setupUI { } - (void)updateDataWith:(SLWebNativeModel *)model { - [_imageView yy_setImageWithURL:[NSURL URLWithString:model.imgUrl] placeholder:nil]; + _imageView.layer.contentsRect = CGRectMake(0, 0, 1, 1); + __weak typeof(self) weakSelf = self; + [self.imageView yy_setImageWithURL:[NSURL URLWithString:model.imgUrl] placeholder:nil options:YYWebImageOptionShowNetworkActivity completion:^(UIImage * _Nullable image, NSURL * _Nonnull url, YYWebImageFromType from, YYWebImageStage stage, NSError * _Nullable error) { + if(error) return ; + if (image.size.width > image.size.height) { + //宽图 + CGFloat width = weakSelf.imageViewSize.height*image.size.width/image.size.height; + if (width > weakSelf.imageViewSize.width) { + CGFloat proportion = weakSelf.imageViewSize.width/width; + weakSelf.imageView.layer.contentsRect = CGRectMake((1 - proportion)/2, 0, proportion, 1); + } + }else if (image.size.width < image.size.height) { + //长图 + CGFloat height = weakSelf.imageViewSize.width*image.size.height/image.size.width; + if (height > weakSelf.imageViewSize.height) { + CGFloat proportion = weakSelf.imageViewSize.height/height; + weakSelf.imageView.layer.contentsRect = CGRectMake(0,(1 - proportion)/2, 1, proportion); + } + } + }]; + if ([model.type isEqualToString:@"image"]) { //图片 _playIcon.hidden = YES; @@ -273,6 +294,7 @@ - (CGRect)reusableManager:(SLReusableManager *)reusableManager frameForRowAtInde - (SLReusableCell *)reusableManager:(SLReusableManager *)reusableManager cellForRowAtIndex:(NSInteger)index { SLWebNativeCell *cell = (SLWebNativeCell *)[reusableManager dequeueReusableCellWithIdentifier:@"cellID" index:index]; SLWebNativeModel *model = self.dataSource[index]; + cell.imageViewSize = [self.frameArray[index] CGRectValue].size; [cell updateDataWith:model]; return cell; } @@ -305,7 +327,7 @@ - (UIView *)animationViewOfPictureTransition:(NSIndexPath *)indexPath { tempView.image = imageCell.imageView.image; tempView.layer.contentsRect = imageCell.imageView.layer.contentsRect; tempView.frame = [imageCell.imageView convertRect:imageCell.imageView.bounds toView:self.view]; - return imageCell; + return tempView; } @end From 60d2c2699483f4c40d8366bff08285ca86e536b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Mon, 29 Jun 2020 17:25:37 +0800 Subject: [PATCH 031/356] Update README.md --- README.md | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index fd3c98c1..aa091cd7 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,11 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git > 5、LeetCode算法练习 > 6、工作中踩过的坑 >> 6.1、键盘和UIMenuController不能同时存在的问题 ->> 6.2、全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突 +>> 6.2、全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突 +>> 6.3、UITableView/UICollectionView获取特定位置的cell +>> 6.4、UIScrollView视觉差动画 +>> 6.5、iOS 传感器集锦 +>> 6.6、iOS 自定义转场动画 > 7、iOS Crash防护 > 8、WKWebView相关 @@ -43,7 +47,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git ## 3、AVFoundation相关 -### 3.1、[微信相机拍摄照片、小视频以及编辑功能](https://www.jianshu.com/p/a2a04cabb98d) +#### 3.1、[微信相机拍摄照片、小视频以及编辑功能](https://www.jianshu.com/p/a2a04cabb98d) > 效果描述: > * 1、自定义相机 拍摄视频和照片 > * 2、切换前后摄像头、调整焦距/设置聚焦点、横屏拍摄 @@ -63,17 +67,17 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git |![图片编辑](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/3、小视频7.gif)|![图片裁剪](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/3、小视频8.gif)| -### 3.2、[人脸检测](https://www.jianshu.com/p/f236dc161a90) +#### 3.2、[人脸检测](https://www.jianshu.com/p/f236dc161a90) ![人脸识别](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/4、人脸识别.gif) -### 3.3、[实时滤镜拍摄和导出](https://www.jianshu.com/p/f236dc161a90) +#### 3.3、[实时滤镜拍摄和导出](https://www.jianshu.com/p/f236dc161a90) > 主要类: 是由SLAvCaptureTool拆分的 SLAvCaptureSession(采集) + SLAvWriterInput(录制) 两个工具类,方便扩展,录制写入实现的方式也略有不同 ![人脸识别](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/5、实时滤镜拍摄.gif) -### 3.4、[GPUImage框架的使用](https://www.jianshu.com/p/97740cd381f7) +#### 3.4、[GPUImage框架的使用](https://www.jianshu.com/p/97740cd381f7) > 效果描述:实时拍摄添加水印和滤镜、本地视频添加水印、GIF图水印 @@ -81,17 +85,17 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git ![GPUImage框架的使用](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/6、GPUImage.gif) -### 3.5、VideoToolBox和AudioToolBox音视频编解码 +#### 3.5、VideoToolBox和AudioToolBox音视频编解码 > 请查看本仓库下的 VideoEncoder&Decoder 文件 ![音视频编码](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/7、音视频编码.gif) -### 3.6、AVFoundation 利用摄像头实时识别物体颜色 +#### 3.6、AVFoundation 利用摄像头实时识别物体颜色 ![音视频编码](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/3.6、拾色器.gif) -### 3.7、[AVFoundation 原生二维码扫描识别和生成](https://juejin.im/post/5c0e1db651882539c60d0434) +#### 3.7、[AVFoundation 原生二维码扫描识别和生成](https://juejin.im/post/5c0e1db651882539c60d0434) > 该代码地址在:https://github.com/wsl2ls/ScanQRcode @@ -111,13 +115,18 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git ## 6、工作中踩过的坑 -### 6.1、[键盘和UIMenuController的并存问题](https://www.jianshu.com/p/ed1b57c4ecea) +#### 6.1、[键盘和UIMenuController的并存问题](https://www.jianshu.com/p/ed1b57c4ecea) | ![问题描述.gif](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/10、键盘和UIMenuController不能同时出现的问题描述.gif) | ![并存问题解决](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/10、键盘和UIMenuController并存问题解决.gif) | -### 6.2、[全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突](https://juejin.im/post/5c0e1e73f265da616413d828) +#### 6.2、[全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突](https://juejin.im/post/5c0e1e73f265da616413d828) > 该代码地址在:https://github.com/wsl2ls/WSLTransferAnimation + + #### 6.3、[UITableView/UICollectionView获取特定位置的cell](https://juejin.im/post/5c0e1df95188250d2722a3bc) +#### 6.4、[UIScrollView视觉差动画](https://juejin.im/post/5c088b45f265da610e7fe156) +#### 6.5、[iOS 传感器集锦](https://juejin.im/post/5c088a1051882517165dd15d) +#### 6.6、[iOS 自定义转场动画](https://juejin.im/post/5c088ba36fb9a049fb43737b) ## 7、iOS Crash防护 From fe4203b98a9f7d3cf99dd8cf076128cf95e0a87f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Mon, 29 Jun 2020 17:28:36 +0800 Subject: [PATCH 032/356] Update README.md --- README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index aa091cd7..06d9cab3 100644 --- a/README.md +++ b/README.md @@ -120,10 +120,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git | ![问题描述.gif](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/10、键盘和UIMenuController不能同时出现的问题描述.gif) | ![并存问题解决](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/10、键盘和UIMenuController并存问题解决.gif) | #### 6.2、[全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突](https://juejin.im/post/5c0e1e73f265da616413d828) - - > 该代码地址在:https://github.com/wsl2ls/WSLTransferAnimation - - #### 6.3、[UITableView/UICollectionView获取特定位置的cell](https://juejin.im/post/5c0e1df95188250d2722a3bc) +#### 6.3、[UITableView/UICollectionView获取特定位置的cell](https://juejin.im/post/5c0e1df95188250d2722a3bc) #### 6.4、[UIScrollView视觉差动画](https://juejin.im/post/5c088b45f265da610e7fe156) #### 6.5、[iOS 传感器集锦](https://juejin.im/post/5c088a1051882517165dd15d) #### 6.6、[iOS 自定义转场动画](https://juejin.im/post/5c088ba36fb9a049fb43737b) From a9181fe9809892500a836a573b092ec9e96745d6 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 6 Jul 2020 17:45:29 +0800 Subject: [PATCH 033/356] =?UTF-8?q?=E4=BA=8C=E8=BF=9B=E5=88=B6=E9=87=8D?= =?UTF-8?q?=E6=8E=92=E4=BC=98=E5=8C=96=E5=90=AF=E5=8A=A8=E9=80=9F=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 8196 -> 8196 bytes iOS_Tips/.DS_Store | Bin 10244 -> 10244 bytes iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 36 ++++++ .../xcshareddata/xcschemes/DarkMode.xcscheme | 7 ++ iOS_Tips/DarkMode/.DS_Store | Bin 12292 -> 12292 bytes .../WorkIssues/SLWorkIssuesViewController.m | 11 +- .../SLBinaryResetViewController.h" | 18 +++ .../SLBinaryResetViewController.m" | 115 ++++++++++++++++++ .../Write Link Map File.png" | Bin 0 -> 33054 bytes .../wsl.order" | 83 +++++++++++++ 10 files changed, 267 insertions(+), 3 deletions(-) create mode 100644 "iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.h" create mode 100644 "iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.m" create mode 100644 "iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/Write Link Map File.png" create mode 100644 "iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/wsl.order" diff --git a/.DS_Store b/.DS_Store index b6c8dc09bf6328012e038c07687211517fb88b78..40b97e6f66b50498a217548584e55732d685664f 100644 GIT binary patch delta 62 zcmZp1XmOa}&nUhzU^hRb_+}n~DXg3+#mPBI`T02vlQ)QpY+fMh#k84SVkV}zI}-qW C0u(L) delta 40 qcmZp1XmOa}&nUJrU^hRb*k&GqDXg3Kih40kY>?f|E-@3vkpch^gAFtQ diff --git a/iOS_Tips/.DS_Store b/iOS_Tips/.DS_Store index 787cc1353718a79c0428c885e26233ed8da573ad..a7846d048fe8daf6d9b4f2b18ecaae62e4b8d77d 100644 GIT binary patch delta 55 zcmZn(XbIS0CBfvuI{AROhCo4vVQ_MOZUF-bFf}kt-XNhfd4U8kGt< delta 55 zcmZn(XbIS0CBbB}d-4Hs4S|9T!{Frn+yVv=U@Bmkyg@=|@&XB7W(I~wK(-|lgTUt3 H5|aD?+yW2- diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 41e054ba..9beb6435 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -10,6 +10,11 @@ 2CEBE85D24A6E65600BA21F3 /* SLTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CEBE85B24A6E65600BA21F3 /* SLTimer.m */; }; 780F5303236D8462000D0EA8 /* SLGridView.m in Sources */ = {isa = PBXBuildFile; fileRef = 780F5302236D8462000D0EA8 /* SLGridView.m */; }; 780F5306236D8570000D0EA8 /* SLImageClipController.m in Sources */ = {isa = PBXBuildFile; fileRef = 780F5305236D8570000D0EA8 /* SLImageClipController.m */; }; + 7811F76F24B2C791000AA044 /* SLBinaryResetViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7811F76E24B2C791000AA044 /* SLBinaryResetViewController.m */; }; + 7811F77124B2C818000AA044 /* wsl.order in Resources */ = {isa = PBXBuildFile; fileRef = 7811F77024B2C818000AA044 /* wsl.order */; }; + 7811F7AD24B32A1E000AA044 /* Write Link Map File.png in Resources */ = {isa = PBXBuildFile; fileRef = 7811F7AA24B32A1E000AA044 /* Write Link Map File.png */; }; + 7811F7AE24B32A1E000AA044 /* Other c Flags.png in Resources */ = {isa = PBXBuildFile; fileRef = 7811F7AB24B32A1E000AA044 /* Other c Flags.png */; }; + 7811F7AF24B32A1E000AA044 /* Order File.png in Resources */ = {isa = PBXBuildFile; fileRef = 7811F7AC24B32A1E000AA044 /* Order File.png */; }; 7822CCF8235B054200E70C29 /* SLPaddingLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 7822CCF7235B054200E70C29 /* SLPaddingLabel.m */; }; 782CFB1D239DDE95001B5528 /* SLSplitScreenViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 782CFB1C239DDE95001B5528 /* SLSplitScreenViewController.m */; }; 782CFB20239DEA05001B5528 /* SLSplitScreenCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 782CFB1F239DEA05001B5528 /* SLSplitScreenCell.m */; }; @@ -188,6 +193,12 @@ 780F5302236D8462000D0EA8 /* SLGridView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLGridView.m; sourceTree = ""; }; 780F5304236D8570000D0EA8 /* SLImageClipController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLImageClipController.h; sourceTree = ""; }; 780F5305236D8570000D0EA8 /* SLImageClipController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLImageClipController.m; sourceTree = ""; }; + 7811F76D24B2C791000AA044 /* SLBinaryResetViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLBinaryResetViewController.h; sourceTree = ""; }; + 7811F76E24B2C791000AA044 /* SLBinaryResetViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLBinaryResetViewController.m; sourceTree = ""; }; + 7811F77024B2C818000AA044 /* wsl.order */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = wsl.order; sourceTree = ""; }; + 7811F7AA24B32A1E000AA044 /* Write Link Map File.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Write Link Map File.png"; sourceTree = ""; }; + 7811F7AB24B32A1E000AA044 /* Other c Flags.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Other c Flags.png"; sourceTree = ""; }; + 7811F7AC24B32A1E000AA044 /* Order File.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Order File.png"; sourceTree = ""; }; 7822CCF6235B054200E70C29 /* SLPaddingLabel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLPaddingLabel.h; sourceTree = ""; }; 7822CCF7235B054200E70C29 /* SLPaddingLabel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLPaddingLabel.m; sourceTree = ""; }; 782CFB1B239DDE95001B5528 /* SLSplitScreenViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLSplitScreenViewController.h; sourceTree = ""; }; @@ -500,6 +511,19 @@ name = Frameworks; sourceTree = ""; }; + 7811F76C24B2C70D000AA044 /* 二进制重排 */ = { + isa = PBXGroup; + children = ( + 7811F7AC24B32A1E000AA044 /* Order File.png */, + 7811F7AB24B32A1E000AA044 /* Other c Flags.png */, + 7811F7AA24B32A1E000AA044 /* Write Link Map File.png */, + 7811F77024B2C818000AA044 /* wsl.order */, + 7811F76D24B2C791000AA044 /* SLBinaryResetViewController.h */, + 7811F76E24B2C791000AA044 /* SLBinaryResetViewController.m */, + ); + path = "二进制重排"; + sourceTree = ""; + }; 782E3EB52373F892001E0DF9 /* Filter */ = { isa = PBXGroup; children = ( @@ -803,6 +827,7 @@ children = ( 7884247D2492102900C2E505 /* SLWorkIssuesViewController.h */, 7884247E2492102900C2E505 /* SLWorkIssuesViewController.m */, + 7811F76C24B2C70D000AA044 /* 二进制重排 */, 78EF8B5C24162B07008D0CD7 /* UIMenuController */, ); path = WorkIssues; @@ -1200,10 +1225,12 @@ 782CFB63239E623D001B5528 /* Cirlce.fsh in Resources */, 782CFB23239DFD0F001B5528 /* SplitScreen_2.fsh in Resources */, 782CFB38239E22AC001B5528 /* SplitScreen_9.vsh in Resources */, + 7811F7AE24B32A1E000AA044 /* Other c Flags.png in Resources */, 782CFB53239E4587001B5528 /* SplitScreen_16.vsh in Resources */, 782CFB6E239E69F3001B5528 /* Scale.vsh in Resources */, 78BDE04D248BFBD7002ED386 /* wsl.png in Resources */, 782CFB37239E22AC001B5528 /* SplitScreen_9.fsh in Resources */, + 7811F7AF24B32A1E000AA044 /* Order File.png in Resources */, 782CFB76239E6A02001B5528 /* SoulOut.vsh in Resources */, 782CFB54239E4587001B5528 /* SplitScreen_16.fsh in Resources */, 78BDE058248E541E002ED386 /* WebNativeJson.txt in Resources */, @@ -1215,11 +1242,13 @@ 78B1048B232F57C30051579F /* Main.storyboard in Resources */, 782CFB27239DFD89001B5528 /* SplitScreen_1.fsh in Resources */, 783FB4612394A76B0039AEFD /* shaderf.fsh in Resources */, + 7811F7AD24B32A1E000AA044 /* Write Link Map File.png in Resources */, 782CFB2F239E04A2001B5528 /* SplitScreen_4.vsh in Resources */, 782CFB67239E6651001B5528 /* HexagonMosaic.vsh in Resources */, 782CFB2B239E0479001B5528 /* SplitScreen_3.vsh in Resources */, 782CFB5B239E6227001B5528 /* Gray.vsh in Resources */, 782CFB5E239E622E001B5528 /* Mosaic.vsh in Resources */, + 7811F77124B2C818000AA044 /* wsl.order in Resources */, 78E72D59247BA29600751373 /* WebTableView.html in Resources */, 782CFB7A239E6A11001B5528 /* Glitch.vsh in Resources */, 782CFB5A239E6227001B5528 /* Gray.fsh in Resources */, @@ -1324,6 +1353,7 @@ 78777CE0238FEA48006FA671 /* SLOpenGLController.m in Sources */, 7851CB362331CC87002295B5 /* SLDarkModeViewController.m in Sources */, 78D30965239688EF00DC373A /* GLESMath.c in Sources */, + 7811F76F24B2C791000AA044 /* SLBinaryResetViewController.m in Sources */, 788ACD652390EA3A00737EC2 /* SLCubeViewController.m in Sources */, 7884248E24963FD200C2E505 /* SLReusableManager.m in Sources */, 7857FD4B24729E8500D3D986 /* BSBacktraceLogger.m in Sources */, @@ -1577,11 +1607,14 @@ GCC_PREFIX_HEADER = "$(SRCROOT)/DarkMode/General/Tool/PrefixHeader.pch"; INFOPLIST_FILE = DarkMode/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_GENERATE_MAP_FILE = YES; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); NEW_SETTING = ""; + ORDER_FILE = "$(SRCROOT)/DarkMode/WorkIssues/二进制重排/wsl.order"; + OTHER_CFLAGS = "-fsanitize-coverage=func,trace-pc-guard"; PRODUCT_BUNDLE_IDENTIFIER = com.wsl2ls.tip; PRODUCT_NAME = SLTips; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1605,11 +1638,14 @@ GCC_PREFIX_HEADER = "$(SRCROOT)/DarkMode/General/Tool/PrefixHeader.pch"; INFOPLIST_FILE = DarkMode/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_GENERATE_MAP_FILE = YES; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); NEW_SETTING = ""; + ORDER_FILE = "$(SRCROOT)/DarkMode/WorkIssues/二进制重排/wsl.order"; + OTHER_CFLAGS = "-fsanitize-coverage=func,trace-pc-guard"; PRODUCT_BUNDLE_IDENTIFIER = com.wsl2ls.tip; PRODUCT_NAME = SLTips; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/iOS_Tips/DarkMode.xcodeproj/xcshareddata/xcschemes/DarkMode.xcscheme b/iOS_Tips/DarkMode.xcodeproj/xcshareddata/xcschemes/DarkMode.xcscheme index f394f659..d70c5f89 100644 --- a/iOS_Tips/DarkMode.xcodeproj/xcshareddata/xcschemes/DarkMode.xcscheme +++ b/iOS_Tips/DarkMode.xcodeproj/xcshareddata/xcschemes/DarkMode.xcscheme @@ -70,6 +70,13 @@ ReferencedContainer = "container:DarkMode.xcodeproj"> + + + + o{JeCauFa0Jruk-*~{Azup+g#i=Vd-^C>&fK~83IiGjg&MkZz!RyKAH4lWKZ zUar{SjQsN8lEjkIVyDESXb_JrAh9GPDRFY4fF~0N$K=zh^7Z1XhPIvwxs_GbHMMm! zz!owvg5m%K_#qUWoC#!Mbq-3LFdNw5QimK1LRm8m-q%B-0jr_8`G_b0E5@U?AOk7% zSrR}l#%g9+a8X`PeqK6I9^^^x$s%H6n>$4AGS-8VqAxHy@)$}PoEh?gbO}QdkOoCn zDnk*94;hrofSLussS}SLWZyoNGPxLKcnFl{u<8pzwhYg zuN-4yRNu^_FrR7iWRZ33#%5+Z3Pwhg6ND8eXNan9UZQNp2uzr6z-*Wd^eHHpl>l)v zLkX&%Ef)aYj#VA9KR@nmmU?3k_9qUth)6}Kt;cRKs(%82_A{^n9hwP@5|9(oA|>QF zx;(POPThq&48;s^SnEMc23(3z9a6CQmdYnac5nh>2-(b{@rR|Jfq|CcLoj%N_5({x WbpNA9AO+z=FnD;8vL6F#_y7Qou4GRD diff --git a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m index d2b47986..742a5d13 100644 --- a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m @@ -9,6 +9,7 @@ #import "SLWorkIssuesViewController.h" #import "SLMenuViewController.h" #import "SLWebViewController.h" +#import "SLBinaryResetViewController.h" @interface SLWorkIssuesViewController () @property (nonatomic, strong) NSMutableArray *titlesArray; @@ -46,19 +47,23 @@ - (void)getData { @"全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突", @"UITableView/UICollectionView获取特定位置的cell", @"UIScrollView视觉差动画", - @"iOS 传感器集锦", @"iOS 自定义转场动画"]]; + @"iOS 传感器集锦", + @"iOS 自定义转场动画", + @"二进制重排优化启动时间"]]; [self.urlArray addObjectsFromArray:@[@"", @"https://juejin.im/post/5c0e1e73f265da616413d828", @"https://juejin.im/post/5c0e1df95188250d2722a3bc", @"https://juejin.im/post/5c088b45f265da610e7fe156", @"https://juejin.im/post/5c088a1051882517165dd15d", - @"https://juejin.im/post/5c088ba36fb9a049fb43737b"]]; + @"https://juejin.im/post/5c088ba36fb9a049fb43737b", + @""]]; [self.classArray addObjectsFromArray:@[[SLMenuViewController class], [SLWebViewController class], [SLWebViewController class], [SLWebViewController class], [SLWebViewController class], - [SLWebViewController class]]]; + [SLWebViewController class], + [SLBinaryResetViewController class]]]; [self.tableView reloadData]; } diff --git "a/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.h" "b/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.h" new file mode 100644 index 00000000..5b2b7fbd --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.h" @@ -0,0 +1,18 @@ +// +// SLBinaryResetViewController.h +// DarkMode +// +// Created by wsl on 2020/7/6. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +///二进制重排优化启动时间 参考:https://juejin.im/post/5e97c3c751882573b86f9d00#heading-17 +@interface SLBinaryResetViewController : SLViewController + +@end + +NS_ASSUME_NONNULL_END diff --git "a/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.m" "b/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.m" new file mode 100644 index 00000000..071c4001 --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.m" @@ -0,0 +1,115 @@ +// +// SLBinaryResetViewController.m +// DarkMode +// +// Created by wsl on 2020/7/6. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLBinaryResetViewController.h" +#import +#import + +@interface SLBinaryResetViewController () +@property (nonatomic, strong) UITextView *textView; +@end + +@implementation SLBinaryResetViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = UIColor.whiteColor; + self.navigationItem.title = @"二进制重排优化启动时间"; + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"生成Order文件" style:UIBarButtonItemStyleDone target:self action:@selector(getOrderFile)]; + self.textView = [[UITextView alloc] initWithFrame:self.view.bounds]; + self.textView.editable = NO; + [self.view addSubview:self.textView]; +} +///获取启动加载时执行的所有函数符号 +- (void)getOrderFile{ + NSMutableArray * symbolNames = [NSMutableArray array]; + while (YES) { + //offsetof 就是针对某个结构体找到某个属性相对这个结构体的偏移量 + //出队,依次取出启动时执行的方法 + SLSymbolNode *node = OSAtomicDequeue(&symbolList, offsetof(SLSymbolNode, next)); + if (node == NULL) { + break; + } + Dl_info info; + dladdr(node->pc, &info); + //根据内存地址获取函数名称 + NSString * name = @(info.dli_sname); + BOOL isObjc = [name hasPrefix:@"+["] || [name hasPrefix:@"-["]; + NSString * symbolName = isObjc ? name: [@"_" stringByAppendingString:name]; + [symbolNames addObject:symbolName]; + NSLog(@"%@",symbolName); + } + //取反 + NSEnumerator * emt = [symbolNames reverseObjectEnumerator]; + //去重 + NSMutableArray *funcs = [NSMutableArray arrayWithCapacity:symbolNames.count]; + NSString * name; + while (name = [emt nextObject]) { + if (![funcs containsObject:name]) { + [funcs addObject:name]; + } + } + //干掉自己! + [funcs removeObject:[NSString stringWithFormat:@"%s",__FUNCTION__]]; + //将数组变成字符串 + NSString * funcStr = [funcs componentsJoinedByString:@"\n"]; + //写入 + NSString * filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"wsl.order"]; + NSData * fileContents = [funcStr dataUsingEncoding:NSUTF8StringEncoding]; + BOOL result = [[NSFileManager defaultManager] createFileAtPath:filePath contents:fileContents attributes:nil]; + if (result) { + NSLog(@"二进制重排后的函数执行序列文件Order:%@",filePath); + }else{ + NSLog(@"文件写入出错"); + } + + self.textView.text = funcStr; +} + +void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, + uint32_t *stop) { + static uint64_t N; // Counter for the guards. + if (start == stop || *start) return; // Initialize only once. + // printf("INIT: %p %p\n", start, stop); + for (uint32_t *x = start; x < stop; x++) + *x = ++N; // Guards should start from 1. +} + +//原子队列 存储启动时加载的所有函数方法 +static OSQueueHead symbolList = OS_ATOMIC_QUEUE_INIT; +//定义符号结构体 +typedef struct { + void *pc; + void *next; +}SLSymbolNode; + +//应用启动时执行,把启动过程中执行的函数地址存储在symbolList中 +void __sanitizer_cov_trace_pc_guard(uint32_t *guard) { + // if (!*guard) return; // Duplicate the guard check. + /* 精确定位 哪里开始 到哪里结束! 在这里面做判断写条件!*/ + + //它的作用其实就是去读取 x30寄存器 中所存储的要返回时下一条指令的地址. 所以他名称叫做 __builtin_return_address . 换句话说 , 这个地址就是我当前这个函数执行完毕后 , 要返回到哪里去的函数地址 . + void *PC = __builtin_return_address(0); + + SLSymbolNode *node = malloc(sizeof(SLSymbolNode)); + *node = (SLSymbolNode){PC,NULL}; + + //根据内存地址获取函数名称 + Dl_info info; + dladdr(node->pc, &info); + NSString * name = @(info.dli_sname); + //这个方法会导致循环引用,故在此过滤 + if ([name isEqualToString:@"-[NSMutableArray(SLCrashProtector) sl_insertObject:atIndex:]"]) { + return; + } + //入队 + // offsetof 用在这里是为了入队添加下一个节点找到 前一个节点next指针的位置 + OSAtomicEnqueue(&symbolList, node, offsetof(SLSymbolNode, next)); +} + +@end diff --git "a/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/Write Link Map File.png" "b/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/Write Link Map File.png" new file mode 100644 index 0000000000000000000000000000000000000000..b5560a024c77134fb96b6a4393a32feb41f3b261 GIT binary patch literal 33054 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 Date: Mon, 6 Jul 2020 17:45:49 +0800 Subject: [PATCH 034/356] =?UTF-8?q?=E4=BA=8C=E8=BF=9B=E5=88=B6=E9=87=8D?= =?UTF-8?q?=E6=8E=92=E4=BC=98=E5=8C=96=E5=90=AF=E5=8A=A8=E9=80=9F=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Order File.png" | Bin 0 -> 86615 bytes .../Other c Flags.png" | Bin 0 -> 137612 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 "iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/Order File.png" create mode 100644 "iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/Other c Flags.png" diff --git "a/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/Order File.png" "b/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/Order File.png" new file mode 100644 index 0000000000000000000000000000000000000000..d183b372afa2ac6c20387b158bdf7a3a873d060e GIT binary patch literal 86615 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%0DqCP~dZnmAN{JJZ6iy!p^BCK7-q?NBdW;gJQ2v;$ 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

A1!!_3O}W>NP=m#7+iE;UKQ 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%0A?`h&BURe{b-Udu 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 literal 0 HcmV?d00001 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/Other c Flags.png" "b/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/Other c Flags.png" new file mode 100644 index 0000000000000000000000000000000000000000..2e1273d05345c8044203697a40f35c69f8097b23 GIT binary patch literal 137612 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℞uTiCC@ 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 literal 0 HcmV?d00001 From c93176ffdefd2249ee9f7cf53d022eafc9318d1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Tue, 7 Jul 2020 10:07:51 +0800 Subject: [PATCH 035/356] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 06d9cab3..c3862975 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,8 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git >> 6.3、UITableView/UICollectionView获取特定位置的cell >> 6.4、UIScrollView视觉差动画 >> 6.5、iOS 传感器集锦 ->> 6.6、iOS 自定义转场动画 +>> 6.6、iOS 自定义转场动画 +>> 6.7、二进制重排优化启动速度 > 7、iOS Crash防护 > 8、WKWebView相关 @@ -124,6 +125,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git #### 6.4、[UIScrollView视觉差动画](https://juejin.im/post/5c088b45f265da610e7fe156) #### 6.5、[iOS 传感器集锦](https://juejin.im/post/5c088a1051882517165dd15d) #### 6.6、[iOS 自定义转场动画](https://juejin.im/post/5c088ba36fb9a049fb43737b) +#### 6.7、二进制重排优化启动速度 ## 7、iOS Crash防护 From 55584bc043de992907d5af6556086a56037104c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Tue, 7 Jul 2020 10:08:51 +0800 Subject: [PATCH 036/356] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c3862975..0cb64262 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git #### 6.4、[UIScrollView视觉差动画](https://juejin.im/post/5c088b45f265da610e7fe156) #### 6.5、[iOS 传感器集锦](https://juejin.im/post/5c088a1051882517165dd15d) #### 6.6、[iOS 自定义转场动画](https://juejin.im/post/5c088ba36fb9a049fb43737b) -#### 6.7、二进制重排优化启动速度 +#### 6.7、[二进制重排优化启动速度](https://juejin.im/post/5ea79839f265da7bba509590) ## 7、iOS Crash防护 From fba2bbc33282cfcfc8a8b11262cb30216a32e55f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Thu, 9 Jul 2020 15:36:03 +0800 Subject: [PATCH 037/356] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 0cb64262..4a555ff3 100644 --- a/README.md +++ b/README.md @@ -142,8 +142,6 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git > * 1、主工程就是iOS_Tips下的DarkMode,别怀疑🤣,历史遗留问题😁😀,大部分内容都在里面,run一下就明白了🤝 > * 2、小视频拍摄录制失败,主要集中在plus和X系列手机上:可能是由于写入的视频宽高videoSize设置的问题,各位可以先试试这样设置 avCaptureTool.videoSize = CGSizeMake(self.view.width * 0.8, self.view.height * 0.8); -> * 3、iPhoneX/XR系列崩溃,错误代码是pods > pods > FBRetainCycleDetector > fishhook.c 第104行 -indirect_symbol_bindings[i] = cur->rebindings[j].replacement: FBRetainCycleDetector 这个是三方库里的,检测内存泄漏的,你可以把 MLeaksFinder 移除,这只是一个辅助调试工具。 From ad7516bd8347e5c7bf9455792161d7e89bd9dd3c Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 10 Jul 2020 15:56:28 +0800 Subject: [PATCH 038/356] =?UTF-8?q?=E4=BA=8C=E8=BF=9B=E5=88=B6=E9=87=8D?= =?UTF-8?q?=E6=8E=92=E4=BC=98=E5=8C=96=E5=90=AF=E5=8A=A8=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SLBinaryResetViewController.m" | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.m" "b/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.m" index 071c4001..0af34ae4 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.m" @@ -25,7 +25,8 @@ - (void)viewDidLoad { self.textView.editable = NO; [self.view addSubview:self.textView]; } -///获取启动加载时执行的所有函数符号 + +///获取启动加载时执行的所有函数符号按顺序写入wsl.order文件中 - (void)getOrderFile{ NSMutableArray * symbolNames = [NSMutableArray array]; while (YES) { @@ -71,14 +72,6 @@ - (void)getOrderFile{ self.textView.text = funcStr; } -void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, - uint32_t *stop) { - static uint64_t N; // Counter for the guards. - if (start == stop || *start) return; // Initialize only once. - // printf("INIT: %p %p\n", start, stop); - for (uint32_t *x = start; x < stop; x++) - *x = ++N; // Guards should start from 1. -} //原子队列 存储启动时加载的所有函数方法 static OSQueueHead symbolList = OS_ATOMIC_QUEUE_INIT; @@ -87,8 +80,18 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, void *pc; void *next; }SLSymbolNode; - -//应用启动时执行,把启动过程中执行的函数地址存储在symbolList中 +void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, + uint32_t *stop) { + static uint64_t N; // Counter for the guards. + if (start == stop || *start) return; // Initialize only once. + // printf("INIT: %p %p\n", start, stop); + for (uint32_t *x = start; x < stop; x++) + *x = ++N; // Guards should start from 1. +} +/* + 静态插桩,相当于此函数在编译时插在了每一个函数体里,这个函数会捕获到所有程序运行过程中执行的方法。 + 我们只需要捕获应用启动时执行的方法就行,把启动过程中执行的函数地址存储在symbolList中。 + */ void __sanitizer_cov_trace_pc_guard(uint32_t *guard) { // if (!*guard) return; // Duplicate the guard check. /* 精确定位 哪里开始 到哪里结束! 在这里面做判断写条件!*/ From 095c0988e69d0a24364a3acb670278b0df7414d1 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 10 Jul 2020 17:26:38 +0800 Subject: [PATCH 039/356] =?UTF-8?q?=E4=BA=8C=E8=BF=9B=E5=88=B6=E9=87=8D?= =?UTF-8?q?=E6=8E=92=E4=BC=98=E5=8C=96=E5=90=AF=E5=8A=A8=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SLBinaryResetViewController.m" | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.m" "b/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.m" index 0af34ae4..5f1b94fa 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.m" @@ -25,8 +25,7 @@ - (void)viewDidLoad { self.textView.editable = NO; [self.view addSubview:self.textView]; } - -///获取启动加载时执行的所有函数符号按顺序写入wsl.order文件中 +///获取启动加载时执行的排序后的所有函数符号,得到顺序执行的函数符号后,这些配置和clang插桩代码就可以删除了(除了Order File配置) - (void)getOrderFile{ NSMutableArray * symbolNames = [NSMutableArray array]; while (YES) { @@ -80,6 +79,13 @@ - (void)getOrderFile{ void *pc; void *next; }SLSymbolNode; + +/* + 所有处理完之后,最后需要Write Link Map File改为NO,把Other C Flags/Other Swift Flags的配置删除掉。 + 因为这个配置会在我们代码中自动插入跳转执行 __sanitizer_cov_trace_pc_guard。重排完就不需要了,需要去除掉。 + 同时把ViewController中的 __sanitizer_cov_trace_pc_guard也要去除掉。 + */ +/// clang插桩代码 void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { static uint64_t N; // Counter for the guards. @@ -88,6 +94,7 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, for (uint32_t *x = start; x < stop; x++) *x = ++N; // Guards should start from 1. } + /* 静态插桩,相当于此函数在编译时插在了每一个函数体里,这个函数会捕获到所有程序运行过程中执行的方法。 我们只需要捕获应用启动时执行的方法就行,把启动过程中执行的函数地址存储在symbolList中。 From 02cbefeedd49859644c1860e241a5cd97a256819 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 13 Jul 2020 14:05:42 +0800 Subject: [PATCH 040/356] =?UTF-8?q?=E4=BA=8C=E8=BF=9B=E5=88=B6=E9=87=8D?= =?UTF-8?q?=E6=8E=92=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SLBinaryResetViewController.m" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.m" "b/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.m" index 5f1b94fa..941e3929 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.m" @@ -42,7 +42,7 @@ - (void)getOrderFile{ BOOL isObjc = [name hasPrefix:@"+["] || [name hasPrefix:@"-["]; NSString * symbolName = isObjc ? name: [@"_" stringByAppendingString:name]; [symbolNames addObject:symbolName]; - NSLog(@"%@",symbolName); +// NSLog(@"%@",symbolName); } //取反 NSEnumerator * emt = [symbolNames reverseObjectEnumerator]; @@ -114,7 +114,7 @@ void __sanitizer_cov_trace_pc_guard(uint32_t *guard) { dladdr(node->pc, &info); NSString * name = @(info.dli_sname); //这个方法会导致循环引用,故在此过滤 - if ([name isEqualToString:@"-[NSMutableArray(SLCrashProtector) sl_insertObject:atIndex:]"]) { + if ([name isEqualToString:@"-[NSMutableArray(SLCrashProtector) sl_insertObject:atIndex:]"] || [name isEqualToString:@"-[NSObject(SLCrashProtector) sl_KVODealloc]"]) { return; } //入队 From 6f76dc4fa3f39d82b6601e3de98284768ca2a1cf Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 13 Jul 2020 15:21:22 +0800 Subject: [PATCH 041/356] =?UTF-8?q?APM=E5=BA=94=E7=94=A8=E6=80=A7=E8=83=BD?= =?UTF-8?q?=E7=9B=91=E6=8E=A7=E7=AE=A1=E7=90=86(doing)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 14 ++++++++ .../WorkIssues/APM/SLAPMViewController.h | 18 +++++++++++ .../WorkIssues/APM/SLAPMViewController.m | 32 +++++++++++++++++++ .../WorkIssues/SLWorkIssuesViewController.m | 4 ++- 4 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.h create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 9beb6435..63c440cb 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -63,6 +63,7 @@ 783FB4612394A76B0039AEFD /* shaderf.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 783FB45F2394A76B0039AEFD /* shaderf.fsh */; }; 784B72062334685E006AEE47 /* SLAvPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 784B72052334685E006AEE47 /* SLAvPlayer.m */; }; 784B720923348241006AEE47 /* SLAvCaptureTool.m in Sources */ = {isa = PBXBuildFile; fileRef = 784B720823348241006AEE47 /* SLAvCaptureTool.m */; }; + 784C4BE124BC40D200D5C199 /* SLAPMViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BE024BC40D200D5C199 /* SLAPMViewController.m */; }; 7851CB362331CC87002295B5 /* SLDarkModeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7851CB332331CC87002295B5 /* SLDarkModeViewController.m */; }; 7851CB372331CC87002295B5 /* SLDarkModeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7851CB352331CC87002295B5 /* SLDarkModeViewController.xib */; }; 7851CB43233222E2002295B5 /* UIView+SLFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 7851CB41233222E2002295B5 /* UIView+SLFrame.m */; }; @@ -263,6 +264,8 @@ 784B72052334685E006AEE47 /* SLAvPlayer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAvPlayer.m; sourceTree = ""; }; 784B720723348241006AEE47 /* SLAvCaptureTool.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAvCaptureTool.h; sourceTree = ""; }; 784B720823348241006AEE47 /* SLAvCaptureTool.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAvCaptureTool.m; sourceTree = ""; }; + 784C4BDF24BC40D200D5C199 /* SLAPMViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMViewController.h; sourceTree = ""; }; + 784C4BE024BC40D200D5C199 /* SLAPMViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMViewController.m; sourceTree = ""; }; 7851CB332331CC87002295B5 /* SLDarkModeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLDarkModeViewController.m; sourceTree = ""; }; 7851CB342331CC87002295B5 /* SLDarkModeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLDarkModeViewController.h; sourceTree = ""; }; 7851CB352331CC87002295B5 /* SLDarkModeViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SLDarkModeViewController.xib; sourceTree = ""; }; @@ -593,6 +596,15 @@ path = ShaderLanguage; sourceTree = ""; }; + 784C4BDE24BC409600D5C199 /* APM */ = { + isa = PBXGroup; + children = ( + 784C4BDF24BC40D200D5C199 /* SLAPMViewController.h */, + 784C4BE024BC40D200D5C199 /* SLAPMViewController.m */, + ); + path = APM; + sourceTree = ""; + }; 7851CB322331CC87002295B5 /* Dark */ = { isa = PBXGroup; children = ( @@ -827,6 +839,7 @@ children = ( 7884247D2492102900C2E505 /* SLWorkIssuesViewController.h */, 7884247E2492102900C2E505 /* SLWorkIssuesViewController.m */, + 784C4BDE24BC409600D5C199 /* APM */, 7811F76C24B2C70D000AA044 /* 二进制重排 */, 78EF8B5C24162B07008D0CD7 /* UIMenuController */, ); @@ -1379,6 +1392,7 @@ 78E72D542477A4E700751373 /* SLWebTableViewController.m in Sources */, 2CEBE85D24A6E65600BA21F3 /* SLTimer.m in Sources */, 783504642452C20B0071283E /* SLMethod.m in Sources */, + 784C4BE124BC40D200D5C199 /* SLAPMViewController.m in Sources */, 787C7E4524656524005DF7ED /* UIView+SLMLeakFinder.m in Sources */, 7862533F24599D420017F8F1 /* NSObject+SLCrashProtector.m in Sources */, 787C7DC2245D74E4005DF7ED /* NSMutableString+SLCrashProtector.m in Sources */, diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.h b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.h new file mode 100644 index 00000000..21c3dec2 --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.h @@ -0,0 +1,18 @@ +// +// SLAPMViewController.h +// DarkMode +// +// Created by wsl on 2020/7/13. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +///iOS APM应用性能监控管理 +@interface SLAPMViewController : SLViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m new file mode 100644 index 00000000..dda36294 --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m @@ -0,0 +1,32 @@ +// +// SLAPMViewController.m +// DarkMode +// +// Created by wsl on 2020/7/13. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLAPMViewController.h" + +@interface SLAPMViewController () + +@end + +@implementation SLAPMViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m index 742a5d13..9cfc21cc 100644 --- a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m @@ -10,6 +10,7 @@ #import "SLMenuViewController.h" #import "SLWebViewController.h" #import "SLBinaryResetViewController.h" +#import "SLAPMViewController.h" @interface SLWorkIssuesViewController () @property (nonatomic, strong) NSMutableArray *titlesArray; @@ -49,7 +50,8 @@ - (void)getData { @"UIScrollView视觉差动画", @"iOS 传感器集锦", @"iOS 自定义转场动画", - @"二进制重排优化启动时间"]]; + @"二进制重排优化启动时间", + @"iOS APM应用性能监控管理(doing)"]]; [self.urlArray addObjectsFromArray:@[@"", @"https://juejin.im/post/5c0e1e73f265da616413d828", @"https://juejin.im/post/5c0e1df95188250d2722a3bc", From d0e846e99f8ea17fc1ba5a2a9f4416ec8e910ea1 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 13 Jul 2020 15:25:39 +0800 Subject: [PATCH 042/356] =?UTF-8?q?iOS=20APM=E5=BA=94=E7=94=A8=E6=80=A7?= =?UTF-8?q?=E8=83=BD=E7=9B=91=E6=8E=A7=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WorkIssues/APM/SLAPMViewController.m | 12 +++--------- .../DarkMode/WorkIssues/SLWorkIssuesViewController.m | 8 +++++--- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m index dda36294..b16c9470 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m @@ -16,17 +16,11 @@ @implementation SLAPMViewController - (void)viewDidLoad { [super viewDidLoad]; - // Do any additional setup after loading the view. + self.view.backgroundColor = [UIColor whiteColor]; + + } -/* -#pragma mark - Navigation -// In a storyboard-based application, you will often want to do a little preparation before navigation -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - // Get the new view controller using [segue destinationViewController]. - // Pass the selected object to the new view controller. -} -*/ @end diff --git a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m index 9cfc21cc..a5effb68 100644 --- a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m @@ -58,14 +58,16 @@ - (void)getData { @"https://juejin.im/post/5c088b45f265da610e7fe156", @"https://juejin.im/post/5c088a1051882517165dd15d", @"https://juejin.im/post/5c088ba36fb9a049fb43737b", - @""]]; + @"二进制重排", + @"APM"]]; [self.classArray addObjectsFromArray:@[[SLMenuViewController class], [SLWebViewController class], [SLWebViewController class], [SLWebViewController class], [SLWebViewController class], [SLWebViewController class], - [SLBinaryResetViewController class]]]; + [SLBinaryResetViewController class], + [SLAPMViewController class]]]; [self.tableView reloadData]; } @@ -105,7 +107,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath NSString *urlString = self.urlArray[indexPath.row]; switch (indexPath.row) { default: - if (urlString.length > 0) { + if (urlString.length > 0 && [urlString hasPrefix:@"http"]) { ((SLWebViewController *)nextVc).urlString = urlString; } [self.navigationController pushViewController:nextVc animated:YES]; From c7bdf5c3ece55f40608dcb1f57d2cc8ed1b6b044 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 13 Jul 2020 17:18:15 +0800 Subject: [PATCH 043/356] =?UTF-8?q?GPU=E4=BD=BF=E7=94=A8=E7=8E=87=E7=9B=91?= =?UTF-8?q?=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 12 ++++ iOS_Tips/DarkMode/WorkIssues/APM/SLAPMGpu.h | 19 ++++++ iOS_Tips/DarkMode/WorkIssues/APM/SLAPMGpu.m | 59 ++++++++++++++++++ .../DarkMode/WorkIssues/APM/SLAPMManager.h | 28 +++++++++ .../DarkMode/WorkIssues/APM/SLAPMManager.m | 60 +++++++++++++++++++ .../WorkIssues/APM/SLAPMViewController.m | 21 ++++++- 6 files changed, 197 insertions(+), 2 deletions(-) create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/SLAPMGpu.h create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/SLAPMGpu.m create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.h create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 63c440cb..7bdfce96 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -64,6 +64,8 @@ 784B72062334685E006AEE47 /* SLAvPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 784B72052334685E006AEE47 /* SLAvPlayer.m */; }; 784B720923348241006AEE47 /* SLAvCaptureTool.m in Sources */ = {isa = PBXBuildFile; fileRef = 784B720823348241006AEE47 /* SLAvCaptureTool.m */; }; 784C4BE124BC40D200D5C199 /* SLAPMViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BE024BC40D200D5C199 /* SLAPMViewController.m */; }; + 784C4BE424BC4C5E00D5C199 /* SLAPMManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BE324BC4C5E00D5C199 /* SLAPMManager.m */; }; + 784C4BE724BC53D500D5C199 /* SLAPMGpu.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BE624BC53D500D5C199 /* SLAPMGpu.m */; }; 7851CB362331CC87002295B5 /* SLDarkModeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7851CB332331CC87002295B5 /* SLDarkModeViewController.m */; }; 7851CB372331CC87002295B5 /* SLDarkModeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7851CB352331CC87002295B5 /* SLDarkModeViewController.xib */; }; 7851CB43233222E2002295B5 /* UIView+SLFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 7851CB41233222E2002295B5 /* UIView+SLFrame.m */; }; @@ -266,6 +268,10 @@ 784B720823348241006AEE47 /* SLAvCaptureTool.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAvCaptureTool.m; sourceTree = ""; }; 784C4BDF24BC40D200D5C199 /* SLAPMViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMViewController.h; sourceTree = ""; }; 784C4BE024BC40D200D5C199 /* SLAPMViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMViewController.m; sourceTree = ""; }; + 784C4BE224BC4C5E00D5C199 /* SLAPMManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMManager.h; sourceTree = ""; }; + 784C4BE324BC4C5E00D5C199 /* SLAPMManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMManager.m; sourceTree = ""; }; + 784C4BE524BC53D500D5C199 /* SLAPMGpu.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMGpu.h; sourceTree = ""; }; + 784C4BE624BC53D500D5C199 /* SLAPMGpu.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMGpu.m; sourceTree = ""; }; 7851CB332331CC87002295B5 /* SLDarkModeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLDarkModeViewController.m; sourceTree = ""; }; 7851CB342331CC87002295B5 /* SLDarkModeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLDarkModeViewController.h; sourceTree = ""; }; 7851CB352331CC87002295B5 /* SLDarkModeViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SLDarkModeViewController.xib; sourceTree = ""; }; @@ -601,6 +607,10 @@ children = ( 784C4BDF24BC40D200D5C199 /* SLAPMViewController.h */, 784C4BE024BC40D200D5C199 /* SLAPMViewController.m */, + 784C4BE224BC4C5E00D5C199 /* SLAPMManager.h */, + 784C4BE324BC4C5E00D5C199 /* SLAPMManager.m */, + 784C4BE524BC53D500D5C199 /* SLAPMGpu.h */, + 784C4BE624BC53D500D5C199 /* SLAPMGpu.m */, ); path = APM; sourceTree = ""; @@ -1375,6 +1385,7 @@ 787C7DC9245D77D9005DF7ED /* SLZombieSafeFree.m in Sources */, 786147FA23630C4D00C5424C /* UIImage+SLCommon.m in Sources */, 78FA0F9D235407E6003E456B /* SLDrawView.m in Sources */, + 784C4BE724BC53D500D5C199 /* SLAPMGpu.m in Sources */, 780F5303236D8462000D0EA8 /* SLGridView.m in Sources */, 7851CB43233222E2002295B5 /* UIView+SLFrame.m in Sources */, 7884246B249070D900C2E505 /* UIColor+SLCommon.m in Sources */, @@ -1423,6 +1434,7 @@ 78E72D73247E861300751373 /* SLWebViewListController.m in Sources */, 782CFB57239E5FE6001B5528 /* SLShaderFilterViewController.m in Sources */, 7822CCF8235B054200E70C29 /* SLPaddingLabel.m in Sources */, + 784C4BE424BC4C5E00D5C199 /* SLAPMManager.m in Sources */, 78842468248FAED100C2E505 /* SLColorPickerViewController.m in Sources */, 787C7DCF2462B03D005DF7ED /* UINavigationController+SLMLeakFinder.m in Sources */, 788ACD622390BFD400737EC2 /* SLLoadImageVC.m in Sources */, diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMGpu.h b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMGpu.h new file mode 100644 index 00000000..98d2120c --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMGpu.h @@ -0,0 +1,19 @@ +// +// SLAPMGpu.h +// DarkMode +// +// Created by wsl on 2020/7/13. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +///GPU占有率监听 +@interface SLAPMGpu : NSObject +///返回GPU使用情况 占有率 ++ (double)getCpuUsage; +@end + +NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMGpu.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMGpu.m new file mode 100644 index 00000000..fa96988c --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMGpu.m @@ -0,0 +1,59 @@ +// +// SLAPMGpu.m +// DarkMode +// +// Created by wsl on 2020/7/13. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLAPMGpu.h" +#import +#import +#import +#import +#import + + +@implementation SLAPMGpu + +#pragma mark - CPU占有率 ++ (double)getCpuUsage { + kern_return_t kr; + thread_array_t threadList; // 保存当前Mach task的线程列表 + mach_msg_type_number_t threadCount; // 保存当前Mach task的线程个数 + thread_info_data_t threadInfo; // 保存单个线程的信息列表 + mach_msg_type_number_t threadInfoCount; // 保存当前线程的信息列表大小 + thread_basic_info_t threadBasicInfo; // 线程的基本信息 + + // 通过“task_threads”API调用获取指定 task 的线程列表 + // mach_task_self_,表示获取当前的 Mach task + kr = task_threads(mach_task_self(), &threadList, &threadCount); + if (kr != KERN_SUCCESS) { + return -1; + } + double cpuUsage = 0; + for (int i = 0; i < threadCount; i++) { + threadInfoCount = THREAD_INFO_MAX; + // 通过“thread_info”API调用来查询指定线程的信息 + // flavor参数传的是THREAD_BASIC_INFO,使用这个类型会返回线程的基本信息, + // 定义在 thread_basic_info_t 结构体,包含了用户和系统的运行时间、运行状态和调度优先级等 + kr = thread_info(threadList[i], THREAD_BASIC_INFO, (thread_info_t)threadInfo, &threadInfoCount); + if (kr != KERN_SUCCESS) { + return -1; + } + + threadBasicInfo = (thread_basic_info_t)threadInfo; + if (!(threadBasicInfo->flags & TH_FLAGS_IDLE)) { + cpuUsage += threadBasicInfo->cpu_usage; + } + } + + // 回收内存,防止内存泄漏 + vm_deallocate(mach_task_self(), (vm_offset_t)threadList, threadCount * sizeof(thread_t)); + + NSLog(@"GPU使用率:%.2f%%",cpuUsage / (double)TH_USAGE_SCALE * 100.0); + return cpuUsage / (double)TH_USAGE_SCALE * 100.0; +} + + +@end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.h b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.h new file mode 100644 index 00000000..f4e5f4e6 --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.h @@ -0,0 +1,28 @@ +// +// SLAPMManager.h +// DarkMode +// +// Created by wsl on 2020/7/13. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// APM 管理者 +@interface SLAPMManager : NSObject +///是否正在监控 +@property (nonatomic, assign) BOOL isMonitoring; + ++ (instancetype)sharedInstance; + +///开始监控 +- (void)startMonitoring; +///结束监控 +- (void)stopMonitoring; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m new file mode 100644 index 00000000..e449edb7 --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m @@ -0,0 +1,60 @@ +// +// SLAPMManager.m +// DarkMode +// +// Created by wsl on 2020/7/13. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLAPMManager.h" +#import "SLTimer.h" + +#import "SLAPMGpu.h" + +@interface SLAPMManager () +@property (nonatomic, copy) NSString *taskName; +@end + +@implementation SLAPMManager + +#pragma mark - Override +/// 重写allocWithZone方法,保证alloc或者init创建的实例不会产生新实例,因为该类覆盖了allocWithZone方法,所以只能通过其父类分配内存,即[super allocWithZone] ++ (instancetype)allocWithZone:(struct _NSZone *)zone { + return [self sharedInstance]; +} +- (nonnull id)copyWithZone:(nullable NSZone *)zone { + return [SLAPMManager sharedInstance]; +} + +#pragma mark - Public ++ (instancetype)sharedInstance { + static SLAPMManager *manager = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + manager = [[super allocWithZone:NULL] init]; + }); + return manager; +} +///开始监控 +- (void)startMonitoring { + if (_isMonitoring) return; + _isMonitoring = YES; + _taskName = [SLTimer execTask:self selector:@selector(monitoring) start:0 interval:1.0/60.0 repeats:YES async:YES]; + +} +///结束监控 +- (void)stopMonitoring { + if (!_isMonitoring) return; + _isMonitoring = NO; + [SLTimer cancelTask:_taskName]; +} + +#pragma mark - Monitoring +///监控中 +- (void)monitoring { + + [SLAPMGpu getCpuUsage]; + +} + +@end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m index b16c9470..141645eb 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m @@ -7,6 +7,7 @@ // #import "SLAPMViewController.h" +#import "SLAPMManager.h" @interface SLAPMViewController () @@ -14,13 +15,29 @@ @interface SLAPMViewController () @implementation SLAPMViewController +#pragma mark - Override - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; - - + self.navigationItem.title = @"APM监控"; + [self setupNavigationBar]; } +#pragma mark - UI +- (void)setupNavigationBar { + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:([SLAPMManager sharedInstance].isMonitoring ? @"停止":@"开始") style:UIBarButtonItemStyleDone target:self action:@selector(changeMonitorState)]; +} + +#pragma mark - Events Handle +///改变监听状态 +- (void)changeMonitorState{ + if ([SLAPMManager sharedInstance].isMonitoring) { + [[SLAPMManager sharedInstance] stopMonitoring]; + }else { + [[SLAPMManager sharedInstance] startMonitoring]; + } + [self setupNavigationBar]; +} @end From a18f6bf1fd40c174df3463c55336ec7a62613989 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 13 Jul 2020 18:32:43 +0800 Subject: [PATCH 044/356] =?UTF-8?q?CPU=E5=8D=A0=E6=9C=89=E7=8E=87=E7=9B=91?= =?UTF-8?q?=E5=90=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 12 +++---- iOS_Tips/DarkMode/WorkIssues/APM/SLAPMCpu.h | 23 ++++++++++++ .../WorkIssues/APM/{SLAPMGpu.m => SLAPMCpu.m} | 35 ++++++++++++++++--- iOS_Tips/DarkMode/WorkIssues/APM/SLAPMGpu.h | 19 ---------- .../DarkMode/WorkIssues/APM/SLAPMManager.m | 7 ++-- 5 files changed, 64 insertions(+), 32 deletions(-) create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/SLAPMCpu.h rename iOS_Tips/DarkMode/WorkIssues/APM/{SLAPMGpu.m => SLAPMCpu.m} (57%) delete mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/SLAPMGpu.h diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 7bdfce96..22c195b4 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -65,7 +65,7 @@ 784B720923348241006AEE47 /* SLAvCaptureTool.m in Sources */ = {isa = PBXBuildFile; fileRef = 784B720823348241006AEE47 /* SLAvCaptureTool.m */; }; 784C4BE124BC40D200D5C199 /* SLAPMViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BE024BC40D200D5C199 /* SLAPMViewController.m */; }; 784C4BE424BC4C5E00D5C199 /* SLAPMManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BE324BC4C5E00D5C199 /* SLAPMManager.m */; }; - 784C4BE724BC53D500D5C199 /* SLAPMGpu.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BE624BC53D500D5C199 /* SLAPMGpu.m */; }; + 784C4BE724BC53D500D5C199 /* SLAPMCpu.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BE624BC53D500D5C199 /* SLAPMCpu.m */; }; 7851CB362331CC87002295B5 /* SLDarkModeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7851CB332331CC87002295B5 /* SLDarkModeViewController.m */; }; 7851CB372331CC87002295B5 /* SLDarkModeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7851CB352331CC87002295B5 /* SLDarkModeViewController.xib */; }; 7851CB43233222E2002295B5 /* UIView+SLFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 7851CB41233222E2002295B5 /* UIView+SLFrame.m */; }; @@ -270,8 +270,8 @@ 784C4BE024BC40D200D5C199 /* SLAPMViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMViewController.m; sourceTree = ""; }; 784C4BE224BC4C5E00D5C199 /* SLAPMManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMManager.h; sourceTree = ""; }; 784C4BE324BC4C5E00D5C199 /* SLAPMManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMManager.m; sourceTree = ""; }; - 784C4BE524BC53D500D5C199 /* SLAPMGpu.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMGpu.h; sourceTree = ""; }; - 784C4BE624BC53D500D5C199 /* SLAPMGpu.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMGpu.m; sourceTree = ""; }; + 784C4BE524BC53D500D5C199 /* SLAPMCpu.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMCpu.h; sourceTree = ""; }; + 784C4BE624BC53D500D5C199 /* SLAPMCpu.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMCpu.m; sourceTree = ""; }; 7851CB332331CC87002295B5 /* SLDarkModeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLDarkModeViewController.m; sourceTree = ""; }; 7851CB342331CC87002295B5 /* SLDarkModeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLDarkModeViewController.h; sourceTree = ""; }; 7851CB352331CC87002295B5 /* SLDarkModeViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SLDarkModeViewController.xib; sourceTree = ""; }; @@ -609,8 +609,8 @@ 784C4BE024BC40D200D5C199 /* SLAPMViewController.m */, 784C4BE224BC4C5E00D5C199 /* SLAPMManager.h */, 784C4BE324BC4C5E00D5C199 /* SLAPMManager.m */, - 784C4BE524BC53D500D5C199 /* SLAPMGpu.h */, - 784C4BE624BC53D500D5C199 /* SLAPMGpu.m */, + 784C4BE524BC53D500D5C199 /* SLAPMCpu.h */, + 784C4BE624BC53D500D5C199 /* SLAPMCpu.m */, ); path = APM; sourceTree = ""; @@ -1385,7 +1385,7 @@ 787C7DC9245D77D9005DF7ED /* SLZombieSafeFree.m in Sources */, 786147FA23630C4D00C5424C /* UIImage+SLCommon.m in Sources */, 78FA0F9D235407E6003E456B /* SLDrawView.m in Sources */, - 784C4BE724BC53D500D5C199 /* SLAPMGpu.m in Sources */, + 784C4BE724BC53D500D5C199 /* SLAPMCpu.m in Sources */, 780F5303236D8462000D0EA8 /* SLGridView.m in Sources */, 7851CB43233222E2002295B5 /* UIView+SLFrame.m in Sources */, 7884246B249070D900C2E505 /* UIColor+SLCommon.m in Sources */, diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMCpu.h b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMCpu.h new file mode 100644 index 00000000..8271561d --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMCpu.h @@ -0,0 +1,23 @@ +// +// SLAPMCpu.h +// DarkMode +// +// Created by wsl on 2020/7/13. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +///CPU占有率监听 +@interface SLAPMCpu : NSObject +///返回GPU使用情况 占有率 ++ (double)getCpuUsage; +/// 返回CPU使用情况 占有率 +/// @param max 设定CPU使用率最大边界值 +/// @param callback 超出边界后的回调方法 返回此时的堆栈信息 ++ (double)getCpuUsageWithMax:(float)max outOfBoundsCallback:(void(^)(NSString *string))callback; +@end + +NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMGpu.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMCpu.m similarity index 57% rename from iOS_Tips/DarkMode/WorkIssues/APM/SLAPMGpu.m rename to iOS_Tips/DarkMode/WorkIssues/APM/SLAPMCpu.m index fa96988c..636eb26d 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMGpu.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMCpu.m @@ -1,21 +1,32 @@ // -// SLAPMGpu.m +// SLAPMCpu.m // DarkMode // // Created by wsl on 2020/7/13. // Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. // -#import "SLAPMGpu.h" +#import "SLAPMCpu.h" #import #import #import #import #import +#import "BSBacktraceLogger.h" -@implementation SLAPMGpu +@implementation SLAPMCpu +//struct thread_basic_info { +// time_value_t user_time; /* user run time(用户运行时长) */ +// time_value_t system_time; /* system run time(系统运行时长) */ +// integer_t cpu_usage; /* scaled cpu usage percentage(CPU使用率,上限1000) */ +// policy_t policy; /* scheduling policy in effect(有效调度策略) */ +// integer_t run_state; /* run state (运行状态,见下) */ +// integer_t flags; /* various flags (各种各样的标记) */ +// integer_t suspend_count; /* suspend count for thread(线程挂起次数) */ +// integer_t sleep_time; /* number of seconds that thread has been sleeping(休眠时间) */ +//}; #pragma mark - CPU占有率 + (double)getCpuUsage { kern_return_t kr; @@ -51,8 +62,22 @@ + (double)getCpuUsage { // 回收内存,防止内存泄漏 vm_deallocate(mach_task_self(), (vm_offset_t)threadList, threadCount * sizeof(thread_t)); - NSLog(@"GPU使用率:%.2f%%",cpuUsage / (double)TH_USAGE_SCALE * 100.0); - return cpuUsage / (double)TH_USAGE_SCALE * 100.0; + float cpu = cpuUsage / (double)TH_USAGE_SCALE * 100.0; + NSLog(@" CPU使用率:%.2f%%",cpu); + return cpu; +} + +/// 返回GPU使用情况 占有率 +/// @param max 设定GPU使用率最大边界值 +/// @param callback 超出边界后的回调方法 返回此时的堆栈信息 ++ (double)getCpuUsageWithMax:(float)max outOfBoundsCallback:(void(^)(NSString *string))callback { + float cpu= [SLAPMCpu getCpuUsage]; + + if (cpu/100.0 >= max) { + NSString *callbackString = [BSBacktraceLogger bs_backtraceOfAllThread]; + callback(callbackString); + } + return cpu; } diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMGpu.h b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMGpu.h deleted file mode 100644 index 98d2120c..00000000 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMGpu.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// SLAPMGpu.h -// DarkMode -// -// Created by wsl on 2020/7/13. -// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -///GPU占有率监听 -@interface SLAPMGpu : NSObject -///返回GPU使用情况 占有率 -+ (double)getCpuUsage; -@end - -NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m index e449edb7..7f182f09 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m @@ -9,9 +9,10 @@ #import "SLAPMManager.h" #import "SLTimer.h" -#import "SLAPMGpu.h" +#import "SLAPMCpu.h" @interface SLAPMManager () +///任务名称 @property (nonatomic, copy) NSString *taskName; @end @@ -53,7 +54,9 @@ - (void)stopMonitoring { ///监控中 - (void)monitoring { - [SLAPMGpu getCpuUsage]; + [SLAPMCpu getCpuUsageWithMax:0.8 outOfBoundsCallback:^(NSString * _Nonnull string) { +// NSLog(@" %@",string); + }]; } From aca331a9427d645eb6f2c657db85695dab95ab14 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 13 Jul 2020 19:21:41 +0800 Subject: [PATCH 045/356] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m index 7f182f09..0c0a3381 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m @@ -54,9 +54,7 @@ - (void)stopMonitoring { ///监控中 - (void)monitoring { - [SLAPMCpu getCpuUsageWithMax:0.8 outOfBoundsCallback:^(NSString * _Nonnull string) { -// NSLog(@" %@",string); - }]; + [SLAPMCpu getCpuUsage]; } From 70529bdb927e7402edc954f402432c8457c43117 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Tue, 14 Jul 2020 09:25:23 +0800 Subject: [PATCH 046/356] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4a555ff3..06836831 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # iOS_Tips -> iOS的一些示例,不定时更新~ 由于内容后期会较多,文件可能会有点大,建议终端用git clone命令下载,这样以后只需git pull更新。 +> iOS的一些示例,不定时更新~ GitHub:https://github.com/wsl2ls/iOS_Tips.git 掘金:https://juejin.im/user/5c00d97b6fb9a049fb436288 From 5459abd68a17107a6553a51c184ca36084f4dece Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 14 Jul 2020 11:53:50 +0800 Subject: [PATCH 047/356] =?UTF-8?q?APM=20=E4=B9=8B=E7=9B=91=E6=8E=A7?= =?UTF-8?q?=E5=86=85=E5=AD=98=E5=92=8C=E7=A3=81=E7=9B=98=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WKWebView/WebCache/SLWebCacheManager.h | 2 +- .../WKWebView/WebCache/SLWebCacheManager.m | 2 +- iOS_Tips/DarkMode/WorkIssues/APM/SLAPMCpu.m | 8 +- .../DarkMode/WorkIssues/APM/SLAPMManager.m | 85 ++++++++++++++++++- 4 files changed, 86 insertions(+), 11 deletions(-) diff --git a/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheManager.h b/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheManager.h index d60eafa2..e5db1297 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheManager.h +++ b/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheManager.h @@ -23,7 +23,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign) NSUInteger cacheTime; /// 磁盘路径 默认 NSCachesDirectory @property (nonatomic, copy) NSString *diskPath; -/// 缓存文件夹 默认 @"Url" +/// 缓存文件夹 默认 @"com.wsl2ls.webCache" @property (nonatomic, copy) NSString *cacheFolder; /// 子路径 默认 @"UrlCacheDownload" @property (nonatomic, copy) NSString *subDirectory; diff --git a/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheManager.m b/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheManager.m index 0082d6b4..8d8c3a5c 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheManager.m +++ b/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheManager.m @@ -300,7 +300,7 @@ - (NSString *)diskPath { } - (NSString *)cacheFolder { if (!_cacheFolder) { - _cacheFolder = @"Url"; + _cacheFolder = @"com.wsl2ls.webCache"; } return _cacheFolder; } diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMCpu.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMCpu.m index 636eb26d..237cec7e 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMCpu.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMCpu.m @@ -7,11 +7,8 @@ // #import "SLAPMCpu.h" -#import -#import -#import -#import -#import + +#include #import "BSBacktraceLogger.h" @@ -63,7 +60,6 @@ + (double)getCpuUsage { vm_deallocate(mach_task_self(), (vm_offset_t)threadList, threadCount * sizeof(thread_t)); float cpu = cpuUsage / (double)TH_USAGE_SCALE * 100.0; - NSLog(@" CPU使用率:%.2f%%",cpu); return cpu; } diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m index 0c0a3381..eafe6e51 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m @@ -11,6 +11,9 @@ #import "SLAPMCpu.h" +#include + + @interface SLAPMManager () ///任务名称 @property (nonatomic, copy) NSString *taskName; @@ -40,7 +43,7 @@ + (instancetype)sharedInstance { - (void)startMonitoring { if (_isMonitoring) return; _isMonitoring = YES; - _taskName = [SLTimer execTask:self selector:@selector(monitoring) start:0 interval:1.0/60.0 repeats:YES async:YES]; + _taskName = [SLTimer execTask:self selector:@selector(monitoring) start:0 interval:1.0 repeats:YES async:YES]; } ///结束监控 @@ -53,9 +56,85 @@ - (void)stopMonitoring { #pragma mark - Monitoring ///监控中 - (void)monitoring { + @autoreleasepool { + + float CPU = [SLAPMCpu getCpuUsage]; + NSLog(@" CPU使用率:%.2f%%",CPU); + + double useMemory = [SLAPMManager getUsageMemory]; + double freeMemory = [SLAPMManager getFreeMemory]; + double totalMemory = [SLAPMManager getTotalMemory]; + NSLog(@" Memory占用:%.1fM 空闲:%.1fM 总共:%.1fM",useMemory, freeMemory, totalMemory); + +// double useDisk= [SLAPMManager getUsageDisk:@""]; +// double freeDisk = [SLAPMManager getFreeDisk]; +// double totalDisk = [SLAPMManager getTotalDisk]; +// NSLog(@" Disk占用:%.1fM 空闲:%.1fG 总共:%.1fG",useDisk, freeDisk, totalDisk); + + + + + + } +} + + +#pragma mark - Memory/Disk +///当前应用的内存占用情况,和Xcode数值相近 单位MB ++ (double)getUsageMemory { + task_vm_info_data_t vmInfo; + mach_msg_type_number_t count = TASK_VM_INFO_COUNT; + if(task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &count) == KERN_SUCCESS) { + return (double)vmInfo.phys_footprint / (1024 * 1024); + } else { + return -1.0; + } +} +///剩余空闲内存 单位MB ++ (double)getFreeMemory{ + mach_port_t host_port = mach_host_self(); + mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t); + vm_size_t page_size; + vm_statistics_data_t vm_stat; + kern_return_t kern; - [SLAPMCpu getCpuUsage]; - + kern = host_page_size(host_port, &page_size); + if (kern != KERN_SUCCESS) return -1; + kern = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size); + if (kern != KERN_SUCCESS) return -1; + return vm_stat.free_count * page_size / (1024 * 1024); +} +/// 总共的内存大小 单位MB ++ (double)getTotalMemory { + int64_t mem = [[NSProcessInfo processInfo] physicalMemory]; + if (mem < -1) mem = -1; + return mem / (1024 * 1024); +} + +///filePath目录下的文件 占用的磁盘大小 单位MB 默认沙盒Caches目录 ++ (double)getUsageDisk:(NSString *)filePath { + if (filePath.length == 0) filePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject; + NSArray *filesArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:filePath error:nil]; + NSEnumerator *filesEnumerator = [filesArray objectEnumerator]; + NSString *fileName; + unsigned long long int fileSize = 0; + while (fileName = [filesEnumerator nextObject]) { + NSDictionary *fileDic = [[NSFileManager defaultManager] attributesOfItemAtPath:[filePath stringByAppendingPathComponent:fileName] error:nil]; + fileSize += [fileDic fileSize]; + } + return fileSize / (1024 * 1024); +} +///剩余空闲的磁盘容量 单位G ++ (double)getFreeDisk { + NSDictionary *fattributes = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil]; + NSNumber *freeSize = [fattributes objectForKey:NSFileSystemFreeSize]; + return [freeSize integerValue] / (1024*1024*1024); +} +///总磁盘容量 单位G ++ (double)getTotalDisk { + NSDictionary *fattributes = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil]; + NSNumber *totalSize = [fattributes objectForKey:NSFileSystemSize]; + return [totalSize integerValue] / (1024*1024*1024); } @end From f34d31116acf5944d74d8146329359ab0d960e0b Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 14 Jul 2020 15:01:10 +0800 Subject: [PATCH 048/356] =?UTF-8?q?=E5=86=85=E5=AD=98=E5=92=8C=E7=A3=81?= =?UTF-8?q?=E7=9B=98=E7=9B=91=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WorkIssues/APM/SLAPMManager.m | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m index eafe6e51..4fbded89 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m @@ -13,10 +13,10 @@ #include - @interface SLAPMManager () ///任务名称 @property (nonatomic, copy) NSString *taskName; + @end @implementation SLAPMManager @@ -66,20 +66,11 @@ - (void)monitoring { double totalMemory = [SLAPMManager getTotalMemory]; NSLog(@" Memory占用:%.1fM 空闲:%.1fM 总共:%.1fM",useMemory, freeMemory, totalMemory); -// double useDisk= [SLAPMManager getUsageDisk:@""]; -// double freeDisk = [SLAPMManager getFreeDisk]; -// double totalDisk = [SLAPMManager getTotalDisk]; -// NSLog(@" Disk占用:%.1fM 空闲:%.1fG 总共:%.1fG",useDisk, freeDisk, totalDisk); - - - - - } } -#pragma mark - Memory/Disk +#pragma mark - Memory / Disk ///当前应用的内存占用情况,和Xcode数值相近 单位MB + (double)getUsageMemory { task_vm_info_data_t vmInfo; @@ -114,15 +105,22 @@ + (double)getTotalMemory { ///filePath目录下的文件 占用的磁盘大小 单位MB 默认沙盒Caches目录 + (double)getUsageDisk:(NSString *)filePath { if (filePath.length == 0) filePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject; - NSArray *filesArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:filePath error:nil]; + ///定时执行时,此句代码会导致内存不断增长?0.1M + NSArray *filesArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:filePath error:nil] ; NSEnumerator *filesEnumerator = [filesArray objectEnumerator]; + filesArray = nil; + NSString *fileName; unsigned long long int fileSize = 0; while (fileName = [filesEnumerator nextObject]) { - NSDictionary *fileDic = [[NSFileManager defaultManager] attributesOfItemAtPath:[filePath stringByAppendingPathComponent:fileName] error:nil]; - fileSize += [fileDic fileSize]; + @autoreleasepool { + //单个文件大小 + NSDictionary *fileDic = [[NSFileManager defaultManager] attributesOfItemAtPath:[filePath stringByAppendingPathComponent:fileName] error:nil]; + fileSize += [fileDic fileSize]; + } } - return fileSize / (1024 * 1024); + filesEnumerator = nil; + return fileSize / (1024*1024); } ///剩余空闲的磁盘容量 单位G + (double)getFreeDisk { From f17aa23ae4b766a73863bf66a3ce39b1cb0cfcc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Tue, 14 Jul 2020 16:42:30 +0800 Subject: [PATCH 049/356] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 06836831..c3d09873 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,8 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git >> 6.4、UIScrollView视觉差动画 >> 6.5、iOS 传感器集锦 >> 6.6、iOS 自定义转场动画 ->> 6.7、二进制重排优化启动速度 +>> 6.7、二进制重排优化启动速度 +>> 6.8、iOS APM应用性能监控管理(doing) > 7、iOS Crash防护 > 8、WKWebView相关 @@ -126,6 +127,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git #### 6.5、[iOS 传感器集锦](https://juejin.im/post/5c088a1051882517165dd15d) #### 6.6、[iOS 自定义转场动画](https://juejin.im/post/5c088ba36fb9a049fb43737b) #### 6.7、[二进制重排优化启动速度](https://juejin.im/post/5ea79839f265da7bba509590) +#### 6.8、[iOS APM应用性能监控管理(doing)]() ## 7、iOS Crash防护 From 992101a0c6a44046320a10ecccacea77570df945 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 14 Jul 2020 17:23:06 +0800 Subject: [PATCH 050/356] =?UTF-8?q?iOS=20APM=E7=9B=91=E6=8E=A7=E4=B9=8B?= =?UTF-8?q?=E5=8D=A1=E9=A1=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 12 +++ iOS_Tips/DarkMode/General/Tool/SLProxy.h | 19 ++++ iOS_Tips/DarkMode/General/Tool/SLProxy.m | 68 +++++++++++++ iOS_Tips/DarkMode/WorkIssues/APM/SLAPMCpu.m | 1 - iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFps.h | 32 ++++++ iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFps.m | 97 +++++++++++++++++++ .../DarkMode/WorkIssues/APM/SLAPMManager.h | 2 +- .../DarkMode/WorkIssues/APM/SLAPMManager.m | 43 ++++---- .../WorkIssues/APM/SLAPMViewController.m | 14 ++- 9 files changed, 264 insertions(+), 24 deletions(-) create mode 100644 iOS_Tips/DarkMode/General/Tool/SLProxy.h create mode 100644 iOS_Tips/DarkMode/General/Tool/SLProxy.m create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFps.h create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFps.m diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 22c195b4..bb9055fe 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -66,6 +66,8 @@ 784C4BE124BC40D200D5C199 /* SLAPMViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BE024BC40D200D5C199 /* SLAPMViewController.m */; }; 784C4BE424BC4C5E00D5C199 /* SLAPMManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BE324BC4C5E00D5C199 /* SLAPMManager.m */; }; 784C4BE724BC53D500D5C199 /* SLAPMCpu.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BE624BC53D500D5C199 /* SLAPMCpu.m */; }; + 784C4BEA24BDA2DE00D5C199 /* SLProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BE924BDA2DE00D5C199 /* SLProxy.m */; }; + 784C4BED24BDA5D700D5C199 /* SLAPMFps.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BEC24BDA5D700D5C199 /* SLAPMFps.m */; }; 7851CB362331CC87002295B5 /* SLDarkModeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7851CB332331CC87002295B5 /* SLDarkModeViewController.m */; }; 7851CB372331CC87002295B5 /* SLDarkModeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7851CB352331CC87002295B5 /* SLDarkModeViewController.xib */; }; 7851CB43233222E2002295B5 /* UIView+SLFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 7851CB41233222E2002295B5 /* UIView+SLFrame.m */; }; @@ -272,6 +274,10 @@ 784C4BE324BC4C5E00D5C199 /* SLAPMManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMManager.m; sourceTree = ""; }; 784C4BE524BC53D500D5C199 /* SLAPMCpu.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMCpu.h; sourceTree = ""; }; 784C4BE624BC53D500D5C199 /* SLAPMCpu.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMCpu.m; sourceTree = ""; }; + 784C4BE824BDA2DE00D5C199 /* SLProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLProxy.h; sourceTree = ""; }; + 784C4BE924BDA2DE00D5C199 /* SLProxy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLProxy.m; sourceTree = ""; }; + 784C4BEB24BDA5D700D5C199 /* SLAPMFps.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMFps.h; sourceTree = ""; }; + 784C4BEC24BDA5D700D5C199 /* SLAPMFps.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMFps.m; sourceTree = ""; }; 7851CB332331CC87002295B5 /* SLDarkModeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLDarkModeViewController.m; sourceTree = ""; }; 7851CB342331CC87002295B5 /* SLDarkModeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLDarkModeViewController.h; sourceTree = ""; }; 7851CB352331CC87002295B5 /* SLDarkModeViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SLDarkModeViewController.xib; sourceTree = ""; }; @@ -611,6 +617,8 @@ 784C4BE324BC4C5E00D5C199 /* SLAPMManager.m */, 784C4BE524BC53D500D5C199 /* SLAPMCpu.h */, 784C4BE624BC53D500D5C199 /* SLAPMCpu.m */, + 784C4BEB24BDA5D700D5C199 /* SLAPMFps.h */, + 784C4BEC24BDA5D700D5C199 /* SLAPMFps.m */, ); path = APM; sourceTree = ""; @@ -785,6 +793,8 @@ 788424C624978E9200C2E505 /* SLKeyChain.m */, 2CEBE85C24A6E65600BA21F3 /* SLTimer.h */, 2CEBE85B24A6E65600BA21F3 /* SLTimer.m */, + 784C4BE824BDA2DE00D5C199 /* SLProxy.h */, + 784C4BE924BDA2DE00D5C199 /* SLProxy.m */, ); path = Tool; sourceTree = ""; @@ -1379,6 +1389,7 @@ 7811F76F24B2C791000AA044 /* SLBinaryResetViewController.m in Sources */, 788ACD652390EA3A00737EC2 /* SLCubeViewController.m in Sources */, 7884248E24963FD200C2E505 /* SLReusableManager.m in Sources */, + 784C4BEA24BDA2DE00D5C199 /* SLProxy.m in Sources */, 7857FD4B24729E8500D3D986 /* BSBacktraceLogger.m in Sources */, 78E72D8224811F6600751373 /* SLWebCacheViewController.m in Sources */, 78E72D8F2483DC2600751373 /* SLWebCacheManager.m in Sources */, @@ -1417,6 +1428,7 @@ 780F5306236D8570000D0EA8 /* SLImageClipController.m in Sources */, 782CFB6A239E68D5001B5528 /* SLSpecialEffectsViewController.m in Sources */, 7884248B2493851B00C2E505 /* SLViewController.m in Sources */, + 784C4BED24BDA5D700D5C199 /* SLAPMFps.m in Sources */, 78E72D5124766E4B00751373 /* SLWebViewController.m in Sources */, 78B10493232F57C50051579F /* main.m in Sources */, 788424C724978E9200C2E505 /* SLKeyChain.m in Sources */, diff --git a/iOS_Tips/DarkMode/General/Tool/SLProxy.h b/iOS_Tips/DarkMode/General/Tool/SLProxy.h new file mode 100644 index 00000000..860ace99 --- /dev/null +++ b/iOS_Tips/DarkMode/General/Tool/SLProxy.h @@ -0,0 +1,19 @@ +// +// SLProxy.h +// DarkMode +// +// Created by wsl on 2020/7/14. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +///消息转发中介 主要解决NSTimer、CADisplayLink等循环引用问题 +@interface SLProxy : NSProxy +///初始化方法 ++ (instancetype)proxyWithTarget:(id)target; +@end + +NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/General/Tool/SLProxy.m b/iOS_Tips/DarkMode/General/Tool/SLProxy.m new file mode 100644 index 00000000..51e76a17 --- /dev/null +++ b/iOS_Tips/DarkMode/General/Tool/SLProxy.m @@ -0,0 +1,68 @@ +// +// SLProxy.m +// DarkMode +// +// Created by wsl on 2020/7/14. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLProxy.h" + +@interface SLProxy () +///转发对象目标 +@property (nullable, nonatomic, weak, readonly) id target; +@end +@implementation SLProxy ++ (instancetype)proxyWithTarget:(id)target { + return [[SLProxy alloc] initWithTarget:target]; +} +- (instancetype)initWithTarget:(id)target { + _target = target; + return self; +} +//将消息接收对象改为 _target +- (id)forwardingTargetForSelector:(SEL)selector { + return _target; +} +//self 对 target 是弱引用,一旦 target 被释放将调用下面两个方法,如果不实现的话会 crash +- (void)forwardInvocation:(NSInvocation *)invocation { + void *null = NULL; + [invocation setReturnValue:&null]; +} +- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector { + return [NSObject instanceMethodSignatureForSelector:@selector(init)]; +} +- (BOOL)respondsToSelector:(SEL)aSelector { + return [_target respondsToSelector:aSelector]; +} +- (BOOL)isEqual:(id)object { + return [_target isEqual:object]; +} +- (NSUInteger)hash { + return [_target hash]; +} +- (Class)superclass { + return [_target superclass]; +} +- (Class)class { + return [_target class]; +} +- (BOOL)isKindOfClass:(Class)aClass { + return [_target isKindOfClass:aClass]; +} +- (BOOL)isMemberOfClass:(Class)aClass { + return [_target isMemberOfClass:aClass]; +} +- (BOOL)conformsToProtocol:(Protocol *)aProtocol { + return [_target conformsToProtocol:aProtocol]; +} +- (BOOL)isProxy { + return YES; +} +- (NSString *)description { + return [_target description]; +} +- (NSString *)debugDescription { + return [_target debugDescription]; +} +@end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMCpu.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMCpu.m index 237cec7e..37f7e51e 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMCpu.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMCpu.m @@ -68,7 +68,6 @@ + (double)getCpuUsage { /// @param callback 超出边界后的回调方法 返回此时的堆栈信息 + (double)getCpuUsageWithMax:(float)max outOfBoundsCallback:(void(^)(NSString *string))callback { float cpu= [SLAPMCpu getCpuUsage]; - if (cpu/100.0 >= max) { NSString *callbackString = [BSBacktraceLogger bs_backtraceOfAllThread]; callback(callbackString); diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFps.h b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFps.h new file mode 100644 index 00000000..8b4bae07 --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFps.h @@ -0,0 +1,32 @@ +// +// SLAPMFps.h +// DarkMode +// +// Created by wsl on 2020/7/14. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN +@class SLAPMFps; +@protocol SLAPMFpsDelegate +///FPS值改变回调 +- (void)APMFps:(SLAPMFps *)APMFps didChangedFps:(float)fps; +@end + +@interface SLAPMFps : NSObject + +@property (nonatomic, weak) id delegate; + ++ (instancetype)sharedInstance; +///开始 +- (void)play; +///暂停 +- (void)paused; +///销毁 +- (void)invalidate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFps.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFps.m new file mode 100644 index 00000000..05fa9933 --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFps.m @@ -0,0 +1,97 @@ +// +// SLAPMFps.m +// DarkMode +// +// Created by wsl on 2020/7/14. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLAPMFps.h" +#import "SLProxy.h" + +@interface SLAPMFps () +{ + NSTimeInterval _lastTime; + int _count; +} +@property (nonatomic, strong) CADisplayLink *displayLink; +@end +@implementation SLAPMFps + +#pragma mark - Override +/// 重写allocWithZone方法,保证alloc或者init创建的实例不会产生新实例,因为该类覆盖了allocWithZone方法,所以只能通过其父类分配内存,即[super allocWithZone] ++ (instancetype)allocWithZone:(struct _NSZone *)zone { + return [self sharedInstance]; +} +/// 重写copyWithZone方法,保证复制返回的是同一份实例 +- (nonnull id)copyWithZone:(nullable NSZone *)zone { + return [SLAPMFps sharedInstance]; +} + +#pragma mark - Public ++ (instancetype)sharedInstance { + static SLAPMFps *fps = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + fps = [[super allocWithZone:NULL] init]; + }); + return fps; +} +///开始 +- (void)play { + [self.displayLink setPaused:NO]; +} +///暂停 +- (void)paused { + [self.displayLink setPaused:YES]; +} +///销毁 +- (void)invalidate { + [self paused]; + [self.displayLink invalidate]; + self.displayLink = nil; +} + +#pragma mark - Getter +- (CADisplayLink *)displayLink { + if (!_displayLink) { + _displayLink = [CADisplayLink displayLinkWithTarget:[SLProxy proxyWithTarget:self] selector:@selector(displayLinkTick:)]; + [_displayLink setPaused:YES]; + [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; + } + return _displayLink; +} + +//这个方法的执行频率跟当前屏幕的刷新频率是一样的,屏幕每渲染刷新一次,就执行一次,那么1秒的时长执行刷新的次数就是当前的FPS值 +- (void)displayLinkTick:(CADisplayLink *)link{ + // duration 是只读的, 表示屏幕刷新的间隔 = 1/fps + // timestamp 是只读的, 表示上次屏幕渲染的时间点 + // frameInterval 是表示定时器被触发的间隔, 默认值是1, 就是表示跟屏幕的刷新频率一致。 + // NSLog(@"timestamp= %f duration= %f frameInterval= %f",link.timestamp, link.duration, frameInterval); + + //初始化屏幕渲染的时间 + if (_lastTime == 0) { + _lastTime = link.timestamp; + return; + } + //刷新次数累加 + _count++; + //刚刚屏幕渲染的时间与最开始幕渲染的时间差 + NSTimeInterval interval = link.timestamp - _lastTime; + if (interval < 1) { + //不足1秒,继续统计刷新次数 + return; + } + //刷新频率 + float fps = _count / interval; + + //1秒之后,初始化时间和次数,重新开始监测 + _lastTime = link.timestamp; + _count = 0; + + if([self.delegate respondsToSelector:@selector(APMFps:didChangedFps:)]) { + [self.delegate APMFps:self didChangedFps:fps]; + } +} + +@end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.h b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.h index f4e5f4e6..8fca8311 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.h +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.h @@ -15,7 +15,7 @@ NS_ASSUME_NONNULL_BEGIN ///是否正在监控 @property (nonatomic, assign) BOOL isMonitoring; -+ (instancetype)sharedInstance; ++ (instancetype)manager; ///开始监控 - (void)startMonitoring; diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m index 4fbded89..cda36957 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m @@ -10,10 +10,11 @@ #import "SLTimer.h" #import "SLAPMCpu.h" +#import "SLAPMFps.h" #include -@interface SLAPMManager () +@interface SLAPMManager () ///任务名称 @property (nonatomic, copy) NSString *taskName; @@ -24,14 +25,15 @@ @implementation SLAPMManager #pragma mark - Override /// 重写allocWithZone方法,保证alloc或者init创建的实例不会产生新实例,因为该类覆盖了allocWithZone方法,所以只能通过其父类分配内存,即[super allocWithZone] + (instancetype)allocWithZone:(struct _NSZone *)zone { - return [self sharedInstance]; + return [self manager]; } +/// 重写copyWithZone方法,保证复制返回的是同一份实例 - (nonnull id)copyWithZone:(nullable NSZone *)zone { - return [SLAPMManager sharedInstance]; + return [SLAPMManager manager]; } #pragma mark - Public -+ (instancetype)sharedInstance { ++ (instancetype)manager { static SLAPMManager *manager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ @@ -43,7 +45,10 @@ + (instancetype)sharedInstance { - (void)startMonitoring { if (_isMonitoring) return; _isMonitoring = YES; - _taskName = [SLTimer execTask:self selector:@selector(monitoring) start:0 interval:1.0 repeats:YES async:YES]; + _taskName = [SLTimer execTask:self selector:@selector(monitoring) start:0 interval:1.0/60 repeats:YES async:YES]; + + [SLAPMFps sharedInstance].delegate = self; + [[SLAPMFps sharedInstance] play]; } ///结束监控 @@ -51,25 +56,23 @@ - (void)stopMonitoring { if (!_isMonitoring) return; _isMonitoring = NO; [SLTimer cancelTask:_taskName]; + [[SLAPMFps sharedInstance] paused]; } #pragma mark - Monitoring ///监控中 - (void)monitoring { - @autoreleasepool { - - float CPU = [SLAPMCpu getCpuUsage]; - NSLog(@" CPU使用率:%.2f%%",CPU); - - double useMemory = [SLAPMManager getUsageMemory]; - double freeMemory = [SLAPMManager getFreeMemory]; - double totalMemory = [SLAPMManager getTotalMemory]; - NSLog(@" Memory占用:%.1fM 空闲:%.1fM 总共:%.1fM",useMemory, freeMemory, totalMemory); - - } + + float CPU = [SLAPMCpu getCpuUsage]; + NSLog(@" CPU使用率:%.2f%%",CPU); + + double useMemory = [SLAPMManager getUsageMemory]; + double freeMemory = [SLAPMManager getFreeMemory]; + double totalMemory = [SLAPMManager getTotalMemory]; + NSLog(@" Memory占用:%.1fM 空闲:%.1fM 总共:%.1fM",useMemory, freeMemory, totalMemory); + } - #pragma mark - Memory / Disk ///当前应用的内存占用情况,和Xcode数值相近 单位MB + (double)getUsageMemory { @@ -135,4 +138,10 @@ + (double)getTotalDisk { return [totalSize integerValue] / (1024*1024*1024); } +#pragma mark - FPS +///FPS值改变回调 +- (void)APMFps:(SLAPMFps *)APMFps didChangedFps:(float)fps { + NSLog(@" FPS:%.2f",fps); +} + @end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m index 141645eb..60cf7ee8 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m @@ -9,6 +9,11 @@ #import "SLAPMViewController.h" #import "SLAPMManager.h" + +/* + 参考资料:https://www.jianshu.com/p/95df83780c8f + */ + @interface SLAPMViewController () @end @@ -23,19 +28,18 @@ - (void)viewDidLoad { [self setupNavigationBar]; } - #pragma mark - UI - (void)setupNavigationBar { - self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:([SLAPMManager sharedInstance].isMonitoring ? @"停止":@"开始") style:UIBarButtonItemStyleDone target:self action:@selector(changeMonitorState)]; + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:([SLAPMManager manager].isMonitoring ? @"停止":@"开始") style:UIBarButtonItemStyleDone target:self action:@selector(changeMonitorState)]; } #pragma mark - Events Handle ///改变监听状态 - (void)changeMonitorState{ - if ([SLAPMManager sharedInstance].isMonitoring) { - [[SLAPMManager sharedInstance] stopMonitoring]; + if ([SLAPMManager manager].isMonitoring) { + [[SLAPMManager manager] stopMonitoring]; }else { - [[SLAPMManager sharedInstance] startMonitoring]; + [[SLAPMManager manager] startMonitoring]; } [self setupNavigationBar]; } From c11d261d7f725e79d6c5ad294ab8449ccdd9a015 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 14 Jul 2020 23:13:12 +0800 Subject: [PATCH 051/356] =?UTF-8?q?APM=20=E4=B9=8B=20runloop=E7=9B=91?= =?UTF-8?q?=E6=B5=8B=E5=8D=A1=E9=A1=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFps.m | 169 +++++++++++++++++++- 1 file changed, 167 insertions(+), 2 deletions(-) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFps.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFps.m index 05fa9933..02205d3a 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFps.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFps.m @@ -9,10 +9,175 @@ #import "SLAPMFps.h" #import "SLProxy.h" + +@interface SLAPMRunLoop : NSObject +{ + int timeoutCount; // 耗时次数 + CFRunLoopObserverRef observer; // 观察者 + dispatch_semaphore_t semaphore; // 信号 + CFRunLoopActivity activity; // 状态 +} +@end +@implementation SLAPMRunLoop + +// 单例 ++ (instancetype)shareInstance { + static id instance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[self alloc] init]; + }); + return instance; +} + +// 开始监听 +- (void)startMonitor { + if (observer) { + return; + } + + // 创建信号 + semaphore = dispatch_semaphore_create(0); + NSLog(@"dispatch_semaphore_create:%@",[SLAPMRunLoop getCurTime]); + + // 注册RunLoop状态观察 + CFRunLoopObserverContext context = {0,(__bridge void*)self,NULL,NULL}; + //创建Run loop observer对象 + //第一个参数用于分配observer对象的内存 + //第二个参数用以设置observer所要关注的事件,详见回调函数myRunLoopObserver中注释 + //第三个参数用于标识该observer是在第一次进入run loop时执行还是每次进入run loop处理时均执行 + //第四个参数用于设置该observer的优先级 + //第五个参数用于设置该observer的回调函数 + //第六个参数用于设置该observer的运行环境 + observer = CFRunLoopObserverCreate(kCFAllocatorDefault, + kCFRunLoopAllActivities, + YES, + 0, + &runLoopObserverCallBack, + &context); + CFRunLoopAddObserver(CFRunLoopGetMain(), observer, kCFRunLoopCommonModes); + + // 在子线程监控时长 + dispatch_async(dispatch_get_global_queue(0, 0), ^{ + while (YES) { // 有信号的话 就查询当前runloop的状态 + // 假定连续5次超时50ms认为卡顿(当然也包含了单次超时250ms) + // 因为下面 runloop 状态改变回调方法runLoopObserverCallBack中会将信号量递增 1,所以每次 runloop 状态改变后,下面的语句都会执行一次 + // dispatch_semaphore_wait:Returns zero on success, or non-zero if the timeout occurred. + long st = dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 50*NSEC_PER_MSEC)); + NSLog(@"dispatch_semaphore_wait:st=%ld,time:%@",st,[self getCurTime]); + if (st != 0) { // 信号量超时了 - 即 runloop 的状态长时间没有发生变更,长期处于某一个状态下 + if (!observer) { + timeoutCount = 0; + semaphore = 0; + activity = 0; + return; + } + NSLog(@"st = %ld,activity = %lu,timeoutCount = %d,time:%@",st,activity,timeoutCount,[self getCurTime]); + // kCFRunLoopBeforeSources - 即将处理source kCFRunLoopAfterWaiting - 刚从休眠中唤醒 + // 获取kCFRunLoopBeforeSources到kCFRunLoopBeforeWaiting再到kCFRunLoopAfterWaiting的状态就可以知道是否有卡顿的情况。 + // kCFRunLoopBeforeSources:停留在这个状态,表示在做很多事情 + if (activity == kCFRunLoopBeforeSources || activity == kCFRunLoopAfterWaiting) { // 发生卡顿,记录卡顿次数 + if (++timeoutCount < 5) { + continue; // 不足 5 次,直接 continue 当次循环,不将timeoutCount置为0 + } + + // 收集Crash信息也可用于实时获取各线程的调用堆栈 +// PLCrashReporterConfig *config = [[PLCrashReporterConfig alloc] initWithSignalHandlerType:PLCrashReporterSignalHandlerTypeBSD symbolicationStrategy:PLCrashReporterSymbolicationStrategyAll]; +// +// PLCrashReporter *crashReporter = [[PLCrashReporter alloc] initWithConfiguration:config]; +// +// NSData *data = [crashReporter generateLiveReport]; +// PLCrashReport *reporter = [[PLCrashReport alloc] initWithData:data error:NULL]; +// NSString *report = [PLCrashReportTextFormatter stringValueForCrashReport:reporter withTextFormat:PLCrashReportTextFormatiOS]; +// +// NSLog(@"---------卡顿信息\n%@\n--------------",report); + } + } + NSLog(@"dispatch_semaphore_wait timeoutCount = 0,time:%@",[self getCurTime]); + timeoutCount = 0; + } + }); +} + +// 停止监听 +- (void)stopMonitor { + if (!observer) { + return; + } + + // 移除观察并释放资源 + CFRunLoopRemoveObserver(CFRunLoopGetMain(), observer, kCFRunLoopCommonModes); + CFRelease(observer); + observer = NULL; +} + +#pragma mark - runloop observer callback + +// 就是runloop有一个状态改变 就记录一下 +static void runLoopObserverCallBack(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info) { + SLAPMRunLoop *monitor = (__bridge SLAPMRunLoop*)info; + + // 记录状态值 + monitor->activity = activity; + + // 发送信号 + dispatch_semaphore_t semaphore = monitor->semaphore; + long st = dispatch_semaphore_signal(semaphore); + NSLog(@"dispatch_semaphore_signal:st=%ld,time:%@",st,[SLAPMRunLoop getCurTime]); + + /* Run Loop Observer Activities */ +// typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) { +// kCFRunLoopEntry = (1UL << 0), // 进入RunLoop循环(这里其实还没进入) +// kCFRunLoopBeforeTimers = (1UL << 1), // RunLoop 要处理timer了 +// kCFRunLoopBeforeSources = (1UL << 2), // RunLoop 要处理source了 +// kCFRunLoopBeforeWaiting = (1UL << 5), // RunLoop要休眠了 +// kCFRunLoopAfterWaiting = (1UL << 6), // RunLoop醒了 +// kCFRunLoopExit = (1UL << 7), // RunLoop退出(和kCFRunLoopEntry对应) +// kCFRunLoopAllActivities = 0x0FFFFFFFU +// }; + + if (activity == kCFRunLoopEntry) { // 即将进入RunLoop + NSLog(@"runLoopObserverCallBack - %@",@"kCFRunLoopEntry"); + } else if (activity == kCFRunLoopBeforeTimers) { // 即将处理Timer + NSLog(@"runLoopObserverCallBack - %@",@"kCFRunLoopBeforeTimers"); + } else if (activity == kCFRunLoopBeforeSources) { // 即将处理Source + NSLog(@"runLoopObserverCallBack - %@",@"kCFRunLoopBeforeSources"); + } else if (activity == kCFRunLoopBeforeWaiting) { //即将进入休眠 + NSLog(@"runLoopObserverCallBack - %@",@"kCFRunLoopBeforeWaiting"); + } else if (activity == kCFRunLoopAfterWaiting) { // 刚从休眠中唤醒 + NSLog(@"runLoopObserverCallBack - %@",@"kCFRunLoopAfterWaiting"); + } else if (activity == kCFRunLoopExit) { // 即将退出RunLoop + NSLog(@"runLoopObserverCallBack - %@",@"kCFRunLoopExit"); + } else if (activity == kCFRunLoopAllActivities) { + NSLog(@"runLoopObserverCallBack - %@",@"kCFRunLoopAllActivities"); + } +} + +#pragma mark - private function + +- (NSString *)getCurTime { + NSDateFormatter *format = [[NSDateFormatter alloc] init]; + [format setDateFormat:@"YYYY/MM/dd hh:mm:ss:SSS"]; + NSString *curTime = [format stringFromDate:[NSDate date]]; + + return curTime; +} + ++ (NSString *) getCurTime { + NSDateFormatter *format = [[NSDateFormatter alloc] init]; + [format setDateFormat:@"YYYY/MM/dd hh:mm:ss:SSS"]; + NSString *curTime = [format stringFromDate:[NSDate date]]; + + return curTime; +} + +@end + + @interface SLAPMFps () { - NSTimeInterval _lastTime; - int _count; + NSTimeInterval _lastTime; //上次屏幕刷新时间 + int _count; //FPS } @property (nonatomic, strong) CADisplayLink *displayLink; @end From 02271048e439fb5048d459ef76ad5760fb098244 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 15 Jul 2020 13:29:33 +0800 Subject: [PATCH 052/356] =?UTF-8?q?iOS=20APM=20=E5=8D=A1=E9=A1=BF=E7=9B=91?= =?UTF-8?q?=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 12 +- .../APM/{SLAPMFps.h => SLAPMFluency.h} | 5 +- .../APM/{SLAPMFps.m => SLAPMFluency.m} | 225 ++++++++++-------- .../DarkMode/WorkIssues/APM/SLAPMManager.m | 8 +- 4 files changed, 134 insertions(+), 116 deletions(-) rename iOS_Tips/DarkMode/WorkIssues/APM/{SLAPMFps.h => SLAPMFluency.h} (86%) rename iOS_Tips/DarkMode/WorkIssues/APM/{SLAPMFps.m => SLAPMFluency.m} (59%) diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index bb9055fe..d770055b 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -67,7 +67,7 @@ 784C4BE424BC4C5E00D5C199 /* SLAPMManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BE324BC4C5E00D5C199 /* SLAPMManager.m */; }; 784C4BE724BC53D500D5C199 /* SLAPMCpu.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BE624BC53D500D5C199 /* SLAPMCpu.m */; }; 784C4BEA24BDA2DE00D5C199 /* SLProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BE924BDA2DE00D5C199 /* SLProxy.m */; }; - 784C4BED24BDA5D700D5C199 /* SLAPMFps.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BEC24BDA5D700D5C199 /* SLAPMFps.m */; }; + 784C4BED24BDA5D700D5C199 /* SLAPMFluency.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BEC24BDA5D700D5C199 /* SLAPMFluency.m */; }; 7851CB362331CC87002295B5 /* SLDarkModeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7851CB332331CC87002295B5 /* SLDarkModeViewController.m */; }; 7851CB372331CC87002295B5 /* SLDarkModeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7851CB352331CC87002295B5 /* SLDarkModeViewController.xib */; }; 7851CB43233222E2002295B5 /* UIView+SLFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 7851CB41233222E2002295B5 /* UIView+SLFrame.m */; }; @@ -276,8 +276,8 @@ 784C4BE624BC53D500D5C199 /* SLAPMCpu.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMCpu.m; sourceTree = ""; }; 784C4BE824BDA2DE00D5C199 /* SLProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLProxy.h; sourceTree = ""; }; 784C4BE924BDA2DE00D5C199 /* SLProxy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLProxy.m; sourceTree = ""; }; - 784C4BEB24BDA5D700D5C199 /* SLAPMFps.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMFps.h; sourceTree = ""; }; - 784C4BEC24BDA5D700D5C199 /* SLAPMFps.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMFps.m; sourceTree = ""; }; + 784C4BEB24BDA5D700D5C199 /* SLAPMFluency.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMFluency.h; sourceTree = ""; }; + 784C4BEC24BDA5D700D5C199 /* SLAPMFluency.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMFluency.m; sourceTree = ""; }; 7851CB332331CC87002295B5 /* SLDarkModeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLDarkModeViewController.m; sourceTree = ""; }; 7851CB342331CC87002295B5 /* SLDarkModeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLDarkModeViewController.h; sourceTree = ""; }; 7851CB352331CC87002295B5 /* SLDarkModeViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SLDarkModeViewController.xib; sourceTree = ""; }; @@ -617,8 +617,8 @@ 784C4BE324BC4C5E00D5C199 /* SLAPMManager.m */, 784C4BE524BC53D500D5C199 /* SLAPMCpu.h */, 784C4BE624BC53D500D5C199 /* SLAPMCpu.m */, - 784C4BEB24BDA5D700D5C199 /* SLAPMFps.h */, - 784C4BEC24BDA5D700D5C199 /* SLAPMFps.m */, + 784C4BEB24BDA5D700D5C199 /* SLAPMFluency.h */, + 784C4BEC24BDA5D700D5C199 /* SLAPMFluency.m */, ); path = APM; sourceTree = ""; @@ -1428,7 +1428,7 @@ 780F5306236D8570000D0EA8 /* SLImageClipController.m in Sources */, 782CFB6A239E68D5001B5528 /* SLSpecialEffectsViewController.m in Sources */, 7884248B2493851B00C2E505 /* SLViewController.m in Sources */, - 784C4BED24BDA5D700D5C199 /* SLAPMFps.m in Sources */, + 784C4BED24BDA5D700D5C199 /* SLAPMFluency.m in Sources */, 78E72D5124766E4B00751373 /* SLWebViewController.m in Sources */, 78B10493232F57C50051579F /* main.m in Sources */, 788424C724978E9200C2E505 /* SLKeyChain.m in Sources */, diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFps.h b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.h similarity index 86% rename from iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFps.h rename to iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.h index 8b4bae07..1a521abb 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFps.h +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.h @@ -1,5 +1,5 @@ // -// SLAPMFps.h +// SLAPMFluency.h // DarkMode // // Created by wsl on 2020/7/14. @@ -15,7 +15,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)APMFps:(SLAPMFps *)APMFps didChangedFps:(float)fps; @end -@interface SLAPMFps : NSObject +///流畅度监听 是否卡顿 +@interface SLAPMFluency : NSObject @property (nonatomic, weak) id delegate; diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFps.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.m similarity index 59% rename from iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFps.m rename to iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.m index 02205d3a..62259c53 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFps.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.m @@ -1,44 +1,36 @@ // -// SLAPMFps.m +// SLAPMFluency.m // DarkMode // // Created by wsl on 2020/7/14. // Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. // -#import "SLAPMFps.h" +#import "SLAPMFluency.h" #import "SLProxy.h" - +/// 利用runloop 检测主线程每次执行消息循环的时间,当这一时间大于阈值时,就记为发生一次卡顿。 @interface SLAPMRunLoop : NSObject { - int timeoutCount; // 耗时次数 - CFRunLoopObserverRef observer; // 观察者 - dispatch_semaphore_t semaphore; // 信号 - CFRunLoopActivity activity; // 状态 + int _timeoutCount; // 耗时次数 + CFRunLoopObserverRef _observer; // 观察者 + dispatch_semaphore_t _semaphore; // 信号 + CFRunLoopActivity _activity; // 状态 } @end -@implementation SLAPMRunLoop -// 单例 -+ (instancetype)shareInstance { - static id instance = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - instance = [[self alloc] init]; - }); - return instance; -} +@implementation SLAPMRunLoop +#pragma mark - Public // 开始监听 -- (void)startMonitor { - if (observer) { +- (void)startRunning { + if (_observer) { return; } // 创建信号 - semaphore = dispatch_semaphore_create(0); - NSLog(@"dispatch_semaphore_create:%@",[SLAPMRunLoop getCurTime]); + _semaphore = dispatch_semaphore_create(0); + NSLog(@"dispatch_semaphore_create:%@",getCurTime()); // 注册RunLoop状态观察 CFRunLoopObserverContext context = {0,(__bridge void*)self,NULL,NULL}; @@ -49,13 +41,13 @@ - (void)startMonitor { //第四个参数用于设置该observer的优先级 //第五个参数用于设置该observer的回调函数 //第六个参数用于设置该observer的运行环境 - observer = CFRunLoopObserverCreate(kCFAllocatorDefault, - kCFRunLoopAllActivities, - YES, - 0, - &runLoopObserverCallBack, - &context); - CFRunLoopAddObserver(CFRunLoopGetMain(), observer, kCFRunLoopCommonModes); + _observer = CFRunLoopObserverCreate(kCFAllocatorDefault, + kCFRunLoopAllActivities, + YES, + 0, + &runLoopObserverCallBack, + &context); + CFRunLoopAddObserver(CFRunLoopGetMain(), _observer, kCFRunLoopCommonModes); // 在子线程监控时长 dispatch_async(dispatch_get_global_queue(0, 0), ^{ @@ -63,78 +55,76 @@ - (void)startMonitor { // 假定连续5次超时50ms认为卡顿(当然也包含了单次超时250ms) // 因为下面 runloop 状态改变回调方法runLoopObserverCallBack中会将信号量递增 1,所以每次 runloop 状态改变后,下面的语句都会执行一次 // dispatch_semaphore_wait:Returns zero on success, or non-zero if the timeout occurred. - long st = dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 50*NSEC_PER_MSEC)); - NSLog(@"dispatch_semaphore_wait:st=%ld,time:%@",st,[self getCurTime]); + long st = dispatch_semaphore_wait(self->_semaphore, dispatch_time(DISPATCH_TIME_NOW, 50*NSEC_PER_MSEC)); + NSLog(@"dispatch_semaphore_wait:st=%ld,time:%@",st,getCurTime()); if (st != 0) { // 信号量超时了 - 即 runloop 的状态长时间没有发生变更,长期处于某一个状态下 - if (!observer) { - timeoutCount = 0; - semaphore = 0; - activity = 0; + if (!self->_observer) { + self->_timeoutCount = 0; + self->_semaphore = 0; + self->_activity = 0; return; } - NSLog(@"st = %ld,activity = %lu,timeoutCount = %d,time:%@",st,activity,timeoutCount,[self getCurTime]); + NSLog(@"st = %ld,activity = %lu,timeoutCount = %d,time:%@",st,self->_activity,self->_timeoutCount,getCurTime()); // kCFRunLoopBeforeSources - 即将处理source kCFRunLoopAfterWaiting - 刚从休眠中唤醒 // 获取kCFRunLoopBeforeSources到kCFRunLoopBeforeWaiting再到kCFRunLoopAfterWaiting的状态就可以知道是否有卡顿的情况。 // kCFRunLoopBeforeSources:停留在这个状态,表示在做很多事情 - if (activity == kCFRunLoopBeforeSources || activity == kCFRunLoopAfterWaiting) { // 发生卡顿,记录卡顿次数 - if (++timeoutCount < 5) { + if (self->_activity == kCFRunLoopBeforeSources || self->_activity == kCFRunLoopAfterWaiting) { // 发生卡顿,记录卡顿次数 + if (++self->_timeoutCount < 5) { continue; // 不足 5 次,直接 continue 当次循环,不将timeoutCount置为0 } // 收集Crash信息也可用于实时获取各线程的调用堆栈 -// PLCrashReporterConfig *config = [[PLCrashReporterConfig alloc] initWithSignalHandlerType:PLCrashReporterSignalHandlerTypeBSD symbolicationStrategy:PLCrashReporterSymbolicationStrategyAll]; -// -// PLCrashReporter *crashReporter = [[PLCrashReporter alloc] initWithConfiguration:config]; -// -// NSData *data = [crashReporter generateLiveReport]; -// PLCrashReport *reporter = [[PLCrashReport alloc] initWithData:data error:NULL]; -// NSString *report = [PLCrashReportTextFormatter stringValueForCrashReport:reporter withTextFormat:PLCrashReportTextFormatiOS]; -// -// NSLog(@"---------卡顿信息\n%@\n--------------",report); + // PLCrashReporterConfig *config = [[PLCrashReporterConfig alloc] initWithSignalHandlerType:PLCrashReporterSignalHandlerTypeBSD symbolicationStrategy:PLCrashReporterSymbolicationStrategyAll]; + // + // PLCrashReporter *crashReporter = [[PLCrashReporter alloc] initWithConfiguration:config]; + // + // NSData *data = [crashReporter generateLiveReport]; + // PLCrashReport *reporter = [[PLCrashReport alloc] initWithData:data error:NULL]; + // NSString *report = [PLCrashReportTextFormatter stringValueForCrashReport:reporter withTextFormat:PLCrashReportTextFormatiOS]; + // + // NSLog(@"---------卡顿信息\n%@\n--------------",report); } } - NSLog(@"dispatch_semaphore_wait timeoutCount = 0,time:%@",[self getCurTime]); - timeoutCount = 0; + NSLog(@"dispatch_semaphore_wait timeoutCount = 0,time:%@",getCurTime()); + self->_timeoutCount = 0; } }); } // 停止监听 -- (void)stopMonitor { - if (!observer) { +- (void)stopRunning { + if (!_observer) { return; } - // 移除观察并释放资源 - CFRunLoopRemoveObserver(CFRunLoopGetMain(), observer, kCFRunLoopCommonModes); - CFRelease(observer); - observer = NULL; + CFRunLoopRemoveObserver(CFRunLoopGetMain(), _observer, kCFRunLoopCommonModes); + CFRelease(_observer); + _observer = NULL; } +/* Run Loop Observer Activities + typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) { + kCFRunLoopEntry = (1UL << 0), // 进入RunLoop循环(这里其实还没进入) + kCFRunLoopBeforeTimers = (1UL << 1), // RunLoop 要处理timer了 + kCFRunLoopBeforeSources = (1UL << 2), // RunLoop 要处理source了 + kCFRunLoopBeforeWaiting = (1UL << 5), // RunLoop要休眠了 + kCFRunLoopAfterWaiting = (1UL << 6), // RunLoop醒了 + kCFRunLoopExit = (1UL << 7), // RunLoop退出(和kCFRunLoopEntry对应) + kCFRunLoopAllActivities = 0x0FFFFFFFU + }; + */ #pragma mark - runloop observer callback - -// 就是runloop有一个状态改变 就记录一下 +///runloop状态改变回调 就记录一下 static void runLoopObserverCallBack(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info) { - SLAPMRunLoop *monitor = (__bridge SLAPMRunLoop*)info; + SLAPMRunLoop *monitor = (__bridge SLAPMRunLoop*)info; // 记录状态值 - monitor->activity = activity; + monitor->_activity = activity; // 发送信号 - dispatch_semaphore_t semaphore = monitor->semaphore; + dispatch_semaphore_t semaphore = monitor->_semaphore; long st = dispatch_semaphore_signal(semaphore); - NSLog(@"dispatch_semaphore_signal:st=%ld,time:%@",st,[SLAPMRunLoop getCurTime]); - - /* Run Loop Observer Activities */ -// typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) { -// kCFRunLoopEntry = (1UL << 0), // 进入RunLoop循环(这里其实还没进入) -// kCFRunLoopBeforeTimers = (1UL << 1), // RunLoop 要处理timer了 -// kCFRunLoopBeforeSources = (1UL << 2), // RunLoop 要处理source了 -// kCFRunLoopBeforeWaiting = (1UL << 5), // RunLoop要休眠了 -// kCFRunLoopAfterWaiting = (1UL << 6), // RunLoop醒了 -// kCFRunLoopExit = (1UL << 7), // RunLoop退出(和kCFRunLoopEntry对应) -// kCFRunLoopAllActivities = 0x0FFFFFFFU -// }; + NSLog(@"dispatch_semaphore_signal:st=%ld,time:%@",st,getCurTime()); if (activity == kCFRunLoopEntry) { // 即将进入RunLoop NSLog(@"runLoopObserverCallBack - %@",@"kCFRunLoopEntry"); @@ -154,27 +144,17 @@ static void runLoopObserverCallBack(CFRunLoopObserverRef observer, CFRunLoopActi } #pragma mark - private function - -- (NSString *)getCurTime { - NSDateFormatter *format = [[NSDateFormatter alloc] init]; - [format setDateFormat:@"YYYY/MM/dd hh:mm:ss:SSS"]; - NSString *curTime = [format stringFromDate:[NSDate date]]; - - return curTime; -} - -+ (NSString *) getCurTime { +NSString * getCurTime(void) { NSDateFormatter *format = [[NSDateFormatter alloc] init]; [format setDateFormat:@"YYYY/MM/dd hh:mm:ss:SSS"]; NSString *curTime = [format stringFromDate:[NSDate date]]; - return curTime; } @end - -@interface SLAPMFps () +///监测帧频,抖动比较大,所以结合runloop检测主线程消息循环执行的时间来作为卡顿的衡量指标 +@interface SLAPMFps : NSObject { NSTimeInterval _lastTime; //上次屏幕刷新时间 int _count; //FPS @@ -183,25 +163,7 @@ @interface SLAPMFps () @end @implementation SLAPMFps -#pragma mark - Override -/// 重写allocWithZone方法,保证alloc或者init创建的实例不会产生新实例,因为该类覆盖了allocWithZone方法,所以只能通过其父类分配内存,即[super allocWithZone] -+ (instancetype)allocWithZone:(struct _NSZone *)zone { - return [self sharedInstance]; -} -/// 重写copyWithZone方法,保证复制返回的是同一份实例 -- (nonnull id)copyWithZone:(nullable NSZone *)zone { - return [SLAPMFps sharedInstance]; -} - #pragma mark - Public -+ (instancetype)sharedInstance { - static SLAPMFps *fps = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - fps = [[super allocWithZone:NULL] init]; - }); - return fps; -} ///开始 - (void)play { [self.displayLink setPaused:NO]; @@ -254,9 +216,64 @@ - (void)displayLinkTick:(CADisplayLink *)link{ _lastTime = link.timestamp; _count = 0; - if([self.delegate respondsToSelector:@selector(APMFps:didChangedFps:)]) { - [self.delegate APMFps:self didChangedFps:fps]; + // if([self.delegate respondsToSelector:@selector(APMFps:didChangedFps:)]) { + // [self.delegate APMFps:self didChangedFps:fps]; + // } +} + +@end + + +@interface SLAPMFluency () +@property (nonatomic, strong) SLAPMFps *fps; +@property (nonatomic, strong) SLAPMRunLoop *runLoop; +@end + +@implementation SLAPMFluency +#pragma mark - Override +/// 重写allocWithZone方法,保证alloc或者init创建的实例不会产生新实例,因为该类覆盖了allocWithZone方法,所以只能通过其父类分配内存,即[super allocWithZone] ++ (instancetype)allocWithZone:(struct _NSZone *)zone { + return [self sharedInstance]; +} +/// 重写copyWithZone方法,保证复制返回的是同一份实例 +- (nonnull id)copyWithZone:(nullable NSZone *)zone { + return [SLAPMFluency sharedInstance]; +} + +#pragma mark - Public ++ (instancetype)sharedInstance { + static SLAPMFluency *luency = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + luency = [[super allocWithZone:NULL] init]; + }); + return luency; +} +///开始 +- (void)play { + // [self.displayLink setPaused:NO]; +} +///暂停 +- (void)paused { + // [self.displayLink setPaused:YES]; +} +///销毁 +- (void)invalidate { + +} + +#pragma mark - Getter +- (SLAPMFps *)fps { + if (!_fps) { + _fps = [[SLAPMFps alloc] init]; + } + return _fps; +} +- (SLAPMRunLoop *)runLoop { + if (!_runLoop) { + _runLoop = [[SLAPMRunLoop alloc] init]; } + return _runLoop;; } @end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m index cda36957..3d3989f2 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m @@ -10,7 +10,7 @@ #import "SLTimer.h" #import "SLAPMCpu.h" -#import "SLAPMFps.h" +#import "SLAPMFluency.h" #include @@ -47,8 +47,8 @@ - (void)startMonitoring { _isMonitoring = YES; _taskName = [SLTimer execTask:self selector:@selector(monitoring) start:0 interval:1.0/60 repeats:YES async:YES]; - [SLAPMFps sharedInstance].delegate = self; - [[SLAPMFps sharedInstance] play]; +// [SLAPMFps sharedInstance].delegate = self; +// [[SLAPMFps sharedInstance] play]; } ///结束监控 @@ -56,7 +56,7 @@ - (void)stopMonitoring { if (!_isMonitoring) return; _isMonitoring = NO; [SLTimer cancelTask:_taskName]; - [[SLAPMFps sharedInstance] paused]; +// [[SLAPMFps sharedInstance] paused]; } #pragma mark - Monitoring From 8d82abd65e60ef4fc331b01213562ed1a39a488b Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 15 Jul 2020 15:10:36 +0800 Subject: [PATCH 053/356] =?UTF-8?q?iOS=20=20APM=20=E4=B9=8B=E5=8D=A1?= =?UTF-8?q?=E9=A1=BF=E7=9B=91=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WorkIssues/APM/SLAPMFluency.h | 10 ++- .../DarkMode/WorkIssues/APM/SLAPMFluency.m | 66 ++++++++----------- .../DarkMode/WorkIssues/APM/SLAPMManager.m | 9 ++- 3 files changed, 39 insertions(+), 46 deletions(-) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.h b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.h index 1a521abb..e043c487 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.h +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.h @@ -21,12 +21,10 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, weak) id delegate; + (instancetype)sharedInstance; -///开始 -- (void)play; -///暂停 -- (void)paused; -///销毁 -- (void)invalidate; +///开始监听 +- (void)startMonitoring; +///结束监听 +- (void)stopMonitoring; @end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.m index 62259c53..3e1fe500 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.m @@ -52,11 +52,12 @@ - (void)startRunning { // 在子线程监控时长 dispatch_async(dispatch_get_global_queue(0, 0), ^{ while (YES) { // 有信号的话 就查询当前runloop的状态 + // 假定连续5次超时50ms认为卡顿(当然也包含了单次超时250ms) // 因为下面 runloop 状态改变回调方法runLoopObserverCallBack中会将信号量递增 1,所以每次 runloop 状态改变后,下面的语句都会执行一次 - // dispatch_semaphore_wait:Returns zero on success, or non-zero if the timeout occurred. + // 当其返回0时表示在timeout之前,该函数所处的线程被成功唤醒。当其返回不为0时,表示timeout发生。 long st = dispatch_semaphore_wait(self->_semaphore, dispatch_time(DISPATCH_TIME_NOW, 50*NSEC_PER_MSEC)); - NSLog(@"dispatch_semaphore_wait:st=%ld,time:%@",st,getCurTime()); + if (st != 0) { // 信号量超时了 - 即 runloop 的状态长时间没有发生变更,长期处于某一个状态下 if (!self->_observer) { self->_timeoutCount = 0; @@ -64,7 +65,7 @@ - (void)startRunning { self->_activity = 0; return; } - NSLog(@"st = %ld,activity = %lu,timeoutCount = %d,time:%@",st,self->_activity,self->_timeoutCount,getCurTime()); + // kCFRunLoopBeforeSources - 即将处理source kCFRunLoopAfterWaiting - 刚从休眠中唤醒 // 获取kCFRunLoopBeforeSources到kCFRunLoopBeforeWaiting再到kCFRunLoopAfterWaiting的状态就可以知道是否有卡顿的情况。 // kCFRunLoopBeforeSources:停留在这个状态,表示在做很多事情 @@ -73,19 +74,10 @@ - (void)startRunning { continue; // 不足 5 次,直接 continue 当次循环,不将timeoutCount置为0 } - // 收集Crash信息也可用于实时获取各线程的调用堆栈 - // PLCrashReporterConfig *config = [[PLCrashReporterConfig alloc] initWithSignalHandlerType:PLCrashReporterSignalHandlerTypeBSD symbolicationStrategy:PLCrashReporterSymbolicationStrategyAll]; - // - // PLCrashReporter *crashReporter = [[PLCrashReporter alloc] initWithConfiguration:config]; - // - // NSData *data = [crashReporter generateLiveReport]; - // PLCrashReport *reporter = [[PLCrashReport alloc] initWithData:data error:NULL]; - // NSString *report = [PLCrashReportTextFormatter stringValueForCrashReport:reporter withTextFormat:PLCrashReportTextFormatiOS]; - // - // NSLog(@"---------卡顿信息\n%@\n--------------",report); + // 收集此时卡顿的调用堆栈 + NSLog(@"---------卡顿了--------------"); } } - NSLog(@"dispatch_semaphore_wait timeoutCount = 0,time:%@",getCurTime()); self->_timeoutCount = 0; } }); @@ -123,21 +115,22 @@ static void runLoopObserverCallBack(CFRunLoopObserverRef observer, CFRunLoopActi // 发送信号 dispatch_semaphore_t semaphore = monitor->_semaphore; + // 当返回值为0时表示当前并没有线程等待其处理的信号量,其处理的信号量的值加1即可。当返回值不为0时,表示其当前有(一个或多个)线程等待其处理的信号量,并且该函数唤醒了一个等待的线程(当线程有优先级时,唤醒优先级最高的线程;否则随机唤醒) long st = dispatch_semaphore_signal(semaphore); - NSLog(@"dispatch_semaphore_signal:st=%ld,time:%@",st,getCurTime()); + // NSLog(@"dispatch_semaphore_signal:st=%ld,time:%@",st,getCurTime()); - if (activity == kCFRunLoopEntry) { // 即将进入RunLoop - NSLog(@"runLoopObserverCallBack - %@",@"kCFRunLoopEntry"); - } else if (activity == kCFRunLoopBeforeTimers) { // 即将处理Timer - NSLog(@"runLoopObserverCallBack - %@",@"kCFRunLoopBeforeTimers"); - } else if (activity == kCFRunLoopBeforeSources) { // 即将处理Source - NSLog(@"runLoopObserverCallBack - %@",@"kCFRunLoopBeforeSources"); - } else if (activity == kCFRunLoopBeforeWaiting) { //即将进入休眠 - NSLog(@"runLoopObserverCallBack - %@",@"kCFRunLoopBeforeWaiting"); - } else if (activity == kCFRunLoopAfterWaiting) { // 刚从休眠中唤醒 - NSLog(@"runLoopObserverCallBack - %@",@"kCFRunLoopAfterWaiting"); - } else if (activity == kCFRunLoopExit) { // 即将退出RunLoop - NSLog(@"runLoopObserverCallBack - %@",@"kCFRunLoopExit"); + if (activity == kCFRunLoopEntry) { + NSLog(@"runLoopObserverCallBack - %@",@"即将进入RunLoop"); + } else if (activity == kCFRunLoopBeforeTimers) { + NSLog(@"runLoopObserverCallBack - %@",@"即将处理Timer"); + } else if (activity == kCFRunLoopBeforeSources) { + NSLog(@"runLoopObserverCallBack - %@",@"即将处理Source"); + } else if (activity == kCFRunLoopBeforeWaiting) { + NSLog(@"runLoopObserverCallBack - %@",@"即将进入休眠"); + } else if (activity == kCFRunLoopAfterWaiting) { + NSLog(@"runLoopObserverCallBack - %@",@"刚从休眠中唤醒"); + } else if (activity == kCFRunLoopExit) { + NSLog(@"runLoopObserverCallBack - %@",@"即将退出RunLoop"); } else if (activity == kCFRunLoopAllActivities) { NSLog(@"runLoopObserverCallBack - %@",@"kCFRunLoopAllActivities"); } @@ -249,17 +242,16 @@ + (instancetype)sharedInstance { }); return luency; } -///开始 -- (void)play { - // [self.displayLink setPaused:NO]; -} -///暂停 -- (void)paused { - // [self.displayLink setPaused:YES]; + +///开始监听 +- (void)startMonitoring { + [self.fps play]; + [self.runLoop startRunning]; } -///销毁 -- (void)invalidate { - +///结束监听 +- (void)stopMonitoring { + [self.fps paused]; + [self.runLoop stopRunning]; } #pragma mark - Getter diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m index 3d3989f2..7be8e0bc 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m @@ -45,18 +45,21 @@ + (instancetype)manager { - (void)startMonitoring { if (_isMonitoring) return; _isMonitoring = YES; + _taskName = [SLTimer execTask:self selector:@selector(monitoring) start:0 interval:1.0/60 repeats:YES async:YES]; -// [SLAPMFps sharedInstance].delegate = self; -// [[SLAPMFps sharedInstance] play]; + [SLAPMFluency sharedInstance].delegate = self; + [[SLAPMFluency sharedInstance] startMonitoring]; } ///结束监控 - (void)stopMonitoring { if (!_isMonitoring) return; _isMonitoring = NO; + [SLTimer cancelTask:_taskName]; -// [[SLAPMFps sharedInstance] paused]; + + [[SLAPMFluency sharedInstance] stopMonitoring]; } #pragma mark - Monitoring From 5f03930b317d39e9491495800d4c80acb69b32c2 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 15 Jul 2020 16:39:24 +0800 Subject: [PATCH 054/356] =?UTF-8?q?iOS=20=20APM=E4=B9=8B=20=E5=8D=A1?= =?UTF-8?q?=E9=A1=BF=E7=9B=91=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WorkIssues/APM/SLAPMFluency.h | 10 ++--- .../DarkMode/WorkIssues/APM/SLAPMFluency.m | 45 ++++++++----------- .../DarkMode/WorkIssues/APM/SLAPMManager.h | 20 ++++++++- .../DarkMode/WorkIssues/APM/SLAPMManager.m | 39 +++++++++------- .../WorkIssues/APM/SLAPMViewController.m | 9 ++++ 5 files changed, 73 insertions(+), 50 deletions(-) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.h b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.h index e043c487..fa8a3e82 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.h +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.h @@ -9,16 +9,16 @@ #import NS_ASSUME_NONNULL_BEGIN -@class SLAPMFps; -@protocol SLAPMFpsDelegate -///FPS值改变回调 -- (void)APMFps:(SLAPMFps *)APMFps didChangedFps:(float)fps; +@class SLAPMFluency; +@protocol SLAPMFluencyDelegate +///卡顿监控回调 当callStack不为nil时,表示卡顿并捕捉到卡顿时的调用栈 +- (void)APMFluency:(SLAPMFluency *)fluency didChangedFps:(float)fps callback:(void(^)(NSString *callStack))callback; @end ///流畅度监听 是否卡顿 @interface SLAPMFluency : NSObject -@property (nonatomic, weak) id delegate; +@property (nonatomic, weak) id delegate; + (instancetype)sharedInstance; ///开始监听 diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.m index 3e1fe500..d8cce300 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.m @@ -9,6 +9,8 @@ #import "SLAPMFluency.h" #import "SLProxy.h" +#import "BSBacktraceLogger.h" + /// 利用runloop 检测主线程每次执行消息循环的时间,当这一时间大于阈值时,就记为发生一次卡顿。 @interface SLAPMRunLoop : NSObject { @@ -75,7 +77,7 @@ - (void)startRunning { } // 收集此时卡顿的调用堆栈 - NSLog(@"---------卡顿了--------------"); + NSLog(@" 卡顿了 \n %@", [BSBacktraceLogger bs_backtraceOfMainThread]); } } self->_timeoutCount = 0; @@ -94,17 +96,6 @@ - (void)stopRunning { _observer = NULL; } -/* Run Loop Observer Activities - typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) { - kCFRunLoopEntry = (1UL << 0), // 进入RunLoop循环(这里其实还没进入) - kCFRunLoopBeforeTimers = (1UL << 1), // RunLoop 要处理timer了 - kCFRunLoopBeforeSources = (1UL << 2), // RunLoop 要处理source了 - kCFRunLoopBeforeWaiting = (1UL << 5), // RunLoop要休眠了 - kCFRunLoopAfterWaiting = (1UL << 6), // RunLoop醒了 - kCFRunLoopExit = (1UL << 7), // RunLoop退出(和kCFRunLoopEntry对应) - kCFRunLoopAllActivities = 0x0FFFFFFFU - }; - */ #pragma mark - runloop observer callback ///runloop状态改变回调 就记录一下 static void runLoopObserverCallBack(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info) { @@ -119,21 +110,21 @@ static void runLoopObserverCallBack(CFRunLoopObserverRef observer, CFRunLoopActi long st = dispatch_semaphore_signal(semaphore); // NSLog(@"dispatch_semaphore_signal:st=%ld,time:%@",st,getCurTime()); - if (activity == kCFRunLoopEntry) { - NSLog(@"runLoopObserverCallBack - %@",@"即将进入RunLoop"); - } else if (activity == kCFRunLoopBeforeTimers) { - NSLog(@"runLoopObserverCallBack - %@",@"即将处理Timer"); - } else if (activity == kCFRunLoopBeforeSources) { - NSLog(@"runLoopObserverCallBack - %@",@"即将处理Source"); - } else if (activity == kCFRunLoopBeforeWaiting) { - NSLog(@"runLoopObserverCallBack - %@",@"即将进入休眠"); - } else if (activity == kCFRunLoopAfterWaiting) { - NSLog(@"runLoopObserverCallBack - %@",@"刚从休眠中唤醒"); - } else if (activity == kCFRunLoopExit) { - NSLog(@"runLoopObserverCallBack - %@",@"即将退出RunLoop"); - } else if (activity == kCFRunLoopAllActivities) { - NSLog(@"runLoopObserverCallBack - %@",@"kCFRunLoopAllActivities"); - } +// if (activity == kCFRunLoopEntry) { +// NSLog(@"runLoopObserverCallBack - %@",@"即将进入RunLoop"); +// } else if (activity == kCFRunLoopBeforeTimers) { +// NSLog(@"runLoopObserverCallBack - %@",@"即将处理Timer"); +// } else if (activity == kCFRunLoopBeforeSources) { +// NSLog(@"runLoopObserverCallBack - %@",@"即将处理Source"); +// } else if (activity == kCFRunLoopBeforeWaiting) { +// NSLog(@"runLoopObserverCallBack - %@",@"即将进入休眠"); +// } else if (activity == kCFRunLoopAfterWaiting) { +// NSLog(@"runLoopObserverCallBack - %@",@"刚从休眠中唤醒"); +// } else if (activity == kCFRunLoopExit) { +// NSLog(@"runLoopObserverCallBack - %@",@"即将退出RunLoop"); +// } else if (activity == kCFRunLoopAllActivities) { +// NSLog(@"runLoopObserverCallBack - %@",@"kCFRunLoopAllActivities"); +// } } #pragma mark - private function diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.h b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.h index 8fca8311..2604a1df 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.h +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.h @@ -10,10 +10,29 @@ NS_ASSUME_NONNULL_BEGIN +/// app性能监控策略/类型 +typedef NS_ENUM(NSInteger, SLAPMType) { + /*无*/ + SLAPMTypeNone = 0, + /*CPU占用率*/ + SLAPMTypeCpu = 1 << 0, + /*内存使用情况*/ + SLAPMTypeMemory = 1 << 1, + /*流畅度、卡顿*/ + SLAPMTypeFluency = 1 << 2, + + /*所有策略*/ + SLAPMTypeAll = 1 << 3 +}; + + /// APM 管理者 @interface SLAPMManager : NSObject + ///是否正在监控 @property (nonatomic, assign) BOOL isMonitoring; +///app性能监控策略/类型 默认SLAPMTypeAll +@property (nonatomic, assign) SLAPMType type; + (instancetype)manager; @@ -22,7 +41,6 @@ NS_ASSUME_NONNULL_BEGIN ///结束监控 - (void)stopMonitoring; - @end NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m index 7be8e0bc..0ebc9161 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m @@ -14,7 +14,7 @@ #include -@interface SLAPMManager () +@interface SLAPMManager () ///任务名称 @property (nonatomic, copy) NSString *taskName; @@ -38,6 +38,7 @@ + (instancetype)manager { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ manager = [[super allocWithZone:NULL] init]; + manager.type = SLAPMTypeAll; }); return manager; } @@ -46,10 +47,14 @@ - (void)startMonitoring { if (_isMonitoring) return; _isMonitoring = YES; - _taskName = [SLTimer execTask:self selector:@selector(monitoring) start:0 interval:1.0/60 repeats:YES async:YES]; + if ((self.type & SLAPMTypeCpu) == SLAPMTypeCpu || (self.type & SLAPMTypeMemory) == SLAPMTypeMemory || (self.type & SLAPMTypeAll) == SLAPMTypeAll) { + _taskName = [SLTimer execTask:self selector:@selector(monitoring) start:0 interval:1.0/60 repeats:YES async:YES]; + } - [SLAPMFluency sharedInstance].delegate = self; - [[SLAPMFluency sharedInstance] startMonitoring]; + if ((self.type & SLAPMTypeFluency) == SLAPMTypeFluency) { + [SLAPMFluency sharedInstance].delegate = self; + [[SLAPMFluency sharedInstance] startMonitoring]; + } } ///结束监控 @@ -58,7 +63,6 @@ - (void)stopMonitoring { _isMonitoring = NO; [SLTimer cancelTask:_taskName]; - [[SLAPMFluency sharedInstance] stopMonitoring]; } @@ -66,13 +70,17 @@ - (void)stopMonitoring { ///监控中 - (void)monitoring { - float CPU = [SLAPMCpu getCpuUsage]; - NSLog(@" CPU使用率:%.2f%%",CPU); + if ((self.type & SLAPMTypeCpu) == SLAPMTypeCpu || (self.type & SLAPMTypeAll) == SLAPMTypeAll) { + float CPU = [SLAPMCpu getCpuUsage]; + NSLog(@" CPU使用率:%.2f%%",CPU); + } - double useMemory = [SLAPMManager getUsageMemory]; - double freeMemory = [SLAPMManager getFreeMemory]; - double totalMemory = [SLAPMManager getTotalMemory]; - NSLog(@" Memory占用:%.1fM 空闲:%.1fM 总共:%.1fM",useMemory, freeMemory, totalMemory); + if ((self.type & SLAPMTypeMemory) == SLAPMTypeMemory || (self.type & SLAPMTypeAll) == SLAPMTypeAll) { + double useMemory = [SLAPMManager getUsageMemory]; + double freeMemory = [SLAPMManager getFreeMemory]; + double totalMemory = [SLAPMManager getTotalMemory]; + NSLog(@" Memory占用:%.1fM 空闲:%.1fM 总共:%.1fM",useMemory, freeMemory, totalMemory); + } } @@ -111,7 +119,7 @@ + (double)getTotalMemory { ///filePath目录下的文件 占用的磁盘大小 单位MB 默认沙盒Caches目录 + (double)getUsageDisk:(NSString *)filePath { if (filePath.length == 0) filePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject; - ///定时执行时,此句代码会导致内存不断增长?0.1M + ///定时执行时,此句代码会导致内存不断增长?0.1M 合理安排执行时机 NSArray *filesArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:filePath error:nil] ; NSEnumerator *filesEnumerator = [filesArray objectEnumerator]; filesArray = nil; @@ -141,10 +149,7 @@ + (double)getTotalDisk { return [totalSize integerValue] / (1024*1024*1024); } -#pragma mark - FPS -///FPS值改变回调 -- (void)APMFps:(SLAPMFps *)APMFps didChangedFps:(float)fps { - NSLog(@" FPS:%.2f",fps); -} +#pragma mark - Fluency/卡顿监测 + @end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m index 60cf7ee8..04ec94be 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m @@ -26,6 +26,15 @@ - (void)viewDidLoad { self.view.backgroundColor = [UIColor whiteColor]; self.navigationItem.title = @"APM监控"; [self setupNavigationBar]; + [SLAPMManager manager].type = SLAPMTypeFluency; +} + +//测试卡顿 +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + //耗时任务 + for (int i = 0; i < 1000; i++) { + sleep(1); + } } #pragma mark - UI From b278cb5d9f8627099d3361cc5a509d0389ba0988 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 15 Jul 2020 18:02:52 +0800 Subject: [PATCH 055/356] =?UTF-8?q?iOS=20APM=E4=B9=8B=E5=8D=A1=E9=A1=BF?= =?UTF-8?q?=E7=9B=91=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WorkIssues/APM/SLAPMFluency.h | 16 +++- .../DarkMode/WorkIssues/APM/SLAPMFluency.m | 84 ++++++++++++++----- .../DarkMode/WorkIssues/APM/SLAPMManager.m | 7 +- .../WorkIssues/APM/SLAPMViewController.m | 4 +- 4 files changed, 81 insertions(+), 30 deletions(-) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.h b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.h index fa8a3e82..72b4f340 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.h +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.h @@ -11,14 +11,26 @@ NS_ASSUME_NONNULL_BEGIN @class SLAPMFluency; @protocol SLAPMFluencyDelegate -///卡顿监控回调 当callStack不为nil时,表示卡顿并捕捉到卡顿时的调用栈 -- (void)APMFluency:(SLAPMFluency *)fluency didChangedFps:(float)fps callback:(void(^)(NSString *callStack))callback; +///卡顿监控回调 当callStack不为nil时,表示发生卡顿并捕捉到卡顿时的调用栈;type == SLAPMFluencyTypeRunloop时,fps为0 +- (void)APMFluency:(SLAPMFluency *)fluency didChangedFps:(float)fps callStackOfStuck:(nullable NSString *)callStack; @end +/// 卡顿监测策略/类型 +typedef NS_ENUM(NSInteger, SLAPMFluencyType) { + /* 建议 Runloop,不消耗额外的CPU资源,可以获取卡顿时的调用堆栈 */ + SLAPMFluencyTypeRunloop = 0, + /*FPS 无法获取卡顿时的调用堆栈,消耗CPU资源,不利于CPU使用率的监控,但可以作为衡量卡顿程度的指数*/ + SLAPMFluencyTypeFps = 1, + /*所有策略*/ + SLAPMFluencyTypeAll = 2 +}; + ///流畅度监听 是否卡顿 @interface SLAPMFluency : NSObject @property (nonatomic, weak) id delegate; +///卡顿监测策略/类型 默认建议 SLAPMFluencyTypeRunloop +@property (nonatomic, assign) SLAPMFluencyType type; + (instancetype)sharedInstance; ///开始监听 diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.m index d8cce300..c1608432 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.m @@ -19,6 +19,9 @@ @interface SLAPMRunLoop : NSObject dispatch_semaphore_t _semaphore; // 信号 CFRunLoopActivity _activity; // 状态 } +///卡顿时的调用堆栈信息 +@property (nonatomic, copy) NSString *callStack; +@property (nonatomic, copy) void (^showStuckInfo)(NSString *callStack); @end @implementation SLAPMRunLoop @@ -77,7 +80,12 @@ - (void)startRunning { } // 收集此时卡顿的调用堆栈 - NSLog(@" 卡顿了 \n %@", [BSBacktraceLogger bs_backtraceOfMainThread]); + NSString *callStack = [BSBacktraceLogger bs_backtraceOfMainThread]; + self.callStack = callStack; + if(self.showStuckInfo) { + self.showStuckInfo(callStack); + } + // NSLog(@" 卡顿了 \n %@", callStack); } } self->_timeoutCount = 0; @@ -110,21 +118,21 @@ static void runLoopObserverCallBack(CFRunLoopObserverRef observer, CFRunLoopActi long st = dispatch_semaphore_signal(semaphore); // NSLog(@"dispatch_semaphore_signal:st=%ld,time:%@",st,getCurTime()); -// if (activity == kCFRunLoopEntry) { -// NSLog(@"runLoopObserverCallBack - %@",@"即将进入RunLoop"); -// } else if (activity == kCFRunLoopBeforeTimers) { -// NSLog(@"runLoopObserverCallBack - %@",@"即将处理Timer"); -// } else if (activity == kCFRunLoopBeforeSources) { -// NSLog(@"runLoopObserverCallBack - %@",@"即将处理Source"); -// } else if (activity == kCFRunLoopBeforeWaiting) { -// NSLog(@"runLoopObserverCallBack - %@",@"即将进入休眠"); -// } else if (activity == kCFRunLoopAfterWaiting) { -// NSLog(@"runLoopObserverCallBack - %@",@"刚从休眠中唤醒"); -// } else if (activity == kCFRunLoopExit) { -// NSLog(@"runLoopObserverCallBack - %@",@"即将退出RunLoop"); -// } else if (activity == kCFRunLoopAllActivities) { -// NSLog(@"runLoopObserverCallBack - %@",@"kCFRunLoopAllActivities"); -// } + // if (activity == kCFRunLoopEntry) { + // NSLog(@"runLoopObserverCallBack - %@",@"即将进入RunLoop"); + // } else if (activity == kCFRunLoopBeforeTimers) { + // NSLog(@"runLoopObserverCallBack - %@",@"即将处理Timer"); + // } else if (activity == kCFRunLoopBeforeSources) { + // NSLog(@"runLoopObserverCallBack - %@",@"即将处理Source"); + // } else if (activity == kCFRunLoopBeforeWaiting) { + // NSLog(@"runLoopObserverCallBack - %@",@"即将进入休眠"); + // } else if (activity == kCFRunLoopAfterWaiting) { + // NSLog(@"runLoopObserverCallBack - %@",@"刚从休眠中唤醒"); + // } else if (activity == kCFRunLoopExit) { + // NSLog(@"runLoopObserverCallBack - %@",@"即将退出RunLoop"); + // } else if (activity == kCFRunLoopAllActivities) { + // NSLog(@"runLoopObserverCallBack - %@",@"kCFRunLoopAllActivities"); + // } } #pragma mark - private function @@ -137,13 +145,15 @@ static void runLoopObserverCallBack(CFRunLoopObserverRef observer, CFRunLoopActi @end -///监测帧频,抖动比较大,所以结合runloop检测主线程消息循环执行的时间来作为卡顿的衡量指标 +///监测帧频,抖动比较大,无法获取卡顿时的调用栈,所以结合runloop检测主线程消息循环执行的时间来作为卡顿的衡量指标 @interface SLAPMFps : NSObject { NSTimeInterval _lastTime; //上次屏幕刷新时间 int _count; //FPS } @property (nonatomic, strong) CADisplayLink *displayLink; +@property (nonatomic, assign) float fps; +@property (nonatomic, copy) void (^fpsChanged)(float fps); @end @implementation SLAPMFps @@ -195,16 +205,16 @@ - (void)displayLinkTick:(CADisplayLink *)link{ } //刷新频率 float fps = _count / interval; + _fps = fps; //1秒之后,初始化时间和次数,重新开始监测 _lastTime = link.timestamp; _count = 0; - // if([self.delegate respondsToSelector:@selector(APMFps:didChangedFps:)]) { - // [self.delegate APMFps:self didChangedFps:fps]; - // } + if (self.fpsChanged) { + self.fpsChanged(fps); + } } - @end @@ -230,14 +240,42 @@ + (instancetype)sharedInstance { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ luency = [[super allocWithZone:NULL] init]; + luency.type = SLAPMFluencyTypeRunloop; }); return luency; } ///开始监听 - (void)startMonitoring { - [self.fps play]; - [self.runLoop startRunning]; + __weak typeof(self) weakSelf = self; + if (self.type == SLAPMFluencyTypeRunloop) { + [self.runLoop startRunning]; + //防止跟 self.fps.fpsChanged的回调重复执行 + self.runLoop.showStuckInfo = ^(NSString *callStack) { + if ([weakSelf.delegate respondsToSelector:@selector(APMFluency:didChangedFps:callStackOfStuck:)]) { + [weakSelf.delegate APMFluency:weakSelf didChangedFps:weakSelf.fps.fps callStackOfStuck:callStack]; + } + }; + + }else if (self.type == SLAPMFluencyTypeFps) { + [self.fps play]; + self.fps.fpsChanged = ^(float fps) { + if ([weakSelf.delegate respondsToSelector:@selector(APMFluency:didChangedFps:callStackOfStuck:)]) { + [weakSelf.delegate APMFluency:weakSelf didChangedFps:fps callStackOfStuck:[weakSelf.runLoop.callStack copy]]; + weakSelf.runLoop.callStack = nil; + } + }; + }else if (self.type == SLAPMFluencyTypeAll) { + [self.fps play]; + [self.runLoop startRunning]; + self.fps.fpsChanged = ^(float fps) { + if ([weakSelf.delegate respondsToSelector:@selector(APMFluency:didChangedFps:callStackOfStuck:)]) { + [weakSelf.delegate APMFluency:weakSelf didChangedFps:fps callStackOfStuck:[weakSelf.runLoop.callStack copy]]; + weakSelf.runLoop.callStack = nil; + } + }; + } + } ///结束监听 - (void)stopMonitoring { diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m index 0ebc9161..fdef1bf6 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m @@ -51,7 +51,7 @@ - (void)startMonitoring { _taskName = [SLTimer execTask:self selector:@selector(monitoring) start:0 interval:1.0/60 repeats:YES async:YES]; } - if ((self.type & SLAPMTypeFluency) == SLAPMTypeFluency) { + if ((self.type & SLAPMTypeFluency) == SLAPMTypeFluency || (self.type & SLAPMTypeAll) == SLAPMTypeAll) { [SLAPMFluency sharedInstance].delegate = self; [[SLAPMFluency sharedInstance] startMonitoring]; } @@ -150,6 +150,9 @@ + (double)getTotalDisk { } #pragma mark - Fluency/卡顿监测 - +///卡顿监控回调 当callStack不为nil时,表示发生卡顿并捕捉到卡顿时的调用栈 +- (void)APMFluency:(SLAPMFluency *)fluency didChangedFps:(float)fps callStackOfStuck:(nullable NSString *)callStack { + NSLog(@" 卡顿监测  fps:%f \n %@", fps, callStack == nil ? @"流畅":[NSString stringWithFormat:@"卡住了 %@",callStack]); +} @end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m index 04ec94be..39504ff5 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m @@ -32,9 +32,7 @@ - (void)viewDidLoad { //测试卡顿 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { //耗时任务 - for (int i = 0; i < 1000; i++) { - sleep(1); - } + sleep(1); } #pragma mark - UI From 3deffed2773487351552db32432e4bdc1e7d5403 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 15 Jul 2020 18:27:38 +0800 Subject: [PATCH 056/356] =?UTF-8?q?iOS=20=20crash=E9=98=B2=E6=8A=A4?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Crash/SLCrashProtector/SLCrashHandler.h | 5 +++-- .../Crash/SLCrashProtector/SLCrashHandler.m | 4 ++-- iOS_Tips/DarkMode/Crash/SLCrashViewController.m | 15 +++++++++++++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h index ff591426..03b313fe 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h @@ -48,12 +48,13 @@ typedef NS_ENUM(NSInteger, SLCrashErrorType) { /// 崩溃处理程序 @interface SLCrashHandler : NSObject -/// 异常捕获回调 提供给外界初始化实现自定义处理 ,日志上报等(注意线程安全) +/// 异常捕获回调 提供给外界初始化实现自定义处理 ,日志上报等(注意线程安全和循环引用) @property (nonatomic, copy) void(^crashHandlerBlock)(SLCrashError *crashError); /// 单例 + (instancetype)defaultCrashHandler; -/// 捕获崩溃异常信息 + +/// 捕获崩溃异常信息 Private - (void)catchCrashException:(NSException * _Nullable )exception type:(SLCrashErrorType)errorType errorDesc:(NSString *)errorDesc; @end diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m index cee8752d..e366d975 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m @@ -26,11 +26,11 @@ + (instancetype)defaultCrashHandler { - (void)catchCrashException:(NSException *)exception type:(SLCrashErrorType)errorType errorDesc:(NSString *)errorDesc { SLCrashError *crashError = [SLCrashError new]; crashError.errorDesc = errorDesc; - crashError.errorType = SLCrashErrorTypeArray; + crashError.errorType = errorType; crashError.exception = exception; //获取当前线程的函数调用栈 crashError.callStackSymbol = [NSThread callStackSymbols]; - NSLog(@"%@" ,errorDesc); +// NSLog(@"%@" ,errorDesc); if (self.crashHandlerBlock) { self.crashHandlerBlock(crashError); } diff --git a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m index 1b073d87..39632c65 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m @@ -11,6 +11,9 @@ @interface SLCrashViewController () +@property (nonatomic, strong) UITextView *textView; + + @property (nonatomic, copy) void(^testBlock)(void); //测试循环引用 @property (nonatomic, strong) NSMutableArray *testMArray; //测试循环引用 @@ -28,15 +31,23 @@ - (void)viewDidLoad { [super viewDidLoad]; [self setupUI]; } +- (void)dealloc { + +} #pragma mark - UI - (void)setupUI { self.navigationItem.title = @"iOS Crash防护"; self.view.backgroundColor = [UIColor whiteColor]; + self.textView = [[UITextView alloc] initWithFrame:self.view.bounds]; + self.textView.editable = NO; + [self.view addSubview:self.textView]; + + SL_WeakSelf; [SLCrashHandler defaultCrashHandler].crashHandlerBlock = ^(SLCrashError * _Nonnull crashError) { -// NSLog(@"%@/%@" ,crashError.errorDesc, [BSBacktraceLogger bs_backtraceOfCurrentThread]); + weakSelf.textView.text = [NSString stringWithFormat:@" 错误描述:%@ \n 调用栈:%@" ,crashError.errorDesc, crashError.callStackSymbol]; }; - [self testCallStack]; + [self testArray]; } #pragma mark - Container Crash From b7961a682dfbf614f12248a9fa1bd6ee279c40ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Wed, 15 Jul 2020 18:48:55 +0800 Subject: [PATCH 057/356] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c3d09873..5b0db3f5 100644 --- a/README.md +++ b/README.md @@ -129,9 +129,11 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git #### 6.7、[二进制重排优化启动速度](https://juejin.im/post/5ea79839f265da7bba509590) #### 6.8、[iOS APM应用性能监控管理(doing)]() +> CPU占用率、内存/磁盘使用率、卡顿监控定位 ...... + ## 7、iOS Crash防护 -> NSArray/NSMutableArray、NSDictionary/NSMutableDictionary、NSString/NSMutableString、Unrecognized Selector、KVO、KVC 、野指针定位、内存泄漏/循环引用 +> Crash防护内容涉及 NSArray/NSMutableArray、NSDictionary/NSMutableDictionary、NSString/NSMutableString、Unrecognized Selector、KVO、KVC 、野指针定位、内存泄漏/循环引用;主要是对常见易错的地方进行容错处理,避免崩溃,并保存出错时的函数调用栈,以方便快速定位代码,主要是利用的runtime和fishook知识。 ## 8、[WKWebView相关](https://juejin.im/post/5ed999fd51882542f9389949) From bc5fe308471b4ac4ca843f91e43fe0becdf69186 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 16 Jul 2020 09:12:07 +0800 Subject: [PATCH 058/356] =?UTF-8?q?iOS=20APM=E4=B9=8BCrash?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/Crash/SLCrashProtector/NSArray+SLCrashProtector.m | 1 - iOS_Tips/DarkMode/Crash/SLCrashProtector/SLKVODelegate.m | 1 + .../Crash/SLCrashProtector/UIViewController+SLMLeakFinder.m | 1 + iOS_Tips/DarkMode/Crash/SLCrashViewController.m | 1 + iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch | 1 - 5 files changed, 3 insertions(+), 2 deletions(-) diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSArray+SLCrashProtector.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSArray+SLCrashProtector.m index 20cd24f2..fc094b60 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSArray+SLCrashProtector.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSArray+SLCrashProtector.m @@ -10,7 +10,6 @@ #import "SLCrashProtector.h" - @implementation NSArray (SLCrashProtector) + (void)load { diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLKVODelegate.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLKVODelegate.m index 41cb5470..332a5ed5 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLKVODelegate.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLKVODelegate.m @@ -7,6 +7,7 @@ // #import "SLKVODelegate.h" +#import "SLCrashProtector.h" @interface SLKVODelegate () { diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/UIViewController+SLMLeakFinder.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/UIViewController+SLMLeakFinder.m index aab78c98..fe6b4227 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/UIViewController+SLMLeakFinder.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/UIViewController+SLMLeakFinder.m @@ -7,6 +7,7 @@ // #import "UIViewController+SLMLeakFinder.h" +#import "SLCrashProtector.h" #import "NSObject+SLMLeakFinder.h" const void *const kSLHasBeenPoppedKey = &kSLHasBeenPoppedKey; diff --git a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m index 39632c65..00fcd7af 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m @@ -7,6 +7,7 @@ // #import "SLCrashViewController.h" +#import "SLCrashProtector.h" #import "BSBacktraceLogger.h" @interface SLCrashViewController () diff --git a/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch b/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch index 2af90eae..c787ae09 100644 --- a/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch +++ b/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch @@ -141,7 +141,6 @@ #import "SLDelayPerform.h" #import "SLAlertView.h" #import "Masonry.h" -#import "SLCrashProtector.h" #import "SLMethod.h" #import "SLViewController.h" From 063443762d1454239b731bb9b7b248148f5f2f6e Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 16 Jul 2020 10:36:48 +0800 Subject: [PATCH 059/356] =?UTF-8?q?iOS=20APM=E4=B9=8BCrash=E9=98=B2?= =?UTF-8?q?=E6=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/AppDelegate.m | 2 +- iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieCatcher.m | 3 ++- iOS_Tips/DarkMode/Crash/SLCrashViewController.m | 5 +++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/iOS_Tips/DarkMode/AppDelegate.m b/iOS_Tips/DarkMode/AppDelegate.m index dc1c6c60..f6470d77 100644 --- a/iOS_Tips/DarkMode/AppDelegate.m +++ b/iOS_Tips/DarkMode/AppDelegate.m @@ -31,7 +31,7 @@ void HandleException(NSException *exception) { // 异常名称 NSString *name = [exception name]; NSString *exceptionInfo = [NSString stringWithFormat:@"程序异常:%@ \nException reason:%@ \nException stack:%@",name, reason, stackArray]; -// NSLog(@"%@", exceptionInfo); + NSLog(@"%@", exceptionInfo); } //设置异常捕获处理方法 void SLSetUncaughtExceptionHandler(void) { diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieCatcher.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieCatcher.m index e536bda1..6ae21b40 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieCatcher.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieCatcher.m @@ -125,7 +125,8 @@ - (void)_throwMessageSentExceptionWithSelector: (SEL)selector { NSException *exception = [NSException exceptionWithName:NSInternalInconsistencyException reason:[NSString stringWithFormat:@"( 野指针必现定位:-[%@ %@]) was sent to a zombie object at address: %p", NSStringFromClass(self.originClass), NSStringFromSelector(selector), self] userInfo:nil]; [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeZombie errorDesc:exception.reason]; - @throw exception; + //是否需要强制抛出异常 +// @throw exception; } @end diff --git a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m index 00fcd7af..c713c532 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m @@ -177,12 +177,13 @@ - (void)testKVC { ///野指针 随机性太强,不方便复现和定位问题,我们需要做的就是把随机变为必现,并且定位到对应的代码,方便查找解决 ///思路来源: https://www.jianshu.com/p/9fd4dc046046?utm_source=oschina-app - (void)testWildPointer { - //开启僵尸对象嗅探定位 + //开启僵尸对象嗅探定位 可以打开或关闭此开关看看效果就知道了 [SLZombieFinder startSniffer]; UILabel *label = [[UILabel alloc] init]; //-fno-objc-arc 记得设置此类编译方式支持MRC //testObj对象所在的内存空间已释放 + label.text = @""; [label release]; //这时新建一个示例对象,覆盖掉了野指针label所指向的内存空间,如果此时没有创建此同类,就会崩溃 @@ -190,7 +191,7 @@ - (void)testWildPointer { newView.backgroundColor = [UIColor greenColor]; [self.view addSubview:newView]; - //向野指针label指向的内存对象发送修改颜色的消息,结果是newView接收到了,因为newView和label是同类,可以处理此消息,所以没有崩溃 + //向野指针label指向的内存对象发送修改颜色的消息,结果是newView接收到了,因为newView和label是同类,可以处理此消息,所以没有崩溃; 在不开启startSniffer时,就把newView的backgroundColor修改了,开启startSniffer后,阻断了向野指针发消息的过程 label.backgroundColor = [UIColor orangeColor]; } From faca6c93a62d45a5f9bbffb0917aa7c5565c5376 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 16 Jul 2020 11:54:56 +0800 Subject: [PATCH 060/356] =?UTF-8?q?iOS=20Crash=E9=98=B2=E6=8A=A4=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SLCrashProtector/NSObject+SLMLeakFinder.m | 6 +- .../Crash/SLCrashProtector/SLCrashHandler.h | 4 +- .../DarkMode/Crash/SLCrashViewController.m | 72 +++++++++++++++---- 3 files changed, 67 insertions(+), 15 deletions(-) diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSObject+SLMLeakFinder.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSObject+SLMLeakFinder.m index 1ff9b88a..b6dfcbe4 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSObject+SLMLeakFinder.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSObject+SLMLeakFinder.m @@ -7,6 +7,7 @@ // #import "NSObject+SLMLeakFinder.h" +#import "SLCrashProtector.h" @implementation NSObject (SLMLeakFinder) @@ -33,7 +34,10 @@ - (BOOL)willDealloc { - (void)notDealloc { NSString *className = NSStringFromClass([self class]); // NSLog(@"有内存没释放:\n 如果%@不应该被释放, 请重写[%@ -willDealloc] 并 returning NO .\nView-ViewController stack: %@", className, className, [self viewStack]); - NSLog(@"有内存没释放:如果%@不应该被释放, 请重写[%@ -willDealloc] 并 returning NO .\n", className, className); + NSString *desc = [NSString stringWithFormat:@"内存泄漏/循环引用:如果%@不应该被释放, 请重写[%@ -willDealloc] 并 returning NO .\n", className, className]; + NSLog(@"%@",desc); + NSException *exception = [NSException exceptionWithName:NSInternalInconsistencyException reason:desc userInfo:nil]; + [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeLeak errorDesc:desc]; } //不需要监测内存泄漏的白名单类 diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h index 03b313fe..f8c3fc1d 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h @@ -30,7 +30,9 @@ typedef NS_ENUM(NSInteger, SLCrashErrorType) { /*KVC异常*/ SLCrashErrorTypeKVC, /*野指针*/ - SLCrashErrorTypeZombie, + SLCrashErrorTypeZombie, + /*内存泄漏/循环引用*/ + SLCrashErrorTypeLeak }; /// 崩溃信息 diff --git a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m index c713c532..babd8cc2 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m @@ -40,15 +40,54 @@ - (void)dealloc { - (void)setupUI { self.navigationItem.title = @"iOS Crash防护"; self.view.backgroundColor = [UIColor whiteColor]; - self.textView = [[UITextView alloc] initWithFrame:self.view.bounds]; + + NSArray *methods = @[@"testArray", + @"testMutableArray", + @"testDictionary", + @"testMutableDictionary", + @"testString", + @"testMutableString", + @"testUnrecognizedSelector", + @"testKVO", + @"testKVC", + @"testWildPointer", + @"testMemoryLeak", + @"testCallStack"]; + NSArray *titles = @[@"数组越界、空值", + @"可变数组越界、空值", + @"字典越界、空值", + @"可变字典越界、空值", + @"字符串越界、空值", + @"可变字符串越界、空值", + @"未实现方法", + @"KVO", + @"KVC", + @"野指针", + @"内存泄漏/循环引用", + @"回调栈"]; + CGSize size = CGSizeMake(self.view.sl_width/4.0, 66); + int i = 0; + for (NSString *method in methods) { + UIButton *testBtn = [[UIButton alloc] initWithFrame:CGRectMake(i%4*size.width, SL_TopNavigationBarHeight+ i/4*size.height, size.width, size.height)]; + [testBtn setTitle:titles[i] forState:UIControlStateNormal]; + testBtn.backgroundColor = UIColor.orangeColor; + testBtn.titleLabel.numberOfLines = 0; + testBtn.titleLabel.textAlignment = NSTextAlignmentCenter; + testBtn.layer.borderColor = [UIColor blackColor].CGColor; + testBtn.layer.borderWidth = 1.0; + [testBtn addTarget:self action:NSSelectorFromString(method) forControlEvents:UIControlEventTouchUpInside]; + [self.view addSubview:testBtn]; + i++; + } + self.textView = [[UITextView alloc] initWithFrame:CGRectMake(0, SL_TopNavigationBarHeight+ i/4*size.height, self.view.sl_width, self.view.sl_height - (SL_TopNavigationBarHeight+ i/4*size.height))]; self.textView.editable = NO; [self.view addSubview:self.textView]; + SL_WeakSelf; [SLCrashHandler defaultCrashHandler].crashHandlerBlock = ^(SLCrashError * _Nonnull crashError) { weakSelf.textView.text = [NSString stringWithFormat:@" 错误描述:%@ \n 调用栈:%@" ,crashError.errorDesc, crashError.callStackSymbol]; }; - [self testArray]; } #pragma mark - Container Crash @@ -183,17 +222,22 @@ - (void)testWildPointer { UILabel *label = [[UILabel alloc] init]; //-fno-objc-arc 记得设置此类编译方式支持MRC //testObj对象所在的内存空间已释放 - label.text = @""; [label release]; //这时新建一个示例对象,覆盖掉了野指针label所指向的内存空间,如果此时没有创建此同类,就会崩溃 - UILabel* newView = [[UILabel alloc] initWithFrame:CGRectMake(0,200,SL_kScreenWidth, 60)]; + UILabel* newView = [[UILabel alloc] initWithFrame:CGRectMake(0,SL_kScreenHeight- 60,SL_kScreenWidth, 60)]; newView.backgroundColor = [UIColor greenColor]; + newView.text = @"startSniffer开启 显示正常"; [self.view addSubview:newView]; //向野指针label指向的内存对象发送修改颜色的消息,结果是newView接收到了,因为newView和label是同类,可以处理此消息,所以没有崩溃; 在不开启startSniffer时,就把newView的backgroundColor修改了,开启startSniffer后,阻断了向野指针发消息的过程 label.backgroundColor = [UIColor orangeColor]; + label.text = @"startSniffer关闭 我是野指针,显示错误"; + + [SLDelayPerform sl_startDelayPerform:^{ + [newView removeFromSuperview]; + } afterDelay:2.0]; } #pragma mark - 内存泄漏/循环引用 @@ -201,23 +245,25 @@ - (void)testWildPointer { //思路来源:https://github.com/Tencent/MLeaksFinder.git //查找循引用连 FBRetainCycleDetector https://yq.aliyun.com/articles/66857 、 https://blog.csdn.net/majiakun1/article/details/78747226 - (void)testMemoryLeak { - self.testBlock = ^{ - self; - }; -// self.testMArray = [[NSMutableArray alloc] initWithObjects:self, nil]; + + //执行此方法后,返回上一级界面,发现SLCrashViewController对象没释放 + self.testBlock = ^{ + self; + }; + // self.testMArray = [[NSMutableArray alloc] initWithObjects:self, nil]; } #pragma mark - 函数调用栈 ///获取任意线程的函数调用栈 https://toutiao.io/posts/aveig6/preview - (void)testCallStack { //打印当前线程调用栈 -// BSLOG; + BSLOG; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ - //在子线程中 打印主线程调用栈,会发现栈基本是空的,因为都已释放了 -// BSLOG_MAIN - BSLOG; + //在子线程中 打印主线程调用栈,会发现栈基本是空的,因为都已释放了 + // BSLOG_MAIN + // BSLOG; }); -// BSLOG_MAIN + // BSLOG_MAIN } @end From 98478892d0c91d09a67bcf372b0d83c8fcdf9103 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 16 Jul 2020 14:55:35 +0800 Subject: [PATCH 061/356] =?UTF-8?q?iOS=20=20Crash=E9=98=B2=E6=8A=A4?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NSArray+SLCrashProtector.m | 12 ++++--- .../NSDictionary+SLCrashProtector.m | 10 ++++-- .../NSMutableArray+SLCrashProtector.m | 32 +++++++++++++------ .../NSMutableDictionary+SLCrashProtector.m | 12 ++++--- .../NSMutableString+SLCrashProtector.m | 6 ++-- .../NSObject+SLCrashProtector.m | 32 +++++++++++++------ .../SLCrashProtector/NSObject+SLMLeakFinder.m | 3 +- .../NSString+SLCrashProtector.m | 15 +++++---- .../Crash/SLCrashProtector/SLCrashHandler.h | 16 +++++++--- .../Crash/SLCrashProtector/SLCrashHandler.m | 24 ++++++-------- .../Crash/SLCrashProtector/SLKVODelegate.m | 3 +- .../Crash/SLCrashProtector/SLZombieCatcher.m | 3 +- .../DarkMode/Crash/SLCrashViewController.m | 16 ++++++---- 13 files changed, 115 insertions(+), 69 deletions(-) diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSArray+SLCrashProtector.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSArray+SLCrashProtector.m index fc094b60..dd4f2f32 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSArray+SLCrashProtector.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSArray+SLCrashProtector.m @@ -34,7 +34,8 @@ - (id)sl_objectAtIndex:(NSInteger)index { return [self sl_objectAtIndex:index]; } @catch (NSException *exception) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason]]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; return nil; } }else { @@ -49,7 +50,8 @@ - (id)sl_singleObjectAtIndex:(NSInteger)index { return [self sl_singleObjectAtIndex:index]; } @catch (NSException *exception) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason]]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; return nil; } }else { @@ -65,7 +67,8 @@ - (id)sl_objectAtIndexedSubscript:(NSInteger)index { return [self sl_objectAtIndexedSubscript:index]; } @catch (NSException *exception) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason]]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; return nil; } } @@ -82,7 +85,8 @@ - (id)sl_initWithObjects:(id _Nonnull const [])objects count:(NSUInteger)cnt{ }else{ //记录错误 NSString *errorInfo = [NSString stringWithFormat:@"异常:数组nil值 *** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[%d]",i]; - [[SLCrashHandler defaultCrashHandler] catchCrashException:nil type:SLCrashErrorTypeArray errorDesc:errorInfo]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeArray errorDesc:errorInfo exception:nil callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } } return [self sl_initWithObjects:objectsNew count:index]; diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSDictionary+SLCrashProtector.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSDictionary+SLCrashProtector.m index 197c1dca..54c66476 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSDictionary+SLCrashProtector.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSDictionary+SLCrashProtector.m @@ -27,7 +27,9 @@ + (void)load { - (id)sl_initWithObjects:(NSArray *)objects forKeys:(NSArray> *)keys { if (objects.count != keys.count) { NSString *errorInfo = [NSString stringWithFormat:@"异常:字典key/value个数不匹配 *** -[NSDictionary initWithObjects:forKeys:]: count of objects (%ld) differs from count of keys (%ld)",(unsigned long)objects.count,(unsigned long)keys.count]; - [[SLCrashHandler defaultCrashHandler] catchCrashException:nil type:SLCrashErrorTypeDictionary errorDesc:errorInfo]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeDictionary errorDesc:errorInfo exception:nil callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; + return nil;//huicha } NSUInteger index = 0; @@ -40,7 +42,8 @@ - (id)sl_initWithObjects:(NSArray *)objects forKeys:(NSArray> *)ke index ++; }else{ NSString *errorInfo = [NSString stringWithFormat:@"异常:字典nil值 *** -[NSDictionary initWithObjects:forKeys]: attempt to insert nil object from objects[%d]",i]; - [[SLCrashHandler defaultCrashHandler] catchCrashException:nil type:SLCrashErrorTypeDictionary errorDesc:errorInfo]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeDictionary errorDesc:errorInfo exception:nil callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } } return [self sl_initWithObjects:[NSArray arrayWithObjects:objectsNew count:index] forKeys: [NSArray arrayWithObjects:keysNew count:index]]; @@ -58,7 +61,8 @@ - (id)sl_initWithObjects:(id _Nonnull const [])objects forKeys:(id index ++; }else{ NSString *errorInfo = [NSString stringWithFormat:@"异常:字典nil值 *** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[%d]",i]; - [[SLCrashHandler defaultCrashHandler] catchCrashException:nil type:SLCrashErrorTypeDictionary errorDesc:errorInfo]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeDictionary errorDesc:errorInfo exception:nil callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } } return [self sl_initWithObjects:objectsNew forKeys:keysNew count:index]; diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSMutableArray+SLCrashProtector.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSMutableArray+SLCrashProtector.m index 83d3712f..b0205aa5 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSMutableArray+SLCrashProtector.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSMutableArray+SLCrashProtector.m @@ -34,7 +34,8 @@ - (id)sl_mObjectAtIndex:(NSInteger)index { return [self sl_mObjectAtIndex:index]; } @catch (NSException *exception) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeMArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason]]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeMArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; return nil; } }else { @@ -50,7 +51,8 @@ - (id)sl_mObjectAtIndexedSubscript:(NSInteger)index { return [self sl_mObjectAtIndexedSubscript:index]; } @catch (NSException *exception) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeMArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason]]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeMArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; return nil; } } @@ -60,7 +62,8 @@ - (id)sl_mObjectAtIndexedSubscript:(NSInteger)index { - (void)sl_removeObjectsInRange:(NSRange)range { if (range.location+range.length>self.count) { NSString *errorInfo = [NSString stringWithFormat:@"异常:数组越界 *** -[__NSArrayM removeObjectsInRange:]: range {%ld, %ld} extends beyond bounds [0 .. %ld]",(unsigned long)range.location,(unsigned long)range.length,(unsigned long)self.count]; - [[SLCrashHandler defaultCrashHandler] catchCrashException:nil type:SLCrashErrorTypeMArray errorDesc:errorInfo]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeMArray errorDesc:errorInfo exception:nil callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; return; } [self sl_removeObjectsInRange:range]; @@ -68,7 +71,8 @@ - (void)sl_removeObjectsInRange:(NSRange)range { //越界 nil值 - (void)sl_replaceObjectAtIndex:(NSInteger)index withObject:(id)object { if (object == nil) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:nil type:SLCrashErrorTypeMArray errorDesc:@"异常:数组nil值 *** -[__NSArrayM replaceObjectAtIndex:withObject:]: object cannot be nil"]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeMArray errorDesc:@"异常:数组nil值 *** -[__NSArrayM replaceObjectAtIndex:withObject:]: object cannot be nil" exception:nil callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; return; } if (index >= self.count) { @@ -76,7 +80,8 @@ - (void)sl_replaceObjectAtIndex:(NSInteger)index withObject:(id)object { return [self sl_replaceObjectAtIndex:index withObject:object]; } @catch (NSException *exception) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeMArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason]]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeMArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } }else { [self sl_replaceObjectAtIndex:index withObject:object]; @@ -89,7 +94,8 @@ - (void)sl_replaceObjectsInRange:(NSRange)range withObjectsFromArray:(NSArray *) return [self sl_replaceObjectsInRange:range withObjectsFromArray:otherArray]; } @catch (NSException *exception) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeMArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason]]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeMArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } }else{ [self sl_replaceObjectsInRange:range withObjectsFromArray:otherArray]; @@ -99,7 +105,10 @@ - (void)sl_replaceObjectsInRange:(NSRange)range withObjectsFromArray:(NSArray *) //越界 nil值 - (void)sl_insertObject:(id)object atIndex:(NSInteger)index { if (object == nil) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:nil type:SLCrashErrorTypeMArray errorDesc:@"异常:数组nil值 *** -[__NSArrayM insertObject:atIndex:]: object cannot be nil"]; + + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeMArray errorDesc:@"异常:数组nil值 *** -[__NSArrayM insertObject:atIndex:]: object cannot be nil" exception:nil callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; + return; } if (index > self.count) { @@ -107,7 +116,8 @@ - (void)sl_insertObject:(id)object atIndex:(NSInteger)index { return [self sl_insertObject:object atIndex:index]; } @catch (NSException *exception) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeMArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason]]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeMArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } }else { [self sl_insertObject:object atIndex:index];; @@ -120,7 +130,8 @@ - (void)sl_insertObjects:(NSArray *)objects atIndexes:(NSIndexSet *)indexes { return [self sl_insertObjects:objects atIndexes:indexes]; } @catch (NSException *exception) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeMArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason]]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeMArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } return; } @@ -137,7 +148,8 @@ - (id)sl_initWithObjects:(id _Nonnull const [])objects count:(NSUInteger)cnt{ }else{ //记录错误 NSString *errorInfo = [NSString stringWithFormat:@"异常:数组nil值 *** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[%d]",i]; - [[SLCrashHandler defaultCrashHandler] catchCrashException:nil type:SLCrashErrorTypeMArray errorDesc:errorInfo]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeMArray errorDesc:errorInfo exception:nil callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } } return [self sl_initWithObjects:objectsNew count:index]; diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSMutableDictionary+SLCrashProtector.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSMutableDictionary+SLCrashProtector.m index b3663b51..8b9863c2 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSMutableDictionary+SLCrashProtector.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSMutableDictionary+SLCrashProtector.m @@ -29,7 +29,8 @@ - (void)sl_setObject:(id)anObject forKey:(id)aKey { [self sl_setObject:anObject forKey:aKey]; } @catch (NSException *exception) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeMDictionary errorDesc:[@"异常:字典nil值 " stringByAppendingString:exception.reason]]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeMDictionary errorDesc:[@"异常:字典nil值 " stringByAppendingString:exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } }else{ [self sl_setObject:anObject forKey:aKey]; @@ -42,7 +43,8 @@ - (void)sl_removeObjectForKey:(id)aKey { [self sl_removeObjectForKey:aKey]; } @catch (NSException *exception) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeMDictionary errorDesc:[@"异常:字典nil值 " stringByAppendingString:exception.reason]]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeMDictionary errorDesc:[@"异常:字典nil值 " stringByAppendingString:exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } }else{ [self sl_removeObjectForKey:aKey]; @@ -55,7 +57,8 @@ - (void)sl_setObject:(id)anObject forKeyedSubscript:(id)key { [self sl_setObject:anObject forKeyedSubscript:key]; } @catch (NSException *exception) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeMDictionary errorDesc:[@"异常:字典nil值 " stringByAppendingString:exception.reason]]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeMDictionary errorDesc:[@"异常:字典nil值 " stringByAppendingString:exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } }else{ [self sl_setObject:anObject forKeyedSubscript:key]; @@ -75,7 +78,8 @@ - (id)sl_initWithObjects:(id _Nonnull const [])objects forKeys:(id index ++; }else{ NSString *errorInfo = [NSString stringWithFormat:@"异常:字典nil值 *** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[%d]",i]; - [[SLCrashHandler defaultCrashHandler] catchCrashException:nil type:SLCrashErrorTypeMDictionary errorDesc:errorInfo]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeMDictionary errorDesc:errorInfo exception:nil callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } } return [self sl_initWithObjects:objectsNew forKeys:keysNew count:index]; diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSMutableString+SLCrashProtector.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSMutableString+SLCrashProtector.m index 0185bf9e..ecad62f6 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSMutableString+SLCrashProtector.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSMutableString+SLCrashProtector.m @@ -29,7 +29,8 @@ - (void)sl_insertString:(NSString *)aString atIndex:(NSUInteger)loc{ [self sl_insertString:aString atIndex:loc]; } @catch (NSException *exception) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeMString errorDesc:[@"异常:MutableString越界 " stringByAppendingString:exception.reason]]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeMString errorDesc:[@"异常:MutableString越界 " stringByAppendingString:exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } }else{ [self sl_insertString:aString atIndex:loc]; @@ -42,7 +43,8 @@ - (void)sl_deleteCharactersInRange:(NSRange)range{ [self sl_deleteCharactersInRange:range]; } @catch (NSException *exception) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeMString errorDesc:[@"异常:MutableString越界 " stringByAppendingString:exception.reason]]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeMString errorDesc:[@"异常:MutableString越界 " stringByAppendingString:exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } if (range.location < self.length) { [self sl_deleteCharactersInRange:NSMakeRange(range.location, self.length-range.location)]; diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSObject+SLCrashProtector.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSObject+SLCrashProtector.m index b0979e69..085cf2a9 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSObject+SLCrashProtector.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSObject+SLCrashProtector.m @@ -37,7 +37,8 @@ + (void)unrecognizedSelectorCrashProtector { - (id)sl_forwardingTargetForSelector:(SEL)aSelector { //判断当前类是否重写了消息转发的相关方法,如果重写了,就走正常的消息转发流程 if (![self isOverideForwardingMethods:[self class]] && !IsSystemClass(self.class)) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:nil type:SLCrashErrorTypeUnrecognizedSelector errorDesc:[NSString stringWithFormat:@"异常:未识别方法 [%@ +%@]",NSStringFromClass([self class]),NSStringFromSelector(aSelector)]]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeUnrecognizedSelector errorDesc:[NSString stringWithFormat:@"异常:未识别方法 [%@ +%@]",NSStringFromClass([self class]),NSStringFromSelector(aSelector)] exception:nil callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; //如果SLCrashHandler也没有实现aSelector,就动态添加上aSelector if (!class_getInstanceMethod([SLCrashHandler class], aSelector)) { class_addMethod([SLCrashHandler class], aSelector, (IMP)SL_DynamicAddMethodIMP, "v@:"); @@ -51,7 +52,8 @@ - (id)sl_forwardingTargetForSelector:(SEL)aSelector { + (id)sl_forwardingTargetForSelector:(SEL)aSelector { //判断当前类是否重写了消息转发的相关方法,如果重写了,就走正常的消息转发流程 if (![self isOverideForwardingMethods:[[self class] class]] && !IsSystemClass(self.class)) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:nil type:SLCrashErrorTypeUnrecognizedSelector errorDesc:[NSString stringWithFormat:@"异常:未识别方法 [%@ +%@]",NSStringFromClass([[self class] class]),NSStringFromSelector(aSelector)]]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeUnrecognizedSelector errorDesc:[NSString stringWithFormat:@"异常:未识别方法 [%@ +%@]",NSStringFromClass([self class]),NSStringFromSelector(aSelector)] exception:nil callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; //如果SLCrashHandler也没有实现aSelector,就动态添加上aSelector if (!class_getInstanceMethod([[SLCrashHandler class] class], aSelector)) { class_addMethod([[SLCrashHandler class] class], aSelector, (IMP)SL_DynamicAddMethodIMP, "v@:"); @@ -112,7 +114,9 @@ - (void)sl_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath optio NSString *className = (NSStringFromClass(self.class) == nil) ? @"" : NSStringFromClass(self.class); NSString *errorReason = [NSString stringWithFormat:@"异常 KVO: Repeated additions to the observer:%@ for the key path:'%@' from %@", observer, keyPath, className]; - [[SLCrashHandler defaultCrashHandler] catchCrashException:nil type:SLCrashErrorTypeKVO errorDesc:errorReason]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeKVO errorDesc:errorReason exception:nil callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; + } } else { [self sl_addObserver:observer forKeyPath:keyPath options:options context:context]; @@ -128,7 +132,8 @@ - (void)sl_removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath{ // 移除 KVO 信息操作失败:移除了未注册的观察者 NSString *className = NSStringFromClass(self.class) == nil ? @"" : NSStringFromClass(self.class); NSString *errorReason = [NSString stringWithFormat:@"异常 KVO: Cannot remove an observer %@ for the key path '%@' from %@ , because it is not registered as an observer", observer, keyPath, className]; - [[SLCrashHandler defaultCrashHandler] catchCrashException:nil type:SLCrashErrorTypeKVO errorDesc:errorReason]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeKVO errorDesc:errorReason exception:nil callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } } else { [self sl_removeObserver:observer forKeyPath:keyPath]; @@ -144,7 +149,8 @@ - (void)sl_removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath co // 移除 KVO 信息操作失败:移除了未注册的观察者 NSString *className = NSStringFromClass(self.class) == nil ? @"" : NSStringFromClass(self.class); NSString *errorReason = [NSString stringWithFormat:@"异常 KVO: Cannot remove an observer %@ for the key path '%@' from %@ , because it is not registered as an observer", observer, keyPath, className]; - [[SLCrashHandler defaultCrashHandler] catchCrashException:nil type:SLCrashErrorTypeKVO errorDesc:errorReason]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeKVO errorDesc:errorReason exception:nil callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } } else { [self sl_removeObserver:observer forKeyPath:keyPath context:context]; @@ -160,7 +166,8 @@ - (void)sl_KVODealloc{ // 被观察者在 dealloc 时仍然注册着 KVO if (keyPaths.count > 0) { NSString *errorReason = [NSString stringWithFormat:@"异常 KVO: An instance %@ was deallocated while key value observers were still registered with it. The Keypaths is:'%@'", self, [keyPaths componentsJoinedByString:@","]]; - [[SLCrashHandler defaultCrashHandler] catchCrashException:nil type:SLCrashErrorTypeKVO errorDesc:errorReason]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeKVO errorDesc:errorReason exception:nil callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } // 移除多余的观察者 for (NSString *keyPath in keyPaths) { @@ -199,7 +206,9 @@ - (void)sl_setValue:(id)value forKey:(NSString *)key { [self sl_setValue:value forKey:key]; } @catch (NSException *exception) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeKVC errorDesc:[@"异常 KVC: " stringByAppendingString:exception.reason]]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeKVC errorDesc:[@"异常 KVC: " stringByAppendingString:exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; + } return; } @@ -207,15 +216,18 @@ - (void)sl_setValue:(id)value forKey:(NSString *)key { } - (void)setNilValueForKey:(NSString *)key { NSString *crashMessages = [NSString stringWithFormat:@"异常 KVC: [<%@ %p> setNilValueForKey]: could not set nil as the value for the key %@.",NSStringFromClass([self class]),self,key]; - [[SLCrashHandler defaultCrashHandler] catchCrashException:nil type:SLCrashErrorTypeKVC errorDesc:crashMessages]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeKVC errorDesc:crashMessages exception:nil callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } - (void)setValue:(id)value forUndefinedKey:(NSString *)key { NSString *crashMessages = [NSString stringWithFormat:@"异常 KVC: [<%@ %p> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key: %@,value:%@'",NSStringFromClass([self class]),self,key,value]; - [[SLCrashHandler defaultCrashHandler] catchCrashException:nil type:SLCrashErrorTypeKVC errorDesc:crashMessages]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeKVC errorDesc:crashMessages exception:nil callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } - (nullable id)valueForUndefinedKey:(NSString *)key { NSString *crashMessages = [NSString stringWithFormat:@"异常 KVC: [<%@ %p> valueForUndefinedKey:]: this class is not key value coding-compliant for the key: %@",NSStringFromClass([self class]),self,key]; - [[SLCrashHandler defaultCrashHandler] catchCrashException:nil type:SLCrashErrorTypeKVC errorDesc:crashMessages]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeKVC errorDesc:crashMessages exception:nil callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; return self; } diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSObject+SLMLeakFinder.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSObject+SLMLeakFinder.m index b6dfcbe4..52454ad0 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSObject+SLMLeakFinder.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSObject+SLMLeakFinder.m @@ -37,7 +37,8 @@ - (void)notDealloc { NSString *desc = [NSString stringWithFormat:@"内存泄漏/循环引用:如果%@不应该被释放, 请重写[%@ -willDealloc] 并 returning NO .\n", className, className]; NSLog(@"%@",desc); NSException *exception = [NSException exceptionWithName:NSInternalInconsistencyException reason:desc userInfo:nil]; - [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeLeak errorDesc:desc]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeLeak errorDesc:desc exception:exception callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } //不需要监测内存泄漏的白名单类 diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSString+SLCrashProtector.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSString+SLCrashProtector.m index 5adf7d10..0faab0c4 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSString+SLCrashProtector.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSString+SLCrashProtector.m @@ -31,7 +31,8 @@ - (unichar)sl_characterAtIndex:(NSUInteger)index{ [self sl_characterAtIndex:index]; } @catch (NSException *exception) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeString errorDesc:[@"异常:String越界 " stringByAppendingString:exception.reason]]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeString errorDesc:[@"异常:String越界 " stringByAppendingString:exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } return 0; } @@ -44,8 +45,8 @@ - (NSString *)sl_substringFromIndex:(NSUInteger)from{ instance = [self sl_substringFromIndex:from]; } @catch (NSException *exception) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeString errorDesc:[@"异常:String越界 " stringByAppendingString:exception.reason]]; - + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeString errorDesc:[@"异常:String越界 " stringByAppendingString:exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } @finally { return instance; @@ -58,8 +59,8 @@ - (NSString *)sl_substringToIndex:(NSUInteger)to{ instance = [self sl_substringToIndex:to]; } @catch (NSException *exception) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeString errorDesc:[@"异常:String越界 " stringByAppendingString:exception.reason]]; - + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeString errorDesc:[@"异常:String越界 " stringByAppendingString:exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } @finally { return instance; @@ -72,8 +73,8 @@ - (NSString *)sl_substringWithRange:(NSRange)range{ instance = [self sl_substringWithRange:range]; } @catch (NSException *exception) { - [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeString errorDesc:[@"异常:String越界 " stringByAppendingString:exception.reason]]; - + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeString errorDesc:[@"异常:String越界 " stringByAppendingString:exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } @finally { return instance; diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h index f8c3fc1d..166e4c25 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h @@ -45,20 +45,26 @@ typedef NS_ENUM(NSInteger, SLCrashErrorType) { @property (nonatomic, strong) NSException *exception; /// 当前线程的函数调用栈 @property (nonatomic, copy) NSArray *callStackSymbol; +///初始化 ++ (instancetype)errorWithErrorType:(SLCrashErrorType)errorType errorDesc:(NSString *)errorDesc exception:(nullable NSException *)exception callStack:(NSArray*)callStackSymbol; +@end + +@class SLCrashHandler; +@protocol SLCrashHandlerDelegate +///捕获到错误信息,交给外界delegate处理 +- (void)crashHandlerDidOutputCrashError:(SLCrashError *)crashError; @end /// 崩溃处理程序 @interface SLCrashHandler : NSObject -/// 异常捕获回调 提供给外界初始化实现自定义处理 ,日志上报等(注意线程安全和循环引用) -@property (nonatomic, copy) void(^crashHandlerBlock)(SLCrashError *crashError); + +///异常捕获回调 提供给外界实现自定义处理 ,日志上报等(注意线程安全) +@property (nonatomic, weak) iddelegate; /// 单例 + (instancetype)defaultCrashHandler; -/// 捕获崩溃异常信息 Private -- (void)catchCrashException:(NSException * _Nullable )exception type:(SLCrashErrorType)errorType errorDesc:(NSString *)errorDesc; - @end NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m index e366d975..23592c40 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m @@ -9,6 +9,15 @@ #import "SLCrashHandler.h" @implementation SLCrashError ++ (instancetype)errorWithErrorType:(SLCrashErrorType)errorType errorDesc:(NSString *)errorDesc exception:(NSException *)exception callStack:(NSArray*)callStackSymbol { + SLCrashError *crashError = [SLCrashError new]; + crashError.errorDesc = errorDesc; + crashError.errorType = errorType; + crashError.exception = exception; + //获取当前线程的函数调用栈 + crashError.callStackSymbol = callStackSymbol; + return crashError; +} @end @implementation SLCrashHandler @@ -22,19 +31,4 @@ + (instancetype)defaultCrashHandler { return crashHandler; } -/// 捕获崩溃异常 -- (void)catchCrashException:(NSException *)exception type:(SLCrashErrorType)errorType errorDesc:(NSString *)errorDesc { - SLCrashError *crashError = [SLCrashError new]; - crashError.errorDesc = errorDesc; - crashError.errorType = errorType; - crashError.exception = exception; - //获取当前线程的函数调用栈 - crashError.callStackSymbol = [NSThread callStackSymbols]; -// NSLog(@"%@" ,errorDesc); - if (self.crashHandlerBlock) { - self.crashHandlerBlock(crashError); - } -} - - @end diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLKVODelegate.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLKVODelegate.m index 332a5ed5..e731a827 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLKVODelegate.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLKVODelegate.m @@ -111,7 +111,8 @@ - (void)observeValueForKeyPath:(NSString *)keyPath [observer observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } @catch (NSException *exception) { NSString *reason = [NSString stringWithFormat:@"异常 KVO: %@",[exception description]]; - [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeArray errorDesc:reason]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeKVO errorDesc:reason exception:nil callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } } } diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieCatcher.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieCatcher.m index 6ae21b40..ab077688 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieCatcher.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieCatcher.m @@ -124,7 +124,8 @@ - (NSString *)description - (void)_throwMessageSentExceptionWithSelector: (SEL)selector { NSException *exception = [NSException exceptionWithName:NSInternalInconsistencyException reason:[NSString stringWithFormat:@"( 野指针必现定位:-[%@ %@]) was sent to a zombie object at address: %p", NSStringFromClass(self.originClass), NSStringFromSelector(selector), self] userInfo:nil]; - [[SLCrashHandler defaultCrashHandler] catchCrashException:exception type:SLCrashErrorTypeZombie errorDesc:exception.reason]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeZombie errorDesc:exception.reason exception:exception callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; //是否需要强制抛出异常 // @throw exception; } diff --git a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m index babd8cc2..33163dfa 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m @@ -10,7 +10,7 @@ #import "SLCrashProtector.h" #import "BSBacktraceLogger.h" -@interface SLCrashViewController () +@interface SLCrashViewController () @property (nonatomic, strong) UITextView *textView; @@ -81,13 +81,17 @@ - (void)setupUI { } self.textView = [[UITextView alloc] initWithFrame:CGRectMake(0, SL_TopNavigationBarHeight+ i/4*size.height, self.view.sl_width, self.view.sl_height - (SL_TopNavigationBarHeight+ i/4*size.height))]; self.textView.editable = NO; + self.textView.text = @"点击上方测试内容按钮,在此输出异常捕获结果..."; [self.view addSubview:self.textView]; - - SL_WeakSelf; - [SLCrashHandler defaultCrashHandler].crashHandlerBlock = ^(SLCrashError * _Nonnull crashError) { - weakSelf.textView.text = [NSString stringWithFormat:@" 错误描述:%@ \n 调用栈:%@" ,crashError.errorDesc, crashError.callStackSymbol]; - }; + [SLCrashHandler defaultCrashHandler].delegate = self; +} + +#pragma mark - SLCrashHandlerDelegate +///异常捕获回调 提供给外界实现自定义处理 ,日志上报等(注意线程安全) +- (void)crashHandlerDidOutputCrashError:(SLCrashError *)crashError { + [self.textView scrollsToTop]; + self.textView.text = [NSString stringWithFormat:@" 错误描述:%@ \n 调用栈:%@" ,crashError.errorDesc, crashError.callStackSymbol]; } #pragma mark - Container Crash From 894f83fc603c1be58fe65371c17d2e90df2b1219 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 16 Jul 2020 19:46:16 +0800 Subject: [PATCH 062/356] =?UTF-8?q?iOS=20Crash=E9=98=B2=E6=8A=A4=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashProtector.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashProtector.h b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashProtector.h index d23bf45a..2e9a448a 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashProtector.h +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashProtector.h @@ -23,7 +23,7 @@ static inline void SL_ExchangeInstanceMethod(Class _originalClass ,SEL _original BOOL didAddMethod = class_addMethod(_originalClass, _originalSel, method_getImplementation(methodNew), method_getTypeEncoding(methodNew)); if (didAddMethod) { // 进行方法的替换 - class_replaceMethod(_originalClass, _targetSel, method_getImplementation(methodOriginal), method_getTypeEncoding(methodOriginal)); + class_replaceMethod(_targetClass, _targetSel, method_getImplementation(methodOriginal), method_getTypeEncoding(methodOriginal)); }else{ // 交换 IMP 指针 method_exchangeImplementations(methodOriginal, methodNew); From 5b2c0bf6fc73d36892e3960784d0f4694ecfb429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Fri, 17 Jul 2020 11:26:39 +0800 Subject: [PATCH 063/356] Update README.md --- README.md | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 5b0db3f5..52784ffe 100644 --- a/README.md +++ b/README.md @@ -149,16 +149,11 @@ avCaptureTool.videoSize = CGSizeMake(self.view.width * 0.8, self.view.height * 0 -## Welcome To Follow Me - -> 您的follow和start,是我前进的动力,Thanks♪(・ω・)ノ -> * [简书](https://www.jianshu.com/u/e15d1f644bea) -> * [微博](https://weibo.com/5732733120/profile?rightmod=1&wvr=6&mod=personinfo&is_all=1) -> * [掘金](https://juejin.im/user/5c00d97b6fb9a049fb436288) -> * [CSDN](https://blog.csdn.net/wsl2ls) -> * QQ交流群:835303405 -> * 微信公众号:iOS2679114653 -> * 微信号:w2679114653(备注来意) +#### Welcome to you 👏 您的follow和start,是我前进的动力,Thanks♪(・ω・)ノ 🤝 + +| [简书 ](https://www.jianshu.com/u/e15d1f644bea) | [掘金](https://juejin.im/user/5c00d97b6fb9a049fb436288) | QQ交流群 | 微信公众号 | 微信号 | +| ---- | ---- | ---- | ---- | ---- | +| [CSDN](https://blog.csdn.net/wsl2ls) | [微博](https://weibo.com/5732733120/profile?rightmod=1&wvr=6&mod=personinfo&is_all=1) | [835303405](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/QQ交流群.png) | [iOS2679114653](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/微信公众号.png) | w2679114653 | ![QQ交流群: 835303405](QQ交流群.png) From 9e04f45e921a6758870b6bc55b3f189ee4f6046e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Fri, 17 Jul 2020 11:36:49 +0800 Subject: [PATCH 064/356] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 52784ffe..a9e58e81 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git 掘金:https://juejin.im/user/5c00d97b6fb9a049fb436288 ### 目录 -> 1、暗黑模式 +> 1、[暗黑模式](#问题说明) > 2、AppleID登录应用 > 3、AVFoundation相关 >> 3.1、AVFoundation 高仿微信相机拍摄和编辑 From 941112298a3d175842c90dbecead2f5c6bd8c31b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Fri, 17 Jul 2020 11:39:09 +0800 Subject: [PATCH 065/356] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a9e58e81..0b9a04db 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git 掘金:https://juejin.im/user/5c00d97b6fb9a049fb436288 ### 目录 -> 1、[暗黑模式](#问题说明) +> 1、[暗黑模式](#暗黑模式适配) > 2、AppleID登录应用 > 3、AVFoundation相关 >> 3.1、AVFoundation 高仿微信相机拍摄和编辑 @@ -39,7 +39,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git > 问题说明 -## 1、 暗黑模式适配 +## 暗黑模式适配 ![暗黑模式](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/暗黑模式.gif) From 397ffdb2ed34e3460ee5f792729bd479cdff1dc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Fri, 17 Jul 2020 11:39:41 +0800 Subject: [PATCH 066/356] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0b9a04db..bb0c2cc2 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git 掘金:https://juejin.im/user/5c00d97b6fb9a049fb436288 ### 目录 -> 1、[暗黑模式](#暗黑模式适配) +> 1、[暗黑模式](#1.暗黑模式适配) > 2、AppleID登录应用 > 3、AVFoundation相关 >> 3.1、AVFoundation 高仿微信相机拍摄和编辑 @@ -39,7 +39,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git > 问题说明 -## 暗黑模式适配 +## 1.暗黑模式适配 ![暗黑模式](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/暗黑模式.gif) From a957efd9f6658580344237627f3138cff87fb7fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Fri, 17 Jul 2020 11:41:11 +0800 Subject: [PATCH 067/356] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bb0c2cc2..71baad45 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git 掘金:https://juejin.im/user/5c00d97b6fb9a049fb436288 ### 目录 -> 1、[暗黑模式](#1.暗黑模式适配) +> 1、[暗黑模式](#1暗黑模式适配) > 2、AppleID登录应用 > 3、AVFoundation相关 >> 3.1、AVFoundation 高仿微信相机拍摄和编辑 @@ -39,7 +39,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git > 问题说明 -## 1.暗黑模式适配 +## 1暗黑模式适配 ![暗黑模式](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/暗黑模式.gif) From a382a96828dc8bc93a533da9fbf3dd78e06b8c89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Fri, 17 Jul 2020 11:41:56 +0800 Subject: [PATCH 068/356] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 71baad45..76bb649a 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git 掘金:https://juejin.im/user/5c00d97b6fb9a049fb436288 ### 目录 -> 1、[暗黑模式](#1暗黑模式适配) +> 1、[暗黑模式](#1、暗黑模式适配) > 2、AppleID登录应用 > 3、AVFoundation相关 >> 3.1、AVFoundation 高仿微信相机拍摄和编辑 @@ -39,7 +39,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git > 问题说明 -## 1暗黑模式适配 +## 1、暗黑模式适配 ![暗黑模式](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/暗黑模式.gif) From 7ade7474234d3baf70487ba27777516f484320bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Fri, 17 Jul 2020 11:42:44 +0800 Subject: [PATCH 069/356] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 76bb649a..f6cc9f6b 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git 掘金:https://juejin.im/user/5c00d97b6fb9a049fb436288 ### 目录 -> 1、[暗黑模式](#1、暗黑模式适配) +> 1、[暗黑模式](#1-暗黑模式适配) > 2、AppleID登录应用 > 3、AVFoundation相关 >> 3.1、AVFoundation 高仿微信相机拍摄和编辑 @@ -39,7 +39,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git > 问题说明 -## 1、暗黑模式适配 +## 1-暗黑模式适配 ![暗黑模式](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/暗黑模式.gif) From 61be7d8377cb34b3200ce387707d838e34a329da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Fri, 17 Jul 2020 11:52:13 +0800 Subject: [PATCH 070/356] Update README.md --- README.md | 92 +++++++++++++++++++++++++++---------------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index f6cc9f6b..f9dfe6d3 100644 --- a/README.md +++ b/README.md @@ -5,30 +5,30 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git ### 目录 > 1、[暗黑模式](#1-暗黑模式适配) -> 2、AppleID登录应用 -> 3、AVFoundation相关 ->> 3.1、AVFoundation 高仿微信相机拍摄和编辑 ->> 3.2、AVFoundation 人脸检测 ->> 3.3、AVFoundation 实时滤镜 ->> 3.4、GPUImage框架的使用 ->> 3.5、VideoToolBox和AudioToolBox音视频编解码 ->> 3.6、AVFoundation 利用摄像头实时识别物体颜色 ->> 3.7、AVFoundation 原生二维码扫描识别和生成 - -> 4、OpenGL ES学习 -> 5、LeetCode算法练习 -> 6、工作中踩过的坑 ->> 6.1、键盘和UIMenuController不能同时存在的问题 ->> 6.2、全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突 ->> 6.3、UITableView/UICollectionView获取特定位置的cell ->> 6.4、UIScrollView视觉差动画 ->> 6.5、iOS 传感器集锦 ->> 6.6、iOS 自定义转场动画 ->> 6.7、二进制重排优化启动速度 ->> 6.8、iOS APM应用性能监控管理(doing) - -> 7、iOS Crash防护 -> 8、WKWebView相关 +> 2、[AppleID登录应用](#2-AppleID登录应用) +> 3、AVFoundation相关(#3-AVFoundation相关) +>> 3.1、AVFoundation 高仿微信相机拍摄和编辑(#3.1-AVFoundation 高仿微信相机拍摄和编辑) +>> 3.2、[AVFoundation 人脸检测](#3.2-AVFoundation 人脸检测) +>> 3.3、[AVFoundation 实时滤镜](#3.3-AVFoundation 实时滤镜) +>> 3.4、[GPUImage框架的使用](#3.4-GPUImage框架的使用) +>> 3.5、[VideoToolBox和AudioToolBox音视频编解码](#3.5-VideoToolBox和AudioToolBox音视频编解码) +>> 3.6、[AVFoundation 利用摄像头实时识别物体颜色](#3.6-AVFoundation 利用摄像头实时识别物体颜色) +>> 3.7、[AVFoundation 原生二维码扫描识别和生成](#3.7-AVFoundation 原生二维码扫描识别和生成) + +> 4、[OpenGL ES学习](#4-OpenGL ES学习) +> 5、[LeetCode算法练习](#5-LeetCode算法练习) +> 6、[工作中踩过的坑](#6-工作中踩过的坑) +>> 6.1、[键盘和UIMenuController不能同时存在的问题](#6.1-键盘和UIMenuController不能同时存在的问题]) +>> 6.2、[全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突](#6.2-全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突) +>> 6.3、[UITableView/UICollectionView获取特定位置的cell](#6.3-UITableView/UICollectionView获取特定位置的cell) +>> 6.4、[UIScrollView视觉差动画](#6.4-UIScrollView视觉差动画) +>> 6.5、[iOS 传感器集锦](#6.5-iOS 传感器集锦) +>> 6.6、[iOS 自定义转场动画](#6.6-iOS 自定义转场动画) +>> 6.7、[二进制重排优化启动速度](#6.7-二进制重排优化启动速度) +>> 6.8、[iOS APM应用性能监控管理(doing)](#6.8-iOS APM应用性能监控管理) + +> 7、[iOS Crash防护](#7-iOS Crash防护) +> 8、[WKWebView相关](#8-WKWebView相关) >> 8.1、WKWebView的使用 >> 8.2、WKWebView+UITableView混排 >> 8.3、WKWebView离线缓存功能 @@ -43,13 +43,13 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git ![暗黑模式](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/暗黑模式.gif) -## 2、AppleID登录应用 +## 2-AppleID登录应用 * 查看本仓库下的AddingTheSignInWithAppleFlowToYourApp -## 3、AVFoundation相关 +## 3-AVFoundation相关 -#### 3.1、[微信相机拍摄照片、小视频以及编辑功能](https://www.jianshu.com/p/a2a04cabb98d) +#### 3.1-[微信相机拍摄照片、小视频以及编辑功能](https://www.jianshu.com/p/a2a04cabb98d) > 效果描述: > * 1、自定义相机 拍摄视频和照片 > * 2、切换前后摄像头、调整焦距/设置聚焦点、横屏拍摄 @@ -69,17 +69,17 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git |![图片编辑](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/3、小视频7.gif)|![图片裁剪](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/3、小视频8.gif)| -#### 3.2、[人脸检测](https://www.jianshu.com/p/f236dc161a90) +#### 3.2-[人脸检测](https://www.jianshu.com/p/f236dc161a90) ![人脸识别](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/4、人脸识别.gif) -#### 3.3、[实时滤镜拍摄和导出](https://www.jianshu.com/p/f236dc161a90) +#### 3.3-[实时滤镜拍摄和导出](https://www.jianshu.com/p/f236dc161a90) > 主要类: 是由SLAvCaptureTool拆分的 SLAvCaptureSession(采集) + SLAvWriterInput(录制) 两个工具类,方便扩展,录制写入实现的方式也略有不同 ![人脸识别](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/5、实时滤镜拍摄.gif) -#### 3.4、[GPUImage框架的使用](https://www.jianshu.com/p/97740cd381f7) +#### 3.4-[GPUImage框架的使用](https://www.jianshu.com/p/97740cd381f7) > 效果描述:实时拍摄添加水印和滤镜、本地视频添加水印、GIF图水印 @@ -87,21 +87,21 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git ![GPUImage框架的使用](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/6、GPUImage.gif) -#### 3.5、VideoToolBox和AudioToolBox音视频编解码 +#### 3.5-VideoToolBox和AudioToolBox音视频编解码 > 请查看本仓库下的 VideoEncoder&Decoder 文件 ![音视频编码](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/7、音视频编码.gif) -#### 3.6、AVFoundation 利用摄像头实时识别物体颜色 +#### 3.6-AVFoundation 利用摄像头实时识别物体颜色 ![音视频编码](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/3.6、拾色器.gif) -#### 3.7、[AVFoundation 原生二维码扫描识别和生成](https://juejin.im/post/5c0e1db651882539c60d0434) +#### 3.7-[AVFoundation 原生二维码扫描识别和生成](https://juejin.im/post/5c0e1db651882539c60d0434) > 该代码地址在:https://github.com/wsl2ls/ScanQRcode -## 4、[OpenGL ES学习](https://www.jianshu.com/p/9259689cac06) +## 4-[OpenGL ES学习](https://www.jianshu.com/p/9259689cac06) > 示例描述: > * 1、GLKit 绘制图片和正方体 @@ -111,31 +111,31 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git |![OpenGLES学习.gif](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/8、OpenGLES学习1.gif)|![OpenGLES学习](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/8、OpenGLES学习2.gif)|![OpenGLES学习](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/8、OpenGLES学习3.gif)| -## 5、[LeetCode算法练习](https://github.com/wsl2ls/AlgorithmSet.git) +## 5-[LeetCode算法练习](https://github.com/wsl2ls/AlgorithmSet.git) > [LeetCode算法练习集合(Swift版) ~ 每天一道算法题](https://github.com/wsl2ls/AlgorithmSet.git) -## 6、工作中踩过的坑 +## 6-工作中踩过的坑 -#### 6.1、[键盘和UIMenuController的并存问题](https://www.jianshu.com/p/ed1b57c4ecea) +#### 6.1-[键盘和UIMenuController的并存问题](https://www.jianshu.com/p/ed1b57c4ecea) | ![问题描述.gif](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/10、键盘和UIMenuController不能同时出现的问题描述.gif) | ![并存问题解决](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/10、键盘和UIMenuController并存问题解决.gif) | -#### 6.2、[全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突](https://juejin.im/post/5c0e1e73f265da616413d828) -#### 6.3、[UITableView/UICollectionView获取特定位置的cell](https://juejin.im/post/5c0e1df95188250d2722a3bc) -#### 6.4、[UIScrollView视觉差动画](https://juejin.im/post/5c088b45f265da610e7fe156) -#### 6.5、[iOS 传感器集锦](https://juejin.im/post/5c088a1051882517165dd15d) -#### 6.6、[iOS 自定义转场动画](https://juejin.im/post/5c088ba36fb9a049fb43737b) -#### 6.7、[二进制重排优化启动速度](https://juejin.im/post/5ea79839f265da7bba509590) -#### 6.8、[iOS APM应用性能监控管理(doing)]() +#### 6.2-[全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突](https://juejin.im/post/5c0e1e73f265da616413d828) +#### 6.3-[UITableView/UICollectionView获取特定位置的cell](https://juejin.im/post/5c0e1df95188250d2722a3bc) +#### 6.4-[UIScrollView视觉差动画](https://juejin.im/post/5c088b45f265da610e7fe156) +#### 6.5-[iOS 传感器集锦](https://juejin.im/post/5c088a1051882517165dd15d) +#### 6.6-[iOS 自定义转场动画](https://juejin.im/post/5c088ba36fb9a049fb43737b) +#### 6.7-[二进制重排优化启动速度](https://juejin.im/post/5ea79839f265da7bba509590) +#### 6.8-[iOS APM应用性能监控管理(doing)]() > CPU占用率、内存/磁盘使用率、卡顿监控定位 ...... -## 7、iOS Crash防护 +## 7-iOS Crash防护 > Crash防护内容涉及 NSArray/NSMutableArray、NSDictionary/NSMutableDictionary、NSString/NSMutableString、Unrecognized Selector、KVO、KVC 、野指针定位、内存泄漏/循环引用;主要是对常见易错的地方进行容错处理,避免崩溃,并保存出错时的函数调用栈,以方便快速定位代码,主要是利用的runtime和fishook知识。 -## 8、[WKWebView相关](https://juejin.im/post/5ed999fd51882542f9389949) +## 8-[WKWebView相关](https://juejin.im/post/5ed999fd51882542f9389949) > [WKWebView的使用](https://juejin.im/post/5c0e1e2ae51d451d971743a1)、[WKWebView+UITableView混排](https://juejin.im/post/5ed999fd51882542f9389949)、WKWebView离线缓存功能、HTML非文本元素替换为原生组件展示、UIScrollView实现原理、UITableView的实现原理 From c12af3d823df26fb4a5901c6c0632b7ea44fb730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Fri, 17 Jul 2020 11:54:17 +0800 Subject: [PATCH 071/356] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f9dfe6d3..20c88f85 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git ### 目录 > 1、[暗黑模式](#1-暗黑模式适配) > 2、[AppleID登录应用](#2-AppleID登录应用) -> 3、AVFoundation相关(#3-AVFoundation相关) +> 3、[AVFoundation相关](#3-AVFoundation相关) >> 3.1、AVFoundation 高仿微信相机拍摄和编辑(#3.1-AVFoundation 高仿微信相机拍摄和编辑) >> 3.2、[AVFoundation 人脸检测](#3.2-AVFoundation 人脸检测) >> 3.3、[AVFoundation 实时滤镜](#3.3-AVFoundation 实时滤镜) From 1cf0dd5dd6e1e9fb0a7ad3d9cb02e1c4517c40fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Fri, 17 Jul 2020 11:57:15 +0800 Subject: [PATCH 072/356] Update README.md --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 20c88f85..45c61e0c 100644 --- a/README.md +++ b/README.md @@ -7,13 +7,13 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git > 1、[暗黑模式](#1-暗黑模式适配) > 2、[AppleID登录应用](#2-AppleID登录应用) > 3、[AVFoundation相关](#3-AVFoundation相关) ->> 3.1、AVFoundation 高仿微信相机拍摄和编辑(#3.1-AVFoundation 高仿微信相机拍摄和编辑) ->> 3.2、[AVFoundation 人脸检测](#3.2-AVFoundation 人脸检测) ->> 3.3、[AVFoundation 实时滤镜](#3.3-AVFoundation 实时滤镜) ->> 3.4、[GPUImage框架的使用](#3.4-GPUImage框架的使用) ->> 3.5、[VideoToolBox和AudioToolBox音视频编解码](#3.5-VideoToolBox和AudioToolBox音视频编解码) ->> 3.6、[AVFoundation 利用摄像头实时识别物体颜色](#3.6-AVFoundation 利用摄像头实时识别物体颜色) ->> 3.7、[AVFoundation 原生二维码扫描识别和生成](#3.7-AVFoundation 原生二维码扫描识别和生成) +>> 3.1、AVFoundation 高仿微信相机拍摄和编辑 +>> 3.2、AVFoundation 人脸检测 +>> 3.3、AVFoundation 实时滤镜 +>> 3.4、GPUImage框架的使用 +>> 3.5、VideoToolBox和AudioToolBox音视频编解码 +>> 3.6、AVFoundation 利用摄像头实时识别物体颜色 +>> 3.7、AVFoundation 原生二维码扫描识别和生成 > 4、[OpenGL ES学习](#4-OpenGL ES学习) > 5、[LeetCode算法练习](#5-LeetCode算法练习) From 9dd5569d8c4bce06a7cf488270e6e3e10222b76d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Fri, 17 Jul 2020 13:33:48 +0800 Subject: [PATCH 073/356] Update README.md --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 45c61e0c..c6fff3d0 100644 --- a/README.md +++ b/README.md @@ -18,14 +18,14 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git > 4、[OpenGL ES学习](#4-OpenGL ES学习) > 5、[LeetCode算法练习](#5-LeetCode算法练习) > 6、[工作中踩过的坑](#6-工作中踩过的坑) ->> 6.1、[键盘和UIMenuController不能同时存在的问题](#6.1-键盘和UIMenuController不能同时存在的问题]) ->> 6.2、[全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突](#6.2-全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突) ->> 6.3、[UITableView/UICollectionView获取特定位置的cell](#6.3-UITableView/UICollectionView获取特定位置的cell) ->> 6.4、[UIScrollView视觉差动画](#6.4-UIScrollView视觉差动画) ->> 6.5、[iOS 传感器集锦](#6.5-iOS 传感器集锦) ->> 6.6、[iOS 自定义转场动画](#6.6-iOS 自定义转场动画) ->> 6.7、[二进制重排优化启动速度](#6.7-二进制重排优化启动速度) ->> 6.8、[iOS APM应用性能监控管理(doing)](#6.8-iOS APM应用性能监控管理) +>> 6.1、键盘和UIMenuController不能同时存在的问题 +>> 6.2、全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突] +>> 6.3、UITableView/UICollectionView获取特定位置的cell +>> 6.4、UIScrollView视觉差动画](#6.4-UIScrollView视觉差动画) +>> 6.5、iOS 传感器集锦 +>> 6.6、iOS 自定义转场动画 +>> 6.7、二进制重排优化启动速度 +>> 6.8、iOS APM应用性能监控管理(doing) > 7、[iOS Crash防护](#7-iOS Crash防护) > 8、[WKWebView相关](#8-WKWebView相关) @@ -101,7 +101,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git > 该代码地址在:https://github.com/wsl2ls/ScanQRcode -## 4-[OpenGL ES学习](https://www.jianshu.com/p/9259689cac06) +## 4-OpenGL ES学习 > 示例描述: > * 1、GLKit 绘制图片和正方体 @@ -111,7 +111,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git |![OpenGLES学习.gif](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/8、OpenGLES学习1.gif)|![OpenGLES学习](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/8、OpenGLES学习2.gif)|![OpenGLES学习](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/8、OpenGLES学习3.gif)| -## 5-[LeetCode算法练习](https://github.com/wsl2ls/AlgorithmSet.git) +## 5-LeetCode算法练习 > [LeetCode算法练习集合(Swift版) ~ 每天一道算法题](https://github.com/wsl2ls/AlgorithmSet.git) From 208b2ab4e41c04fde2b37218f951a58d821001c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Fri, 17 Jul 2020 13:35:13 +0800 Subject: [PATCH 074/356] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c6fff3d0..e488f9a4 100644 --- a/README.md +++ b/README.md @@ -135,7 +135,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git > Crash防护内容涉及 NSArray/NSMutableArray、NSDictionary/NSMutableDictionary、NSString/NSMutableString、Unrecognized Selector、KVO、KVC 、野指针定位、内存泄漏/循环引用;主要是对常见易错的地方进行容错处理,避免崩溃,并保存出错时的函数调用栈,以方便快速定位代码,主要是利用的runtime和fishook知识。 -## 8-[WKWebView相关](https://juejin.im/post/5ed999fd51882542f9389949) +## 8-WKWebView相关 > [WKWebView的使用](https://juejin.im/post/5c0e1e2ae51d451d971743a1)、[WKWebView+UITableView混排](https://juejin.im/post/5ed999fd51882542f9389949)、WKWebView离线缓存功能、HTML非文本元素替换为原生组件展示、UIScrollView实现原理、UITableView的实现原理 From 08bb020956d73993106f8ea414766a415fba4bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Fri, 17 Jul 2020 13:37:34 +0800 Subject: [PATCH 075/356] Update README.md --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e488f9a4..c841afee 100644 --- a/README.md +++ b/README.md @@ -10,21 +10,21 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git >> 3.1、AVFoundation 高仿微信相机拍摄和编辑 >> 3.2、AVFoundation 人脸检测 >> 3.3、AVFoundation 实时滤镜 ->> 3.4、GPUImage框架的使用 +>> 3.4、GPUImage框架的使用 >> 3.5、VideoToolBox和AudioToolBox音视频编解码 ->> 3.6、AVFoundation 利用摄像头实时识别物体颜色 +>> 3.6、AVFoundation 利用摄像头实时识别物体颜色 >> 3.7、AVFoundation 原生二维码扫描识别和生成 > 4、[OpenGL ES学习](#4-OpenGL ES学习) > 5、[LeetCode算法练习](#5-LeetCode算法练习) > 6、[工作中踩过的坑](#6-工作中踩过的坑) ->> 6.1、键盘和UIMenuController不能同时存在的问题 +>> 6.1、键盘和UIMenuController不能同时存在的问题 >> 6.2、全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突] >> 6.3、UITableView/UICollectionView获取特定位置的cell >> 6.4、UIScrollView视觉差动画](#6.4-UIScrollView视觉差动画) ->> 6.5、iOS 传感器集锦 ->> 6.6、iOS 自定义转场动画 ->> 6.7、二进制重排优化启动速度 +>> 6.5、iOS 传感器集锦 +>> 6.6、iOS 自定义转场动画 +>> 6.7、二进制重排优化启动速度 >> 6.8、iOS APM应用性能监控管理(doing) > 7、[iOS Crash防护](#7-iOS Crash防护) From 867d459d67d17e7fed5bc237bef01ffa49cc905e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Fri, 17 Jul 2020 13:40:11 +0800 Subject: [PATCH 076/356] Update README.md --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c841afee..46bf26b5 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,11 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git >> 3.6、AVFoundation 利用摄像头实时识别物体颜色 >> 3.7、AVFoundation 原生二维码扫描识别和生成 -> 4、[OpenGL ES学习](#4-OpenGL ES学习) +> 4、[OpenGL ES学习](#4-OpenGLES学习) > 5、[LeetCode算法练习](#5-LeetCode算法练习) > 6、[工作中踩过的坑](#6-工作中踩过的坑) >> 6.1、键盘和UIMenuController不能同时存在的问题 ->> 6.2、全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突] +>> 6.2、全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突 >> 6.3、UITableView/UICollectionView获取特定位置的cell >> 6.4、UIScrollView视觉差动画](#6.4-UIScrollView视觉差动画) >> 6.5、iOS 传感器集锦 @@ -27,7 +27,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git >> 6.7、二进制重排优化启动速度 >> 6.8、iOS APM应用性能监控管理(doing) -> 7、[iOS Crash防护](#7-iOS Crash防护) +> 7、[iOS Crash防护](#7-iOSCrash防护) > 8、[WKWebView相关](#8-WKWebView相关) >> 8.1、WKWebView的使用 >> 8.2、WKWebView+UITableView混排 @@ -36,7 +36,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git >> 8.5、UIScrollView实现原理 >> 8.6、UITableView的实现原理 -> 问题说明 +> [问题说明](#问题说明) ## 1-暗黑模式适配 @@ -101,7 +101,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git > 该代码地址在:https://github.com/wsl2ls/ScanQRcode -## 4-OpenGL ES学习 +## 4-OpenGLES学习 > 示例描述: > * 1、GLKit 绘制图片和正方体 @@ -131,7 +131,7 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git > CPU占用率、内存/磁盘使用率、卡顿监控定位 ...... -## 7-iOS Crash防护 +## 7-iOSCrash防护 > Crash防护内容涉及 NSArray/NSMutableArray、NSDictionary/NSMutableDictionary、NSString/NSMutableString、Unrecognized Selector、KVO、KVC 、野指针定位、内存泄漏/循环引用;主要是对常见易错的地方进行容错处理,避免崩溃,并保存出错时的函数调用栈,以方便快速定位代码,主要是利用的runtime和fishook知识。 From ea001b7909111c269f2afe414c136cc88dbe19cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Fri, 17 Jul 2020 13:48:51 +0800 Subject: [PATCH 077/356] Update README.md --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 46bf26b5..896bac3d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ # iOS_Tips > iOS的一些示例,不定时更新~ -GitHub:https://github.com/wsl2ls/iOS_Tips.git -掘金:https://juejin.im/user/5c00d97b6fb9a049fb436288 + +| [简书 ](https://www.jianshu.com/u/e15d1f644bea) | [掘金](https://juejin.im/user/5c00d97b6fb9a049fb436288) | +| ---- | ---- | +| [CSDN](https://blog.csdn.net/wsl2ls) | [微博](https://weibo.com/5732733120/profile?rightmod=1&wvr=6&mod=personinfo&is_all=1) | ### 目录 > 1、[暗黑模式](#1-暗黑模式适配) @@ -148,13 +150,14 @@ GitHub:https://github.com/wsl2ls/iOS_Tips.git avCaptureTool.videoSize = CGSizeMake(self.view.width * 0.8, self.view.height * 0.8); - #### Welcome to you 👏 您的follow和start,是我前进的动力,Thanks♪(・ω・)ノ 🤝 | [简书 ](https://www.jianshu.com/u/e15d1f644bea) | [掘金](https://juejin.im/user/5c00d97b6fb9a049fb436288) | QQ交流群 | 微信公众号 | 微信号 | | ---- | ---- | ---- | ---- | ---- | | [CSDN](https://blog.csdn.net/wsl2ls) | [微博](https://weibo.com/5732733120/profile?rightmod=1&wvr=6&mod=personinfo&is_all=1) | [835303405](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/QQ交流群.png) | [iOS2679114653](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/微信公众号.png) | w2679114653 | +[回到顶部](#iOS_Tips) + ![QQ交流群: 835303405](QQ交流群.png) > 欢迎扫描下方二维码关注——奔跑的程序猿iOSer——微信公众号:iOS2679114653 本公众号是一个iOS开发者们的分享,交流,学习平台,会不定时的发送技术干货,源码,也欢迎大家积极踊跃投稿,(择优上头条) ^_^分享自己开发攻城的过程,心得,相互学习,共同进步,成为攻城狮中的翘楚! From 25880abadf850d168a37f3571be13455ee004f9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Fri, 17 Jul 2020 13:57:35 +0800 Subject: [PATCH 078/356] Update README.md --- README.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 896bac3d..0a6c85f2 100644 --- a/README.md +++ b/README.md @@ -61,13 +61,8 @@ > 主要类:SLAvCaptureTool(音视频采集录制工具)、SLAvEditExport(导出编辑的音视频)。关于视频的压缩问题,可以通过降低采集时的分辨率sessionPreset、降低写入文件时的分辨率(AVVideoWidthKey宽AVVideoHeightKey高)和码率(AVVideoCodecKey)、指定高的FormatProfile(AVVideoProfileLevelKey)等方法来实现,同时也要保证一定的清晰度满足业务的需求, 可以看看这篇文章https://www.jianshu.com/p/4f69c22c6dce |![拍摄视频.gif](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/3、小视频1.gif)|![拍摄照片](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/3、小视频2.gif)|![横屏视频](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/3、小视频3.gif)| - -***** - +| ---- | ---- | ---- | |![视频编辑](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/3、小视频4.gif)|![视频编辑](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/3、小视频5.gif)|![图片编辑](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/3、小视频6.gif)| - -**** - |![图片编辑](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/3、小视频7.gif)|![图片裁剪](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/3、小视频8.gif)| @@ -137,6 +132,8 @@ > Crash防护内容涉及 NSArray/NSMutableArray、NSDictionary/NSMutableDictionary、NSString/NSMutableString、Unrecognized Selector、KVO、KVC 、野指针定位、内存泄漏/循环引用;主要是对常见易错的地方进行容错处理,避免崩溃,并保存出错时的函数调用栈,以方便快速定位代码,主要是利用的runtime和fishook知识。 +![iOS Crash防护](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/iOS Crash防护.gif) + ## 8-WKWebView相关 > [WKWebView的使用](https://juejin.im/post/5c0e1e2ae51d451d971743a1)、[WKWebView+UITableView混排](https://juejin.im/post/5ed999fd51882542f9389949)、WKWebView离线缓存功能、HTML非文本元素替换为原生组件展示、UIScrollView实现原理、UITableView的实现原理 From eef8c363494d7ead162eea1c09fcf02f16fcb288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Fri, 17 Jul 2020 14:08:16 +0800 Subject: [PATCH 079/356] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0a6c85f2..2bd13f25 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ > Crash防护内容涉及 NSArray/NSMutableArray、NSDictionary/NSMutableDictionary、NSString/NSMutableString、Unrecognized Selector、KVO、KVC 、野指针定位、内存泄漏/循环引用;主要是对常见易错的地方进行容错处理,避免崩溃,并保存出错时的函数调用栈,以方便快速定位代码,主要是利用的runtime和fishook知识。 -![iOS Crash防护](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/iOS Crash防护.gif) +![iOSCrash防护](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/iOSCrash防护.gif) ## 8-WKWebView相关 From c53ac2338b7086ecba0df33ea3377415f9da2b30 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 17 Jul 2020 22:11:00 +0800 Subject: [PATCH 080/356] =?UTF-8?q?iOS=20Crash=E9=98=B2=E6=8A=A4=E4=B9=8B?= =?UTF-8?q?=E9=87=8E=E6=8C=87=E9=92=88=E6=8D=95=E8=8E=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Crash/SLCrashProtector/SLZombieFinder.m | 26 ++++++++++++------- .../DarkMode/Crash/SLCrashViewController.m | 5 ++-- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieFinder.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieFinder.m index fdd9ba93..083721b2 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieFinder.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieFinder.m @@ -9,12 +9,14 @@ #import "SLZombieFinder.h" #import "SLZombieCatcher.h" #import +#import "SLCrashProtector.h" -typedef void (*SLDeallocPointer) (id obj); +typedef void (*SLDeallocPointer) (id obj); ///指向Dealloc实现IMP的指针 static BOOL _enabled = NO; -static NSArray *_rootClasses = nil; -static NSDictionary *_rootClassDeallocImps = nil; +static NSArray *_rootClasses = nil; //根/基类 +static NSDictionary *_rootClassDeallocImps = nil; //存储根类Dealloc的方法实现IMP +/// 嗅探/延迟释放实例的白名单类,不对在此名单中的类进行僵尸对象嗅探/延迟释放 static inline NSMutableSet *sl_sniff_white_list() { static NSMutableSet *lxd_sniff_white_list; static dispatch_once_t onceToken; @@ -23,7 +25,7 @@ }); return lxd_sniff_white_list; } - +///释放实例 static inline void sl_dealloc(__unsafe_unretained id obj) { Class currentCls = [obj class]; Class rootCls = currentCls; @@ -39,7 +41,7 @@ static inline void sl_dealloc(__unsafe_unretained id obj) { deallocImp(obj); } } - +///交换IMP,并返回method的原始IMP static inline IMP sl_swizzleMethodWithBlock(Method method, void *block) { IMP blockImplementation = imp_implementationWithBlock(block); return method_setImplementation(method, blockImplementation); @@ -78,24 +80,29 @@ + (void)appendIgnoreClass: (Class)cls { } } - #pragma mark - Private +///hook基类NSObject/NSProxy的dealloc方法,并指向swizzledDeallocBlock对应的IMP + (void)_swizzleDealloc { static void *swizzledDeallocBlock = NULL; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ + ///NSObject/NSProxy的dealloc交换后的方法实现 swizzledDeallocBlock = [^void(id obj) { Class currentClass = [obj class]; NSString *clsName = NSStringFromClass(currentClass); - if ([sl_sniff_white_list() containsObject: clsName]) { + //_UITextSizeCache 这个私有类的实例对象在dispatch_after里释放会崩溃,故排除 + if ([sl_sniff_white_list() containsObject:clsName] || [clsName isEqualToString:@"_UITextSizeCache"]) { sl_dealloc(obj); } else { NSValue *objVal = [NSValue valueWithBytes: &obj objCType: @encode(typeof(obj))]; + ///动态转换obj对象的isa类对象为SLZombieCatcher,让SLZombieCatcher去捕获异常的消息并抛出异常 object_setClass(obj, [SLZombieCatcher class]); + ///保存原来的类 ((SLZombieCatcher *)obj).originClass = currentClass; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(30 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + ///延迟5秒释放此obj对象内存空间,如果释放前,有新消息发送给此地址的对象(SLZombieCatcher),就说明出现了野指针/坏内存访问 + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ __unsafe_unretained id deallocObj = nil; [objVal getValue: &deallocObj]; object_setClass(deallocObj, currentClass); @@ -107,12 +114,14 @@ + (void)_swizzleDealloc { NSMutableDictionary *deallocImps = [NSMutableDictionary dictionary]; for (Class rootClass in _rootClasses) { + //设置方法dealloc的实现IMP为swizzledDeallocBlock的方法实现IMP,并存储原有的dealloc的IMP,适当时机去执行 IMP originalDeallocImp = sl_swizzleMethodWithBlock(class_getInstanceMethod(rootClass, @selector(dealloc)), swizzledDeallocBlock); [deallocImps setObject: [NSValue valueWithBytes: &originalDeallocImp objCType: @encode(typeof(IMP))] forKey: NSStringFromClass(rootClass)]; } _rootClassDeallocImps = [deallocImps copy]; } +///恢复原来的IMP指向 + (void)_unswizzleDealloc { [_rootClasses enumerateObjectsUsingBlock:^(Class rootClass, NSUInteger idx, BOOL *stop) { IMP originalDeallocImp = NULL; @@ -122,7 +131,6 @@ + (void)_unswizzleDealloc { NSParameterAssert(originalDeallocImp); method_setImplementation(class_getInstanceMethod(rootClass, @selector(dealloc)), originalDeallocImp); }]; - [_rootClassDeallocImps release]; _rootClassDeallocImps = nil; } diff --git a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m index 33163dfa..294ba133 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m @@ -32,9 +32,6 @@ - (void)viewDidLoad { [super viewDidLoad]; [self setupUI]; } -- (void)dealloc { - -} #pragma mark - UI - (void)setupUI { @@ -223,6 +220,7 @@ - (void)testWildPointer { //开启僵尸对象嗅探定位 可以打开或关闭此开关看看效果就知道了 [SLZombieFinder startSniffer]; + UILabel *label = [[UILabel alloc] init]; //-fno-objc-arc 记得设置此类编译方式支持MRC //testObj对象所在的内存空间已释放 @@ -242,6 +240,7 @@ - (void)testWildPointer { [SLDelayPerform sl_startDelayPerform:^{ [newView removeFromSuperview]; } afterDelay:2.0]; + } #pragma mark - 内存泄漏/循环引用 From 744c785b4210cf47f759e114c7aab958ae49e7be Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sat, 18 Jul 2020 16:45:29 +0800 Subject: [PATCH 081/356] =?UTF-8?q?iOS=20Crash=E9=98=B2=E6=8A=A4=E4=B9=8B?= =?UTF-8?q?=E9=87=8E=E6=8C=87=E9=92=88=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieFinder.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieFinder.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieFinder.m index 083721b2..6630812b 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieFinder.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieFinder.m @@ -92,7 +92,7 @@ + (void)_swizzleDealloc { Class currentClass = [obj class]; NSString *clsName = NSStringFromClass(currentClass); //_UITextSizeCache 这个私有类的实例对象在dispatch_after里释放会崩溃,故排除 - if ([sl_sniff_white_list() containsObject:clsName] || [clsName isEqualToString:@"_UITextSizeCache"]) { + if ([sl_sniff_white_list() containsObject:clsName] || [clsName isEqualToString:@"_UITextSizeCache"] || [clsName isEqualToString:@"NSConcreteValue"] || [clsName isEqualToString:@"SLZombieCatcher"] ) { sl_dealloc(obj); } else { NSValue *objVal = [NSValue valueWithBytes: &obj objCType: @encode(typeof(obj))]; From 64dab8d86997685cc49faa8df24695388282546f Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sat, 18 Jul 2020 16:59:53 +0800 Subject: [PATCH 082/356] =?UTF-8?q?iOS=20=20APM=E7=9B=91=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 6 ++ .../DarkMode/WorkIssues/APM/SLAPMManager.m | 73 +---------------- .../DarkMode/WorkIssues/APM/SLAPMMemoryDisk.h | 32 ++++++++ .../DarkMode/WorkIssues/APM/SLAPMMemoryDisk.m | 81 +++++++++++++++++++ 4 files changed, 123 insertions(+), 69 deletions(-) create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/SLAPMMemoryDisk.h create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/SLAPMMemoryDisk.m diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index d770055b..993f9f95 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -68,6 +68,7 @@ 784C4BE724BC53D500D5C199 /* SLAPMCpu.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BE624BC53D500D5C199 /* SLAPMCpu.m */; }; 784C4BEA24BDA2DE00D5C199 /* SLProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BE924BDA2DE00D5C199 /* SLProxy.m */; }; 784C4BED24BDA5D700D5C199 /* SLAPMFluency.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BEC24BDA5D700D5C199 /* SLAPMFluency.m */; }; + 784C4C3A24C2EE6600D5C199 /* SLAPMMemoryDisk.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4C3924C2EE6600D5C199 /* SLAPMMemoryDisk.m */; }; 7851CB362331CC87002295B5 /* SLDarkModeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7851CB332331CC87002295B5 /* SLDarkModeViewController.m */; }; 7851CB372331CC87002295B5 /* SLDarkModeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7851CB352331CC87002295B5 /* SLDarkModeViewController.xib */; }; 7851CB43233222E2002295B5 /* UIView+SLFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 7851CB41233222E2002295B5 /* UIView+SLFrame.m */; }; @@ -278,6 +279,8 @@ 784C4BE924BDA2DE00D5C199 /* SLProxy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLProxy.m; sourceTree = ""; }; 784C4BEB24BDA5D700D5C199 /* SLAPMFluency.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMFluency.h; sourceTree = ""; }; 784C4BEC24BDA5D700D5C199 /* SLAPMFluency.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMFluency.m; sourceTree = ""; }; + 784C4C3824C2EE6600D5C199 /* SLAPMMemoryDisk.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMMemoryDisk.h; sourceTree = ""; }; + 784C4C3924C2EE6600D5C199 /* SLAPMMemoryDisk.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMMemoryDisk.m; sourceTree = ""; }; 7851CB332331CC87002295B5 /* SLDarkModeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLDarkModeViewController.m; sourceTree = ""; }; 7851CB342331CC87002295B5 /* SLDarkModeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLDarkModeViewController.h; sourceTree = ""; }; 7851CB352331CC87002295B5 /* SLDarkModeViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SLDarkModeViewController.xib; sourceTree = ""; }; @@ -617,6 +620,8 @@ 784C4BE324BC4C5E00D5C199 /* SLAPMManager.m */, 784C4BE524BC53D500D5C199 /* SLAPMCpu.h */, 784C4BE624BC53D500D5C199 /* SLAPMCpu.m */, + 784C4C3824C2EE6600D5C199 /* SLAPMMemoryDisk.h */, + 784C4C3924C2EE6600D5C199 /* SLAPMMemoryDisk.m */, 784C4BEB24BDA5D700D5C199 /* SLAPMFluency.h */, 784C4BEC24BDA5D700D5C199 /* SLAPMFluency.m */, ); @@ -1447,6 +1452,7 @@ 782CFB57239E5FE6001B5528 /* SLShaderFilterViewController.m in Sources */, 7822CCF8235B054200E70C29 /* SLPaddingLabel.m in Sources */, 784C4BE424BC4C5E00D5C199 /* SLAPMManager.m in Sources */, + 784C4C3A24C2EE6600D5C199 /* SLAPMMemoryDisk.m in Sources */, 78842468248FAED100C2E505 /* SLColorPickerViewController.m in Sources */, 787C7DCF2462B03D005DF7ED /* UINavigationController+SLMLeakFinder.m in Sources */, 788ACD622390BFD400737EC2 /* SLLoadImageVC.m in Sources */, diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m index fdef1bf6..243a5485 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m @@ -10,9 +10,9 @@ #import "SLTimer.h" #import "SLAPMCpu.h" +#import "SLAPMMemoryDisk.h" #import "SLAPMFluency.h" -#include @interface SLAPMManager () ///任务名称 @@ -76,79 +76,14 @@ - (void)monitoring { } if ((self.type & SLAPMTypeMemory) == SLAPMTypeMemory || (self.type & SLAPMTypeAll) == SLAPMTypeAll) { - double useMemory = [SLAPMManager getUsageMemory]; - double freeMemory = [SLAPMManager getFreeMemory]; - double totalMemory = [SLAPMManager getTotalMemory]; + double useMemory = [SLAPMMemoryDisk getUsageMemory]; + double freeMemory = [SLAPMMemoryDisk getFreeMemory]; + double totalMemory = [SLAPMMemoryDisk getTotalMemory]; NSLog(@" Memory占用:%.1fM 空闲:%.1fM 总共:%.1fM",useMemory, freeMemory, totalMemory); } } -#pragma mark - Memory / Disk -///当前应用的内存占用情况,和Xcode数值相近 单位MB -+ (double)getUsageMemory { - task_vm_info_data_t vmInfo; - mach_msg_type_number_t count = TASK_VM_INFO_COUNT; - if(task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &count) == KERN_SUCCESS) { - return (double)vmInfo.phys_footprint / (1024 * 1024); - } else { - return -1.0; - } -} -///剩余空闲内存 单位MB -+ (double)getFreeMemory{ - mach_port_t host_port = mach_host_self(); - mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t); - vm_size_t page_size; - vm_statistics_data_t vm_stat; - kern_return_t kern; - - kern = host_page_size(host_port, &page_size); - if (kern != KERN_SUCCESS) return -1; - kern = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size); - if (kern != KERN_SUCCESS) return -1; - return vm_stat.free_count * page_size / (1024 * 1024); -} -/// 总共的内存大小 单位MB -+ (double)getTotalMemory { - int64_t mem = [[NSProcessInfo processInfo] physicalMemory]; - if (mem < -1) mem = -1; - return mem / (1024 * 1024); -} - -///filePath目录下的文件 占用的磁盘大小 单位MB 默认沙盒Caches目录 -+ (double)getUsageDisk:(NSString *)filePath { - if (filePath.length == 0) filePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject; - ///定时执行时,此句代码会导致内存不断增长?0.1M 合理安排执行时机 - NSArray *filesArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:filePath error:nil] ; - NSEnumerator *filesEnumerator = [filesArray objectEnumerator]; - filesArray = nil; - - NSString *fileName; - unsigned long long int fileSize = 0; - while (fileName = [filesEnumerator nextObject]) { - @autoreleasepool { - //单个文件大小 - NSDictionary *fileDic = [[NSFileManager defaultManager] attributesOfItemAtPath:[filePath stringByAppendingPathComponent:fileName] error:nil]; - fileSize += [fileDic fileSize]; - } - } - filesEnumerator = nil; - return fileSize / (1024*1024); -} -///剩余空闲的磁盘容量 单位G -+ (double)getFreeDisk { - NSDictionary *fattributes = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil]; - NSNumber *freeSize = [fattributes objectForKey:NSFileSystemFreeSize]; - return [freeSize integerValue] / (1024*1024*1024); -} -///总磁盘容量 单位G -+ (double)getTotalDisk { - NSDictionary *fattributes = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil]; - NSNumber *totalSize = [fattributes objectForKey:NSFileSystemSize]; - return [totalSize integerValue] / (1024*1024*1024); -} - #pragma mark - Fluency/卡顿监测 ///卡顿监控回调 当callStack不为nil时,表示发生卡顿并捕捉到卡顿时的调用栈 - (void)APMFluency:(SLAPMFluency *)fluency didChangedFps:(float)fps callStackOfStuck:(nullable NSString *)callStack { diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMMemoryDisk.h b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMMemoryDisk.h new file mode 100644 index 00000000..cea3c063 --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMMemoryDisk.h @@ -0,0 +1,32 @@ +// +// SLAPMMemoryDisk.h +// DarkMode +// +// Created by wsl on 2020/7/18. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// 内存磁盘容量监控 +@interface SLAPMMemoryDisk : NSObject + +///当前应用的内存占用情况,和Xcode数值相近 单位MB ++ (double)getUsageMemory; +///剩余空闲内存 单位MB ++ (double)getFreeMemory; +/// 总共的内存大小 单位MB ++ (double)getTotalMemory; + +///filePath目录下的文件 占用的磁盘大小 单位MB 默认沙盒Caches目录 此句代码不要频繁定时执行,比较耗内存 ++ (double)getUsageDisk:(NSString *)filePath; +///剩余空闲的磁盘容量 单位G ++ (double)getFreeDisk; +///总磁盘容量 单位G ++ (double)getTotalDisk; + +@end + +NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMMemoryDisk.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMMemoryDisk.m new file mode 100644 index 00000000..d7b8bfff --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMMemoryDisk.m @@ -0,0 +1,81 @@ +// +// SLAPMMemoryDisk.m +// DarkMode +// +// Created by wsl on 2020/7/18. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLAPMMemoryDisk.h" +#include + +@implementation SLAPMMemoryDisk + + +#pragma mark - Memory / Disk +///当前应用的内存占用情况,和Xcode数值相近 单位MB ++ (double)getUsageMemory { + task_vm_info_data_t vmInfo; + mach_msg_type_number_t count = TASK_VM_INFO_COUNT; + if(task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &count) == KERN_SUCCESS) { + return (double)vmInfo.phys_footprint / (1024 * 1024); + } else { + return -1.0; + } +} +///剩余空闲内存 单位MB ++ (double)getFreeMemory{ + mach_port_t host_port = mach_host_self(); + mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t); + vm_size_t page_size; + vm_statistics_data_t vm_stat; + kern_return_t kern; + + kern = host_page_size(host_port, &page_size); + if (kern != KERN_SUCCESS) return -1; + kern = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size); + if (kern != KERN_SUCCESS) return -1; + return vm_stat.free_count * page_size / (1024 * 1024); +} +/// 总共的内存大小 单位MB ++ (double)getTotalMemory { + int64_t mem = [[NSProcessInfo processInfo] physicalMemory]; + if (mem < -1) mem = -1; + return mem / (1024 * 1024); +} + +///filePath目录下的文件 占用的磁盘大小 单位MB 默认沙盒Caches目录 ++ (double)getUsageDisk:(NSString *)filePath { + if (filePath.length == 0) filePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject; + ///定时执行时,此句代码会导致内存不断增长?0.1M 合理安排执行时机 + NSArray *filesArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:filePath error:nil] ; + NSEnumerator *filesEnumerator = [filesArray objectEnumerator]; + filesArray = nil; + + NSString *fileName; + unsigned long long int fileSize = 0; + while (fileName = [filesEnumerator nextObject]) { + @autoreleasepool { + //单个文件大小 + NSDictionary *fileDic = [[NSFileManager defaultManager] attributesOfItemAtPath:[filePath stringByAppendingPathComponent:fileName] error:nil]; + fileSize += [fileDic fileSize]; + } + } + filesEnumerator = nil; + return fileSize / (1024*1024); +} +///剩余空闲的磁盘容量 单位G ++ (double)getFreeDisk { + NSDictionary *fattributes = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil]; + NSNumber *freeSize = [fattributes objectForKey:NSFileSystemFreeSize]; + return [freeSize integerValue] / (1024*1024*1024); +} +///总磁盘容量 单位G ++ (double)getTotalDisk { + NSDictionary *fattributes = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil]; + NSNumber *totalSize = [fattributes objectForKey:NSFileSystemSize]; + return [totalSize integerValue] / (1024*1024*1024); +} + + +@end From 0b496c610ffd23190338251d25c954c4c65cc557 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sat, 18 Jul 2020 18:13:55 +0800 Subject: [PATCH 083/356] =?UTF-8?q?iOS=20crash=E9=98=B2=E6=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NSObject+SLCrashProtector.m | 16 ---------------- .../Crash/SLCrashProtector/SLCrashProtector.h | 17 +++++++++++++++++ .../Crash/SLCrashProtector/SLZombieFinder.h | 4 ++-- .../Crash/SLCrashProtector/SLZombieFinder.m | 19 ++++++++++++++++--- .../DarkMode/Crash/SLCrashViewController.m | 1 + 5 files changed, 36 insertions(+), 21 deletions(-) diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSObject+SLCrashProtector.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSObject+SLCrashProtector.m index 085cf2a9..d0abfe5e 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSObject+SLCrashProtector.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSObject+SLCrashProtector.m @@ -178,22 +178,6 @@ - (void)sl_KVODealloc{ // } [self sl_KVODealloc]; } -/*是否是系统类*/ -static inline BOOL IsSystemClass(Class cls){ - __block BOOL isSystem = NO; - NSString *className = NSStringFromClass(cls); - if ([className hasPrefix:@"NS"]) { - isSystem = YES; - return isSystem; - } - NSBundle *mainBundle = [NSBundle bundleForClass:cls]; - if (mainBundle == [NSBundle mainBundle]) { - isSystem = NO; - }else{ - isSystem = YES; - } - return isSystem; -} #pragma mark - KVC /// KVC 防护 diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashProtector.h b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashProtector.h index 2e9a448a..064ab968 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashProtector.h +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashProtector.h @@ -36,5 +36,22 @@ static inline void SL_ExchangeClassMethod(Class _class ,SEL _originalSel,SEL _ex method_exchangeImplementations(methodOriginal, methodNew); } +/*是否是系统类*/ +static inline BOOL IsSystemClass(Class cls){ + __block BOOL isSystem = NO; + NSString *className = NSStringFromClass(cls); + if ([className hasPrefix:@"NS"]) { + isSystem = YES; + return isSystem; + } + NSBundle *mainBundle = [NSBundle bundleForClass:cls]; + if (mainBundle == [NSBundle mainBundle]) { + isSystem = NO; + }else{ + isSystem = YES; + } + return isSystem; +} + #endif /* SLCrashProtector_h */ diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieFinder.h b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieFinder.h index 9a990e0c..5d44bdeb 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieFinder.h +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieFinder.h @@ -13,7 +13,7 @@ NS_ASSUME_NONNULL_BEGIN /* -fno-objc-arc 记得设置此类编译方式支持MRC */ -///zombie/野指针对象嗅探器 来源:https://github.com/sindrilin/LXDZombieSniffer.git +///zombie/野指针对象嗅探器 目前还不完善,不推荐使用 ,仅做交流学习 来源:https://github.com/sindrilin/LXDZombieSniffer.git @interface SLZombieFinder : NSObject ///启动zombie嗅探 @@ -22,7 +22,7 @@ NS_ASSUME_NONNULL_BEGIN ///关闭zombie嗅探 + (void)closeSniffer; - ///添加嗅探白名单类 + ///添加嗅探白名单类 不嗅探名单之内的类 + (void)appendIgnoreClass: (Class)cls; @end diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieFinder.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieFinder.m index 6630812b..a4735a42 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieFinder.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLZombieFinder.m @@ -12,9 +12,10 @@ #import "SLCrashProtector.h" typedef void (*SLDeallocPointer) (id obj); ///指向Dealloc实现IMP的指针 -static BOOL _enabled = NO; +static BOOL _enabled = NO; //嗅探器是否已开启 static NSArray *_rootClasses = nil; //根/基类 static NSDictionary *_rootClassDeallocImps = nil; //存储根类Dealloc的方法实现IMP +static BOOL isOnlySnifferMyClass = NO; ///是否仅嗅探自己创建的类 默认NO /// 嗅探/延迟释放实例的白名单类,不对在此名单中的类进行僵尸对象嗅探/延迟释放 static inline NSMutableSet *sl_sniff_white_list() { @@ -22,6 +23,18 @@ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ lxd_sniff_white_list = [[NSMutableSet alloc] init]; + + [lxd_sniff_white_list addObject:@"_UITextSizeCache"]; + [lxd_sniff_white_list addObject:@"NSConcreteValue"]; + [lxd_sniff_white_list addObject:@"SLZombieCatcher"]; + [lxd_sniff_white_list addObject:@"OS_dispatch_data"]; + + [lxd_sniff_white_list addObject:@"__NSGlobalBlock__"]; + [lxd_sniff_white_list addObject:@"__NSStackBlock__ "]; + [lxd_sniff_white_list addObject:@"__NSMallocBlock__"]; + [lxd_sniff_white_list addObject:@"NSBlock"]; + [lxd_sniff_white_list addObject:@"NSValue"]; + }); return lxd_sniff_white_list; } @@ -92,7 +105,7 @@ + (void)_swizzleDealloc { Class currentClass = [obj class]; NSString *clsName = NSStringFromClass(currentClass); //_UITextSizeCache 这个私有类的实例对象在dispatch_after里释放会崩溃,故排除 - if ([sl_sniff_white_list() containsObject:clsName] || [clsName isEqualToString:@"_UITextSizeCache"] || [clsName isEqualToString:@"NSConcreteValue"] || [clsName isEqualToString:@"SLZombieCatcher"] ) { + if ([sl_sniff_white_list() containsObject:clsName] || [clsName hasPrefix:@"OS_xpc"] || [clsName hasPrefix:@"WK"]) { sl_dealloc(obj); } else { NSValue *objVal = [NSValue valueWithBytes: &obj objCType: @encode(typeof(obj))]; @@ -102,7 +115,7 @@ + (void)_swizzleDealloc { ((SLZombieCatcher *)obj).originClass = currentClass; ///延迟5秒释放此obj对象内存空间,如果释放前,有新消息发送给此地址的对象(SLZombieCatcher),就说明出现了野指针/坏内存访问 - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ __unsafe_unretained id deallocObj = nil; [objVal getValue: &deallocObj]; object_setClass(deallocObj, currentClass); diff --git a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m index 294ba133..c630b2d1 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m @@ -218,6 +218,7 @@ - (void)testKVC { ///思路来源: https://www.jianshu.com/p/9fd4dc046046?utm_source=oschina-app - (void)testWildPointer { //开启僵尸对象嗅探定位 可以打开或关闭此开关看看效果就知道了 + // 目前还不完善,不推荐使用 ,仅做交流学习 [SLZombieFinder startSniffer]; From a6c7262db969eae6f3f729dcf7e6286932767469 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 20 Jul 2020 11:44:49 +0800 Subject: [PATCH 084/356] =?UTF-8?q?APM=20=E4=BB=A3=E7=A0=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/.DS_Store | Bin 10244 -> 10244 bytes iOS_Tips/DarkMode/.DS_Store | Bin 12292 -> 14340 bytes .../NSArray+SLCrashProtector.m | 6 +++--- .../NSMutableArray+SLCrashProtector.m | 4 ++-- .../DarkMode/WorkIssues/APM/SLAPMManager.h | 5 +++-- .../DarkMode/WorkIssues/APM/SLAPMManager.m | 16 +++++++++++++++- 6 files changed, 23 insertions(+), 8 deletions(-) diff --git a/iOS_Tips/.DS_Store b/iOS_Tips/.DS_Store index a7846d048fe8daf6d9b4f2b18ecaae62e4b8d77d..9963f42397c120b4c5e455f0a5600b2163f9f9e1 100644 GIT binary patch delta 300 zcmZn(XbG6$&nUGqU^hRb)Z{=xk%oAn;*_MpVlV3?p;b>e9bZ00iOi`01_N&s{jB1 delta 255 zcmZn(XbG6$&nU4mU^hRb#Nv_l#Bt1Dp zoCj54f;cZTV*mqKa*KEylLzbM1L7K!??~`5HcWmkVa3ceb?M|c5;_6}8HT~h`MCuQ zAi#8hVX}dg+~g+7684KBGY#IKJUCfjN`A786b};rEXTBDu$<%Mb5bfoDK1Gl`AIrOh$Yt63&CRBUEfaAikz8v(}#005~WRs;Y5 diff --git a/iOS_Tips/DarkMode/.DS_Store b/iOS_Tips/DarkMode/.DS_Store index aaf1990cb3d53dbcd69d9600b293902cd81df1fe..391c9b5974f79831590c0bcac6bf0bc171a695dc 100644 GIT binary patch delta 1129 zcmZokXem%&U|?W$DortDU@!nOIe-{M3-ADmHU5GfOwC#O9TP@=Qz#1(Qz+tFUo>y#drQSwTcb)piU*<^2&T+tEwK-b%q$MNlM5xpgmUv;;5Mzaz6DaAFCj5GR)U8O&Q)b* z{lEZHJ$bE!Ykf|-VQ_MOZUNA3Kwr5w0!c20aE5$_B8F@RPljS3ECmKaF|x@nL%tX9?8X-6ItoT+lM{p$CTEDMPF|uc$z;ED z@_uD0Htm{&AdUBxWnfH36*PE$sL+JPel^O-n>txmXWFb+GJZbIo(@} z&w*VI40Lv2iUg(0RA3|}GUOm9FQ}@?9cl_p6B8z{QrpeG(&GZy;2d>XZYbMvc%_$6 xHc3`sumFJpH;`~e&dnPyzGt4yuM^0_1j*|bAZ3$tbS6%AQ3-|xG_?bLApmPzI}`u_ delta 755 zcmZoEXh~3DU|?W$DortDV9)?EIe-{M3-ADmHUi%q#~O zK&mI-m2lmBO45;S;)5HEs*`yX9x}7)t)2WqL62k3K8Gq(_d||Aj>=>&MJ|LugM!lJ zIz?V4E``axin5cFl+u_CUrf$Zl0dPW>BVfFbvlz3l%*!~Df6(wxz3aC2(4u|G&Ist zFtVIHLD+S2tcs+PYX&f6SQ(sw;hV@%%#eZXi*_4PHFN99GgM^Qpv+w=a*P`$-&84A ze{SAk@c!gMM^HpCxB&GQF=Qi$HB^3cxoRyVQ((m8Z)$Sv=`*;$72ZEM*->41vYt8* z5?_I7!iC8PRfQ*)sjtvU%5Mk9AJAwv27iVEhE#?;26qM@WaD9KCQeY8{7^ht2J8tS s0Zd8UKmwR}5UFY7#rMpU`Aq_OfT;$Q));`a!Q>p1iJP~n+R?#r0PY;&*8l(j diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSArray+SLCrashProtector.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSArray+SLCrashProtector.m index dd4f2f32..1fc0b6b2 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSArray+SLCrashProtector.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSArray+SLCrashProtector.m @@ -36,7 +36,7 @@ - (id)sl_objectAtIndex:(NSInteger)index { @catch (NSException *exception) { SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; - return nil; + return self.lastObject; } }else { return [self sl_objectAtIndex:index]; @@ -52,7 +52,7 @@ - (id)sl_singleObjectAtIndex:(NSInteger)index { @catch (NSException *exception) { SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; - return nil; + return self.lastObject; } }else { return [self sl_singleObjectAtIndex:index]; @@ -69,7 +69,7 @@ - (id)sl_objectAtIndexedSubscript:(NSInteger)index { @catch (NSException *exception) { SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; - return nil; + return self.lastObject; } } return [self sl_objectAtIndexedSubscript:index]; diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSMutableArray+SLCrashProtector.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSMutableArray+SLCrashProtector.m index b0205aa5..62b806e5 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSMutableArray+SLCrashProtector.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/NSMutableArray+SLCrashProtector.m @@ -36,7 +36,7 @@ - (id)sl_mObjectAtIndex:(NSInteger)index { @catch (NSException *exception) { SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeMArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; - return nil; + return self.lastObject; } }else { return [self sl_mObjectAtIndex:index]; @@ -53,7 +53,7 @@ - (id)sl_mObjectAtIndexedSubscript:(NSInteger)index { @catch (NSException *exception) { SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeMArray errorDesc:[NSString stringWithFormat:@"异常:数组越界 %@",exception.reason] exception:exception callStack:[NSThread callStackSymbols]]; [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; - return nil; + return self.lastObject; } } return [self sl_mObjectAtIndexedSubscript:index]; diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.h b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.h index 2604a1df..e270e598 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.h +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.h @@ -20,9 +20,10 @@ typedef NS_ENUM(NSInteger, SLAPMType) { SLAPMTypeMemory = 1 << 1, /*流畅度、卡顿*/ SLAPMTypeFluency = 1 << 2, - + /*iOS Crash防护模块*/ + SLAPMTypeCrash = 1 << 3, /*所有策略*/ - SLAPMTypeAll = 1 << 3 + SLAPMTypeAll = 1 << 4 }; diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m index 243a5485..26b96b81 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m @@ -12,9 +12,10 @@ #import "SLAPMCpu.h" #import "SLAPMMemoryDisk.h" #import "SLAPMFluency.h" +#import "SLCrashProtector.h" -@interface SLAPMManager () +@interface SLAPMManager () ///任务名称 @property (nonatomic, copy) NSString *taskName; @@ -51,6 +52,11 @@ - (void)startMonitoring { _taskName = [SLTimer execTask:self selector:@selector(monitoring) start:0 interval:1.0/60 repeats:YES async:YES]; } + + if ((self.type & SLAPMTypeCpu) == SLAPMTypeCrash || (self.type & SLAPMTypeMemory) == SLAPMTypeMemory) { + [SLCrashHandler defaultCrashHandler].delegate = self; + } + if ((self.type & SLAPMTypeFluency) == SLAPMTypeFluency || (self.type & SLAPMTypeAll) == SLAPMTypeAll) { [SLAPMFluency sharedInstance].delegate = self; [[SLAPMFluency sharedInstance] startMonitoring]; @@ -63,6 +69,7 @@ - (void)stopMonitoring { _isMonitoring = NO; [SLTimer cancelTask:_taskName]; + [SLAPMFluency sharedInstance].delegate = nil; [[SLAPMFluency sharedInstance] stopMonitoring]; } @@ -90,4 +97,11 @@ - (void)APMFluency:(SLAPMFluency *)fluency didChangedFps:(float)fps callStackOfS NSLog(@" 卡顿监测  fps:%f \n %@", fps, callStack == nil ? @"流畅":[NSString stringWithFormat:@"卡住了 %@",callStack]); } +#pragma mark - SLCrashHandlerDelegate +///异常捕获回调 提供给外界实现自定义处理 ,日志上报等 +- (void)crashHandlerDidOutputCrashError:(SLCrashError *)crashError { + NSString *errorInfo = [NSString stringWithFormat:@" 错误描述:%@ \n 调用栈:%@" ,crashError.errorDesc, crashError.callStackSymbol]; + NSLog(@"%@",errorInfo); +} + @end From 10e29b86e409509d858bf1a9c4ca7cf64c224bff Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 20 Jul 2020 11:47:53 +0800 Subject: [PATCH 085/356] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m index 26b96b81..039891ff 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m @@ -48,16 +48,16 @@ - (void)startMonitoring { if (_isMonitoring) return; _isMonitoring = YES; - if ((self.type & SLAPMTypeCpu) == SLAPMTypeCpu || (self.type & SLAPMTypeMemory) == SLAPMTypeMemory || (self.type & SLAPMTypeAll) == SLAPMTypeAll) { + if ((self.type & SLAPMTypeCpu) == SLAPMTypeCpu || (self.type & SLAPMTypeMemory) == SLAPMTypeMemory || self.type == SLAPMTypeAll) { _taskName = [SLTimer execTask:self selector:@selector(monitoring) start:0 interval:1.0/60 repeats:YES async:YES]; } - if ((self.type & SLAPMTypeCpu) == SLAPMTypeCrash || (self.type & SLAPMTypeMemory) == SLAPMTypeMemory) { + if ((self.type & SLAPMTypeCpu) == SLAPMTypeCrash || self.type == SLAPMTypeAll) { [SLCrashHandler defaultCrashHandler].delegate = self; } - if ((self.type & SLAPMTypeFluency) == SLAPMTypeFluency || (self.type & SLAPMTypeAll) == SLAPMTypeAll) { + if ((self.type & SLAPMTypeFluency) == SLAPMTypeFluency || self.type == SLAPMTypeAll) { [SLAPMFluency sharedInstance].delegate = self; [[SLAPMFluency sharedInstance] startMonitoring]; } @@ -77,12 +77,12 @@ - (void)stopMonitoring { ///监控中 - (void)monitoring { - if ((self.type & SLAPMTypeCpu) == SLAPMTypeCpu || (self.type & SLAPMTypeAll) == SLAPMTypeAll) { + if ((self.type & SLAPMTypeCpu) == SLAPMTypeCpu || self.type == SLAPMTypeAll) { float CPU = [SLAPMCpu getCpuUsage]; NSLog(@" CPU使用率:%.2f%%",CPU); } - if ((self.type & SLAPMTypeMemory) == SLAPMTypeMemory || (self.type & SLAPMTypeAll) == SLAPMTypeAll) { + if ((self.type & SLAPMTypeMemory) == SLAPMTypeMemory || self.type == SLAPMTypeAll) { double useMemory = [SLAPMMemoryDisk getUsageMemory]; double freeMemory = [SLAPMMemoryDisk getFreeMemory]; double totalMemory = [SLAPMMemoryDisk getTotalMemory]; From 02b5b728709d12b269c332e836852263ef00b00d Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 20 Jul 2020 19:23:39 +0800 Subject: [PATCH 086/356] =?UTF-8?q?=E9=AB=98=E8=B4=A8=E9=87=8F=E6=8A=80?= =?UTF-8?q?=E6=9C=AF=E5=8D=9A=E5=AE=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 8 ++++++++ .../DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 4 ++++ ...17\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 3 files changed, 13 insertions(+) create mode 100644 "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" create mode 100644 "iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 993f9f95..0e5cd8d9 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -69,6 +69,8 @@ 784C4BEA24BDA2DE00D5C199 /* SLProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BE924BDA2DE00D5C199 /* SLProxy.m */; }; 784C4BED24BDA5D700D5C199 /* SLAPMFluency.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4BEC24BDA5D700D5C199 /* SLAPMFluency.m */; }; 784C4C3A24C2EE6600D5C199 /* SLAPMMemoryDisk.m in Sources */ = {isa = PBXBuildFile; fileRef = 784C4C3924C2EE6600D5C199 /* SLAPMMemoryDisk.m */; }; + 784C4C6E24C5B4F500D5C199 /* 笔记.md in Resources */ = {isa = PBXBuildFile; fileRef = 784C4C6D24C5B4F500D5C199 /* 笔记.md */; }; + 784C4C7024C5B5DD00D5C199 /* 高质量技术博客.md in Resources */ = {isa = PBXBuildFile; fileRef = 784C4C6F24C5B5DD00D5C199 /* 高质量技术博客.md */; }; 7851CB362331CC87002295B5 /* SLDarkModeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7851CB332331CC87002295B5 /* SLDarkModeViewController.m */; }; 7851CB372331CC87002295B5 /* SLDarkModeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7851CB352331CC87002295B5 /* SLDarkModeViewController.xib */; }; 7851CB43233222E2002295B5 /* UIView+SLFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 7851CB41233222E2002295B5 /* UIView+SLFrame.m */; }; @@ -281,6 +283,8 @@ 784C4BEC24BDA5D700D5C199 /* SLAPMFluency.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMFluency.m; sourceTree = ""; }; 784C4C3824C2EE6600D5C199 /* SLAPMMemoryDisk.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMMemoryDisk.h; sourceTree = ""; }; 784C4C3924C2EE6600D5C199 /* SLAPMMemoryDisk.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMMemoryDisk.m; sourceTree = ""; }; + 784C4C6D24C5B4F500D5C199 /* 笔记.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = "笔记.md"; sourceTree = ""; }; + 784C4C6F24C5B5DD00D5C199 /* 高质量技术博客.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = "高质量技术博客.md"; sourceTree = ""; }; 7851CB332331CC87002295B5 /* SLDarkModeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLDarkModeViewController.m; sourceTree = ""; }; 7851CB342331CC87002295B5 /* SLDarkModeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLDarkModeViewController.h; sourceTree = ""; }; 7851CB352331CC87002295B5 /* SLDarkModeViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SLDarkModeViewController.xib; sourceTree = ""; }; @@ -862,6 +866,8 @@ 7884247C24920FCA00C2E505 /* WorkIssues */ = { isa = PBXGroup; children = ( + 784C4C6F24C5B5DD00D5C199 /* 高质量技术博客.md */, + 784C4C6D24C5B4F500D5C199 /* 笔记.md */, 7884247D2492102900C2E505 /* SLWorkIssuesViewController.h */, 7884247E2492102900C2E505 /* SLWorkIssuesViewController.m */, 784C4BDE24BC409600D5C199 /* APM */, @@ -1268,6 +1274,7 @@ 782CFB6E239E69F3001B5528 /* Scale.vsh in Resources */, 78BDE04D248BFBD7002ED386 /* wsl.png in Resources */, 782CFB37239E22AC001B5528 /* SplitScreen_9.fsh in Resources */, + 784C4C7024C5B5DD00D5C199 /* 高质量技术博客.md in Resources */, 7811F7AF24B32A1E000AA044 /* Order File.png in Resources */, 782CFB76239E6A02001B5528 /* SoulOut.vsh in Resources */, 782CFB54239E4587001B5528 /* SplitScreen_16.fsh in Resources */, @@ -1282,6 +1289,7 @@ 783FB4612394A76B0039AEFD /* shaderf.fsh in Resources */, 7811F7AD24B32A1E000AA044 /* Write Link Map File.png in Resources */, 782CFB2F239E04A2001B5528 /* SplitScreen_4.vsh in Resources */, + 784C4C6E24C5B4F500D5C199 /* 笔记.md in Resources */, 782CFB67239E6651001B5528 /* HexagonMosaic.vsh in Resources */, 782CFB2B239E0479001B5528 /* SplitScreen_3.vsh in Resources */, 782CFB5B239E6227001B5528 /* Gray.vsh in Resources */, diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" new file mode 100644 index 00000000..0e3d9712 --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -0,0 +1,4 @@ +一、性能优化 +[微信读书 iOS 性能优化总结](https://wereadteam.github.io/2016/05/03/WeRead-Performance/) + + diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" new file mode 100644 index 00000000..8b137891 --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -0,0 +1 @@ + From 201fc21731e02fd67135eabec4fe5e01ac493012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Tue, 21 Jul 2020 10:08:55 +0800 Subject: [PATCH 087/356] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2bd13f25..0861b104 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ >> 6.1、键盘和UIMenuController不能同时存在的问题 >> 6.2、全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突 >> 6.3、UITableView/UICollectionView获取特定位置的cell ->> 6.4、UIScrollView视觉差动画](#6.4-UIScrollView视觉差动画) +>> 6.4、UIScrollView视觉差动画 >> 6.5、iOS 传感器集锦 >> 6.6、iOS 自定义转场动画 >> 6.7、二进制重排优化启动速度 From fae027d41e7b25ba222d959245bc438bac4f4d96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Tue, 21 Jul 2020 10:28:02 +0800 Subject: [PATCH 088/356] Update README.md --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0861b104..176eb7b1 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ >> 8.5、UIScrollView实现原理 >> 8.6、UITableView的实现原理 -> [问题说明](#问题说明) +> [ 结尾](#结尾) ## 1-暗黑模式适配 @@ -140,10 +140,11 @@ ![WKWebView相关](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/12、WKWebView.gif) -## 问题说明: +## 结尾 -> * 1、主工程就是iOS_Tips下的DarkMode,别怀疑🤣,历史遗留问题😁😀,大部分内容都在里面,run一下就明白了🤝 -> * 2、小视频拍摄录制失败,主要集中在plus和X系列手机上:可能是由于写入的视频宽高videoSize设置的问题,各位可以先试试这样设置 +> * 1、主工程就是iOS_Tips下的DarkMode,别怀疑🤣,历史遗留问题😁😀,大部分内容都在里面,run一下就明白了🤝; +> * 2、该demo里面有些功能还没有写博客介绍,后期有时间会补上,不过代码我一般喜欢写注释,所以我相信大家读起来应该也容易理解,建议大家看完之后,自己也可以写写,把整个流程过一遍,也许会比我写的更好哟; +> * 3、小视频拍摄录制失败,主要集中在plus和X系列手机上:可能是由于写入的视频宽高videoSize设置的问题,各位可以先试试这样设置 avCaptureTool.videoSize = CGSizeMake(self.view.width * 0.8, self.view.height * 0.8); From 82006381b25cc158ab9b1fc3f21134c7b3f089e7 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 21 Jul 2020 14:09:29 +0800 Subject: [PATCH 089/356] =?UTF-8?q?=E8=AE=B0=E5=BD=95=E7=9C=8B=E8=BF=87?= =?UTF-8?q?=E7=9A=84=E9=AB=98=E8=B4=A8=E9=87=8F=E5=8D=9A=E5=AE=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\347\254\224\350\256\260.md" | 10 ++++++++-- ...200\346\234\257\345\215\232\345\256\242.md" | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 0e3d9712..aa4dfbfe 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -1,4 +1,10 @@ -一、性能优化 -[微信读书 iOS 性能优化总结](https://wereadteam.github.io/2016/05/03/WeRead-Performance/) + 一、性能优化 +1. 优化业务流程 +2. 合理的线程分配 +3. 预处理、延时加载、按需加载 +4. 三级缓存 +5. 使用正确的API + + diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 8b137891..13f4e4a5 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -1 +1,19 @@ +1、[WeRead团队博客](https://wereadteam.github.io/) +2、[美团技术团队](https://tech.meituan.com/) +3、[Lyman's Blog](http://www.lymanli.com) +4、[sunnyxx孙源](http://blog.sunnyxx.com) +5、[波儿菜](https://www.jianshu.com/u/a89bf7b8bdd8) +6、[张不坏的博客](https://zhangbuhuai.com) +7、[微博@iOS程序犭袁](https://github.com/ChenYilong) +8、[小东邪](https://juejin.im/user/58ec343861ff4b00691b4f26) +9、[onevcat](https://onevcat.com/#blog) +10、[戴铭](https://www.jianshu.com/u/9a4903d7e3d1) +11、[casatwy](https://casatwy.com) +12、[bang](http://blog.cnbang.net) +13、[杭州小刘](https://github.com/FantasticLBP/knowledge-kit/blob/master/SUMMARY.md) +14、[收納箱](https://juejin.im/user/5ea7963b5188256da0323498) +15、[齐舞647](https://juejin.im/user/5979852b5188253df6575210/posts) +16、[性能优化](https://github.com/skyming/iOS-Performance-Optimization) +17、[阿里、字节 一套高效的iOS面试题解答](https://github.com/colourful987/bytedance-alibaba-interview) +18、[面试题、基础知识点](https://github.com/liberalisman/iOS-InterviewQuestion-collection) From 7d572e1d68670cd712459f76b7c6ca817dc103d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Tue, 21 Jul 2020 14:24:06 +0800 Subject: [PATCH 090/356] =?UTF-8?q?Update=20=E9=AB=98=E8=B4=A8=E9=87=8F?= =?UTF-8?q?=E6=8A=80=E6=9C=AF=E5=8D=9A=E5=AE=A2.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...00\346\234\257\345\215\232\345\256\242.md" | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 13f4e4a5..e47e0605 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -1,19 +1,21 @@ -1、[WeRead团队博客](https://wereadteam.github.io/) -2、[美团技术团队](https://tech.meituan.com/) -3、[Lyman's Blog](http://www.lymanli.com) -4、[sunnyxx孙源](http://blog.sunnyxx.com) -5、[波儿菜](https://www.jianshu.com/u/a89bf7b8bdd8) -6、[张不坏的博客](https://zhangbuhuai.com) -7、[微博@iOS程序犭袁](https://github.com/ChenYilong) -8、[小东邪](https://juejin.im/user/58ec343861ff4b00691b4f26) -9、[onevcat](https://onevcat.com/#blog) -10、[戴铭](https://www.jianshu.com/u/9a4903d7e3d1) -11、[casatwy](https://casatwy.com) -12、[bang](http://blog.cnbang.net) -13、[杭州小刘](https://github.com/FantasticLBP/knowledge-kit/blob/master/SUMMARY.md) -14、[收納箱](https://juejin.im/user/5ea7963b5188256da0323498) -15、[齐舞647](https://juejin.im/user/5979852b5188253df6575210/posts) -16、[性能优化](https://github.com/skyming/iOS-Performance-Optimization) -17、[阿里、字节 一套高效的iOS面试题解答](https://github.com/colourful987/bytedance-alibaba-interview) -18、[面试题、基础知识点](https://github.com/liberalisman/iOS-InterviewQuestion-collection) +## 看过的高质量技术博客集合 + +* 1、[WeRead团队博客](https://wereadteam.github.io/) +* 2、[美团技术团队](https://tech.meituan.com/) +* 3、[Lyman's Blog](http://www.lymanli.com) +* 4、[sunnyxx孙源](http://blog.sunnyxx.com) +* 5、[波儿菜](https://www.jianshu.com/u/a89bf7b8bdd8) +* 6、[张不坏的博客](https://zhangbuhuai.com) +* 7、[微博@iOS程序犭袁](https://github.com/ChenYilong) +* 8、[小东邪](https://juejin.im/user/58ec343861ff4b00691b4f26) +* 9、[onevcat](https://onevcat.com/#blog) +* 10、[戴铭](https://www.jianshu.com/u/9a4903d7e3d1) +* 11、[casatwy](https://casatwy.com) +* 12、[bang](http://blog.cnbang.net) +* 13、[杭州小刘](https://github.com/FantasticLBP/knowledge-kit/blob/master/SUMMARY.md) +* 14、[收納箱](https://juejin.im/user/5ea7963b5188256da0323498) +* 15、[齐舞647](https://juejin.im/user/5979852b5188253df6575210/posts) +* 16、[性能优化](https://github.com/skyming/iOS-Performance-Optimization) +* 17、[阿里、字节 一套高效的iOS面试题解答](https://github.com/colourful987/bytedance-alibaba-interview) +* 18、[面试题、基础知识点](https://github.com/liberalisman/iOS-InterviewQuestion-collection) From 97bd1053af5178d695440b70d64e1e5e51ce1da5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Tue, 21 Jul 2020 14:29:05 +0800 Subject: [PATCH 091/356] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 176eb7b1..9727465a 100644 --- a/README.md +++ b/README.md @@ -37,9 +37,8 @@ >> 8.4、Html非文本元素替换为原生组件展示 >> 8.5、UIScrollView实现原理 >> 8.6、UITableView的实现原理 - -> [ 结尾](#结尾) - + +> [结尾](#结尾) ## 1-暗黑模式适配 @@ -144,7 +143,8 @@ > * 1、主工程就是iOS_Tips下的DarkMode,别怀疑🤣,历史遗留问题😁😀,大部分内容都在里面,run一下就明白了🤝; > * 2、该demo里面有些功能还没有写博客介绍,后期有时间会补上,不过代码我一般喜欢写注释,所以我相信大家读起来应该也容易理解,建议大家看完之后,自己也可以写写,把整个流程过一遍,也许会比我写的更好哟; -> * 3、小视频拍摄录制失败,主要集中在plus和X系列手机上:可能是由于写入的视频宽高videoSize设置的问题,各位可以先试试这样设置 +> * 3、[看过的高质量技术博客集合](iOS_Tips/DarkMode/WorkIssues/高质量技术博客.md),这些博客质量都挺高的,都出自各个大厂、大佬之后,认真看完绝对干活满满; +> * 4、小视频拍摄录制失败,主要集中在plus和X系列手机上:可能是由于写入的视频宽高videoSize设置的问题,各位可以先试试这样设置 avCaptureTool.videoSize = CGSizeMake(self.view.width * 0.8, self.view.height * 0.8); From 9ceae05d020e463b2c2dba58f6a6572e4c7321d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Tue, 21 Jul 2020 14:30:43 +0800 Subject: [PATCH 092/356] Delete .DS_Store --- .DS_Store | Bin 8196 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 40b97e6f66b50498a217548584e55732d685664f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8196 zcmeHM&1(}u6o1pEc9T$zP;3Pc3$`j)N@7ZT5FtsELa?@_DF*Q)AKfKc-0X&A)1WaD z3SN5X-Fo!{kK%t&d+{&O|3d_C`etU6ZZ>T%Nu}aUnEB1ly!U4Ix9{!l+W-KG)szsx zBmhWQDF*!598u^ztvzMP9+^NSs1Hfq+|27{9*+Y((qcd`AQ%t~2nGZLf`PNZ06w#6 zk&b!p^I6df1_T5DB?I*SAY-K%v9ZOG-8!&gDFC7ehgrcsd-X?@=>THH#ui5$!9uty zB3C7Lib3qmfpB%4kJ$1pj$9oGTN&-xD-%0IA$H0l`2o12lK{z$_F% z1Iv}a-^RHczgc059XY)aN^P2@G9C47UwcZSZKGtykAYdH5h4N*|=r=ffSHlPS9q-^~pj-~1O;%F4g_|tKA z30o8DC~Lw4tTkMP&33OuC}XFzQodd-+uZ%kmvyab1%uzo(6DFZ+^FRB`Mv)0e(&Q{ z(X6MeoK>sFa+OTrN=j4Ie6Et#6sx$Q8VOz9QjOKha?VmK52^5mY3eAz`?>smO|54F zFy}S43?Ys9M_P;PKAoe{RF7o3}dw{(GUO1Cl~Iw)E_I<3;o3Ysx8}f7|6R@Z(OqhrON?RjQkM9=A%RdM2G-O>XR@kCJiv=H5>5 z(-^-A_t$tc9(9^x#N zKyhjOaB0vzh|(7W!(4lk=KqP~zyJ5OhENs^2nNnJ1H=i#bOa&X3jw7;k9I^9as$KXcrFy!iv-dl97o From 5fa056105b068405552b9002bb01683e6ae0d75e Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 22 Jul 2020 10:50:39 +0800 Subject: [PATCH 093/356] =?UTF-8?q?=E6=97=A5=E5=BF=97=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/Crash/SLCrashViewController.m | 19 ++++++++++++++++++- .../DarkMode/General/Tool/PrefixHeader.pch | 13 +++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m index c630b2d1..1a82732e 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m @@ -88,7 +88,24 @@ - (void)setupUI { ///异常捕获回调 提供给外界实现自定义处理 ,日志上报等(注意线程安全) - (void)crashHandlerDidOutputCrashError:(SLCrashError *)crashError { [self.textView scrollsToTop]; - self.textView.text = [NSString stringWithFormat:@" 错误描述:%@ \n 调用栈:%@" ,crashError.errorDesc, crashError.callStackSymbol]; + NSString *errorInfo = [NSString stringWithFormat:@" 错误描述:%@ \n 调用栈:%@" ,crashError.errorDesc, crashError.callStackSymbol]; + self.textView.text = errorInfo; + + ///日志写入缓存,适当时机上传后台 + NSString *logPath = [SL_CachesDir stringByAppendingFormat:@"/com.wsl2ls.CrashLog"]; + if(![[NSFileManager defaultManager] fileExistsAtPath:logPath]) { + [[NSFileManager defaultManager] createDirectoryAtPath:logPath withIntermediateDirectories:NO attributes:nil error:nil]; + } + if(![[NSFileManager defaultManager] fileExistsAtPath:[logPath stringByAppendingFormat:@"/log"]]) { + NSError *error; + [errorInfo writeToFile:[logPath stringByAppendingFormat:@"/log"] atomically:YES encoding:NSUTF8StringEncoding error:&error]; + }else { + NSFileHandle * fileHandle = [NSFileHandle fileHandleForWritingAtPath:[logPath stringByAppendingFormat:@"/log"]]; + [fileHandle seekToEndOfFile]; + [fileHandle writeData:[errorInfo dataUsingEncoding:NSUTF8StringEncoding]]; + [fileHandle closeFile]; + } + } #pragma mark - Container Crash diff --git a/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch b/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch index c787ae09..9b9d0e20 100644 --- a/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch +++ b/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch @@ -110,6 +110,19 @@ #define SL_IS_EMPTY_STRING(x) (SL_IS_NULL(x) || [x isEqual:@""] || [x isEqual:@"(null)"]) #define SL_DEFUSE_EMPTY_STRING(x) (!SL_IS_EMPTY_STRING(x) ? x : @"") + +//沙河目录 +///获取沙盒主目录路径 +#define SL_HomeDir NSHomeDirectory(); +/// 获取Documents目录路径 +#define SL_DocumentDir [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] +/// 获取Library的目录路径 +#define SL_LibraryDir [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject] +/// 获取Caches目录路径 +#define SL_CachesDir [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject] +/// 获取tmp目录路径 +#define SL_TmpDir NSTemporaryDirectory() + //---------------------- About Color 颜色 ---------------------------- /// 随机颜色 #define SL_UIColorFromRandomColor [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:1.0] From 355ffd412efd90ad371ed56ae10058624e0e6978 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 22 Jul 2020 18:12:23 +0800 Subject: [PATCH 094/356] =?UTF-8?q?Crash=E5=BC=82=E5=B8=B8=E6=8D=95?= =?UTF-8?q?=E8=8E=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Crash/SLCrashProtector/SLCrashHandler.h | 4 +- .../Crash/SLCrashProtector/SLCrashHandler.m | 96 +++++++++++++++++++ .../DarkMode/Crash/SLCrashViewController.m | 2 + .../WorkIssues/\347\254\224\350\256\260.md" | 3 + ...00\346\234\257\345\215\232\345\256\242.md" | 2 + 5 files changed, 106 insertions(+), 1 deletion(-) diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h index 166e4c25..75ac952a 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h @@ -11,8 +11,10 @@ NS_ASSUME_NONNULL_BEGIN typedef NS_ENUM(NSInteger, SLCrashErrorType) { + /*未知错误*/ + SLCrashErrorTypeUnknow = 0, /*Array*/ - SLCrashErrorTypeArray = 0, + SLCrashErrorTypeArray, /*NSMutableArray*/ SLCrashErrorTypeMArray, /*NSDictionary*/ diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m index 23592c40..2cc1eb0a 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m @@ -20,6 +20,10 @@ + (instancetype)errorWithErrorType:(SLCrashErrorType)errorType errorDesc:(NSStri } @end + +@interface SLCrashHandler () +@end + @implementation SLCrashHandler + (instancetype)defaultCrashHandler { @@ -27,8 +31,100 @@ + (instancetype)defaultCrashHandler { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ crashHandler = [[SLCrashHandler alloc] init]; + [crashHandler setUncaughtExceptionHandler]; }); return crashHandler; } +/// 其他三方注册的异常处理 handler +static NSUncaughtExceptionHandler *otherUncaughtExceptionHandler = NULL; +///设置异常捕获回调 +- (void)setUncaughtExceptionHandler{ + ///先获取保留其他三方的异常Handler + otherUncaughtExceptionHandler = NSGetUncaughtExceptionHandler(); + ///注册自己的异常Handler + NSSetUncaughtExceptionHandler (SL_HandleException); + + ///注册信号Handler + signal(SIGABRT, sl_uncaughtSignalHandler); + signal(SIGILL, sl_uncaughtSignalHandler); + signal(SIGSEGV, sl_uncaughtSignalHandler); + signal(SIGFPE, sl_uncaughtSignalHandler); + signal(SIGBUS, sl_uncaughtSignalHandler); + signal(SIGPIPE, sl_uncaughtSignalHandler); + +} +///异常捕获处理 +void SL_HandleException(NSException *exception) { + if (otherUncaughtExceptionHandler) { + //如果其他三方也有注册,则也执行其他三方的Handle,然后在执行自己的 + otherUncaughtExceptionHandler(exception); + } + NSString *exceptionInfo = [NSString stringWithFormat:@"异常:%@, %@",exception.name, exception.reason]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeUnknow errorDesc:exceptionInfo exception:exception callStack:exception.callStackSymbols]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; +} + + +///异常信号处理回调 +void sl_uncaughtSignalHandler(int signal) { + NSString *exceptionInfo = [NSString stringWithFormat:@"异常信号:%@ Crash",signalName(signal)]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeUnknow errorDesc:exceptionInfo exception:nil callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; +} +///信号名称 关于信号这部分可以看 https://mp.weixin.qq.com/s/hVj-j61Br3dox37SN79fDQ +NSString *signalName(int signal) { + switch (signal) { + case SIGABRT: + /* + abort() 发生的信号: + 典型的软件信号,通过 pthread_kill() 发送 + */ + return @"SIGABRT"; + case SIGILL: + /* + 非法指令,即机器码指令不正确: + 1, iOS 上偶现的问题,遇到之后用户会连续闪退,直到应用二进制的缓存重新加载 或重启手机。此问题挺影响体验,但是报给苹果不认,因为苹果那边没有收集到,目前没有太好办法。因为 iOS 应用内无法对一片内存同时获取 w+x 权限的,因此应用无法造成此类问题,所以判断是苹果的问题。 + */ + return @"SIGILL"; + case SIGSEGV: + /*段错误: + 1、访问未申请的虚拟内存地址 + 2、没有写权限的内存写入 + */ + return @"SIGSEGV"; + case SIGFPE: + /* + 算术运算出错,比如除0错误: + iOS 默认是不启用的,所以我们一般不会遇到 + */ + return @"SIGFPE"; + case SIGBUS: + /*总线错误 + 1、内存地址对齐出错 2、试图执行没有执行权限的代码地址 + */ + return @"SIGBUS"; + case SIGPIPE: + /*管道破裂 + 1, Socket通信是可能遇到,如读进程以及终止时,写进程继续写入数据。 + */ + return @"SIGPIPE"; + case SIGKILL: + /* + 进程内无法拦截: + 1, exit(), kill(9) 等函数调用 2, iOS系统杀进程用的,比如 watchDog 杀进程 + */ + return @"SIGKILL"; + case SIGTRAP: + /* + 由断点指令或其它trap指令产生: + 部分系统框架里面会用 __builtin_trap() 来产生一个 SIGTRAP 类型的 Crash + */ + return @"SIGTRAP"; + default: + return @"UNKNOWN"; + } +} + + @end diff --git a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m index 1a82732e..150386d7 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m @@ -82,6 +82,7 @@ - (void)setupUI { [self.view addSubview:self.textView]; [SLCrashHandler defaultCrashHandler].delegate = self; + } #pragma mark - SLCrashHandlerDelegate @@ -124,6 +125,7 @@ - (void)testArray { strings[1] = nilStr; NSArray *array2 = [NSArray arrayWithObjects:strings count:2]; NSArray *array3 = [NSArray arrayWithObject:nil]; + } ///可变数组防护 越界和nil值 - (void)testMutableArray { diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index aa4dfbfe..68ea7d1c 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -4,6 +4,9 @@ 3. 预处理、延时加载、按需加载 4. 三级缓存 5. 使用正确的API +6. 启动连续闪退保护 +7. Crash防护 +8. diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index e47e0605..d08d6293 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -19,3 +19,5 @@ * 16、[性能优化](https://github.com/skyming/iOS-Performance-Optimization) * 17、[阿里、字节 一套高效的iOS面试题解答](https://github.com/colourful987/bytedance-alibaba-interview) * 18、[面试题、基础知识点](https://github.com/liberalisman/iOS-InterviewQuestion-collection) +* 19、[音视频笔记-雷霄骅](https://blog.csdn.net/leixiaohua1020) +* 20、[Joy___](https://www.jianshu.com/u/9c51a213b02e) From 4d2281ba9791a7ce2f8f00cef3c82ef54af195f5 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 22 Jul 2020 18:32:04 +0800 Subject: [PATCH 095/356] APM --- .../Crash/SLCrashProtector/SLCrashHandler.m | 20 ++++++++++--------- .../WorkIssues/APM/SLAPMViewController.m | 4 +++- .../WorkIssues/\347\254\224\350\256\260.md" | 2 +- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m index 2cc1eb0a..d6928c48 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m @@ -43,19 +43,21 @@ - (void)setUncaughtExceptionHandler{ ///先获取保留其他三方的异常Handler otherUncaughtExceptionHandler = NSGetUncaughtExceptionHandler(); ///注册自己的异常Handler - NSSetUncaughtExceptionHandler (SL_HandleException); + NSSetUncaughtExceptionHandler (SL_UncaughtExceptionHandler); ///注册信号Handler - signal(SIGABRT, sl_uncaughtSignalHandler); - signal(SIGILL, sl_uncaughtSignalHandler); - signal(SIGSEGV, sl_uncaughtSignalHandler); - signal(SIGFPE, sl_uncaughtSignalHandler); - signal(SIGBUS, sl_uncaughtSignalHandler); - signal(SIGPIPE, sl_uncaughtSignalHandler); + signal(SIGABRT, SL_UncaughtSignalHandler); + signal(SIGILL, SL_UncaughtSignalHandler); + signal(SIGSEGV, SL_UncaughtSignalHandler); + signal(SIGFPE, SL_UncaughtSignalHandler); + signal(SIGBUS, SL_UncaughtSignalHandler); + signal(SIGPIPE, SL_UncaughtSignalHandler); + signal(SIGKILL, SL_UncaughtSignalHandler); + signal(SIGTRAP, SL_UncaughtSignalHandler); } ///异常捕获处理 -void SL_HandleException(NSException *exception) { +void SL_UncaughtExceptionHandler(NSException *exception) { if (otherUncaughtExceptionHandler) { //如果其他三方也有注册,则也执行其他三方的Handle,然后在执行自己的 otherUncaughtExceptionHandler(exception); @@ -67,7 +69,7 @@ void SL_HandleException(NSException *exception) { ///异常信号处理回调 -void sl_uncaughtSignalHandler(int signal) { +void SL_UncaughtSignalHandler(int signal) { NSString *exceptionInfo = [NSString stringWithFormat:@"异常信号:%@ Crash",signalName(signal)]; SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeUnknow errorDesc:exceptionInfo exception:nil callStack:[NSThread callStackSymbols]]; [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m index 39504ff5..1598b0aa 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m @@ -11,7 +11,9 @@ /* - 参考资料:https://www.jianshu.com/p/95df83780c8f + 参考资料: + https://www.jianshu.com/p/95df83780c8f + https://www.jianshu.com/p/8123fc17fe0e */ @interface SLAPMViewController () diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 68ea7d1c..ea0c6991 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -1,4 +1,4 @@ - 一、性能优化 + 一、APM/性能优化 1. 优化业务流程 2. 合理的线程分配 3. 预处理、延时加载、按需加载 From 638017324e7f2c3e8f8f547e2572ec1a1e96d48e Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 23 Jul 2020 18:10:47 +0800 Subject: [PATCH 096/356] =?UTF-8?q?=E9=AB=98=E8=B4=A8=E9=87=8F=E6=8A=80?= =?UTF-8?q?=E6=9C=AF=E5=8D=9A=E5=AE=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xcshareddata/xcschemes/DarkMode.xcscheme | 2 +- iOS_Tips/DarkMode/Crash/SLCrashViewController.m | 7 ++++++- ...217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 4 ++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/iOS_Tips/DarkMode.xcodeproj/xcshareddata/xcschemes/DarkMode.xcscheme b/iOS_Tips/DarkMode.xcodeproj/xcshareddata/xcschemes/DarkMode.xcscheme index d70c5f89..c3deb5d7 100644 --- a/iOS_Tips/DarkMode.xcodeproj/xcshareddata/xcschemes/DarkMode.xcscheme +++ b/iOS_Tips/DarkMode.xcodeproj/xcshareddata/xcschemes/DarkMode.xcscheme @@ -51,7 +51,7 @@ @property (nonatomic, strong) UITextView *textView; - @property (nonatomic, copy) void(^testBlock)(void); //测试循环引用 @property (nonatomic, strong) NSMutableArray *testMArray; //测试循环引用 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index d08d6293..4b6f3218 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -21,3 +21,7 @@ * 18、[面试题、基础知识点](https://github.com/liberalisman/iOS-InterviewQuestion-collection) * 19、[音视频笔记-雷霄骅](https://blog.csdn.net/leixiaohua1020) * 20、[Joy___](https://www.jianshu.com/u/9c51a213b02e) +* 21、[maniac_kk](https://juejin.im/user/5aaf755cf265da23870ea3cf/posts) +* 22、[阿里巴巴淘系技术](https://juejin.im/user/5e8558f3518825738f2b1327) +* 23、[欧阳大哥2013](https://juejin.im/user/593fb40eda2f6000673bdc61) +* 24、[Wangkai](https://juejin.im/user/5bf20f696fb9a049fb4340b0) From 0fe95befc18ec680400809004897f4bf2b80e32d Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 23 Jul 2020 18:40:54 +0800 Subject: [PATCH 097/356] =?UTF-8?q?iOS=20=20APM=20=E7=BA=BF=E7=A8=8B?= =?UTF-8?q?=E6=95=B0=E9=87=8F=E7=9B=91=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 6 ++ .../WorkIssues/APM/SLAPMThreadCount.h | 18 ++++ .../WorkIssues/APM/SLAPMThreadCount.m | 94 +++++++++++++++++++ 3 files changed, 118 insertions(+) create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.h create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.m diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 0e5cd8d9..226ae41b 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -121,6 +121,7 @@ 788ACD622390BFD400737EC2 /* SLLoadImageVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 788ACD612390BFD400737EC2 /* SLLoadImageVC.m */; }; 788ACD652390EA3A00737EC2 /* SLCubeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 788ACD642390EA3A00737EC2 /* SLCubeViewController.m */; }; 788ADB382441F48F00302CD9 /* SLCrashViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 788ADB362441F48F00302CD9 /* SLCrashViewController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 789AD16324C99DCA00CB0B4C /* SLAPMThreadCount.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD16224C99DCA00CB0B4C /* SLAPMThreadCount.m */; }; 78A179A8249B0AA8006F52E3 /* NSDictionary+SLExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A179A6249B0AA8006F52E3 /* NSDictionary+SLExtension.m */; }; 78A1998C2451BEE7005B2B4B /* UIButton+SLTitleImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A1998B2451BEE7005B2B4B /* UIButton+SLTitleImage.m */; }; 78A1998F2451C049005B2B4B /* SLButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A1998E2451C049005B2B4B /* SLButton.m */; }; @@ -378,6 +379,8 @@ 788ACD642390EA3A00737EC2 /* SLCubeViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLCubeViewController.m; sourceTree = ""; }; 788ADB352441F48F00302CD9 /* SLCrashViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLCrashViewController.h; sourceTree = ""; }; 788ADB362441F48F00302CD9 /* SLCrashViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLCrashViewController.m; sourceTree = ""; }; + 789AD16124C99DCA00CB0B4C /* SLAPMThreadCount.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMThreadCount.h; sourceTree = ""; }; + 789AD16224C99DCA00CB0B4C /* SLAPMThreadCount.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMThreadCount.m; sourceTree = ""; }; 78A179A6249B0AA8006F52E3 /* NSDictionary+SLExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+SLExtension.m"; sourceTree = ""; }; 78A179A7249B0AA8006F52E3 /* NSDictionary+SLExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+SLExtension.h"; sourceTree = ""; }; 78A1998A2451BEE7005B2B4B /* UIButton+SLTitleImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIButton+SLTitleImage.h"; sourceTree = ""; }; @@ -628,6 +631,8 @@ 784C4C3924C2EE6600D5C199 /* SLAPMMemoryDisk.m */, 784C4BEB24BDA5D700D5C199 /* SLAPMFluency.h */, 784C4BEC24BDA5D700D5C199 /* SLAPMFluency.m */, + 789AD16124C99DCA00CB0B4C /* SLAPMThreadCount.h */, + 789AD16224C99DCA00CB0B4C /* SLAPMThreadCount.m */, ); path = APM; sourceTree = ""; @@ -1463,6 +1468,7 @@ 784C4C3A24C2EE6600D5C199 /* SLAPMMemoryDisk.m in Sources */, 78842468248FAED100C2E505 /* SLColorPickerViewController.m in Sources */, 787C7DCF2462B03D005DF7ED /* UINavigationController+SLMLeakFinder.m in Sources */, + 789AD16324C99DCA00CB0B4C /* SLAPMThreadCount.m in Sources */, 788ACD622390BFD400737EC2 /* SLLoadImageVC.m in Sources */, 78E72D5C247BDDE700751373 /* SLWebTableViewController2.m in Sources */, 78842454248F863500C2E505 /* SLTableViewController.m in Sources */, diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.h b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.h new file mode 100644 index 00000000..bdfa9194 --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.h @@ -0,0 +1,18 @@ +// +// SLAPMThreadCount.h +// DarkMode +// +// Created by wsl on 2020/7/23. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +///监控线程数量 参考:https://juejin.im/post/5e92a113e51d4547134bdadb +@interface SLAPMThreadCount : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.m new file mode 100644 index 00000000..a4d0966c --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.m @@ -0,0 +1,94 @@ +// +// SLAPMThreadCount.m +// DarkMode +// +// Created by wsl on 2020/7/23. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLAPMThreadCount.h" +#include +#include + +#ifndef kk_dispatch_main_async_safe +#define kk_dispatch_main_async_safe(block)\ +if (dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) == dispatch_queue_get_label(dispatch_get_main_queue())) {\ + block();\ +} else {\ + dispatch_async(dispatch_get_main_queue(), block);\ +} +#endif + +static pthread_introspection_hook_t old_pthread_introspection_hook_t = NULL; +static int threadCount = 0; +#define KK_THRESHOLD 40 +static const int threadIncreaseThreshold = 10; + +//线程数量超过40,就会弹窗警告,并且控制台打印所有线程的堆栈;之后阈值每增加5条(45、50、55...)同样警告+打印堆栈;如果线程数量再次少于40条,阈值恢复到40 +static int maxThreadCountThreshold = KK_THRESHOLD; +static dispatch_semaphore_t global_semaphore; +static int threadCountIncrease = 0; +static bool isMonitor = false; + +@implementation SLAPMThreadCount + ++ (void)startMonitor { + global_semaphore = dispatch_semaphore_create(1); + dispatch_semaphore_wait(global_semaphore, DISPATCH_TIME_FOREVER); + mach_msg_type_number_t count; + thread_act_array_t threads; + task_threads(mach_task_self(), &threads, &count); + threadCount = count; //加解锁之间,保证线程的数量不变 + old_pthread_introspection_hook_t = pthread_introspection_hook_install(kk_pthread_introspection_hook_t); + dispatch_semaphore_signal(global_semaphore); + + isMonitor = true; + kk_dispatch_main_async_safe(^{ + [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(clearThreadCountIncrease) userInfo:nil repeats:YES]; + }); +} ++ (void)clearThreadCountIncrease +{ + threadCountIncrease = 0; +} + +void kk_pthread_introspection_hook_t(unsigned int event, +pthread_t thread, void *addr, size_t size) +{ + if (old_pthread_introspection_hook_t) { + old_pthread_introspection_hook_t(event, thread, addr, size); + } + if (event == PTHREAD_INTROSPECTION_THREAD_CREATE) { + threadCount = threadCount + 1; + if (isMonitor && (threadCount > maxThreadCountThreshold)) { + maxThreadCountThreshold += 5; + kk_Alert_Log_CallStack(false, 0); + } + threadCountIncrease = threadCountIncrease + 1; + if (isMonitor && (threadCountIncrease > threadIncreaseThreshold)) { + kk_Alert_Log_CallStack(true, threadCountIncrease); + } + } + else if (event == PTHREAD_INTROSPECTION_THREAD_DESTROY){ + threadCount = threadCount - 1; + if (threadCount < KK_THRESHOLD) { + maxThreadCountThreshold = KK_THRESHOLD; + } + if (threadCountIncrease > 0) { + threadCountIncrease = threadCountIncrease - 1; + } + } +} + +void kk_Alert_Log_CallStack(bool isIncreaseLog, int num) +{ + dispatch_semaphore_wait(global_semaphore, DISPATCH_TIME_FOREVER); + if (isIncreaseLog) { + printf("\n🔥💥💥💥💥💥一秒钟开启 %d 条线程!💥💥💥💥💥🔥\n", num); + } +// [KKCallStack callStackWithType:KKCallStackTypeAll]; + dispatch_semaphore_signal(global_semaphore); +} + +@end + From 3c0a3afa117da74ec34edba198e0b0f86d6c41d7 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 23 Jul 2020 18:56:30 +0800 Subject: [PATCH 098/356] =?UTF-8?q?iOS=20=20APM=20=E7=BA=BF=E7=A8=8B?= =?UTF-8?q?=E6=95=B0=E9=87=8F=E7=9B=91=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.m | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.m index a4d0966c..8d87b38e 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.m @@ -20,18 +20,19 @@ #endif static pthread_introspection_hook_t old_pthread_introspection_hook_t = NULL; -static int threadCount = 0; -#define KK_THRESHOLD 40 -static const int threadIncreaseThreshold = 10; +static int threadCount = 0; //线程数量 +#define KK_THRESHOLD 40 //线程数量阈值 +static const int threadIncreaseThreshold = 10; //线程增量阈值 //线程数量超过40,就会弹窗警告,并且控制台打印所有线程的堆栈;之后阈值每增加5条(45、50、55...)同样警告+打印堆栈;如果线程数量再次少于40条,阈值恢复到40 static int maxThreadCountThreshold = KK_THRESHOLD; -static dispatch_semaphore_t global_semaphore; -static int threadCountIncrease = 0; +static dispatch_semaphore_t global_semaphore; //信号量 保证线程安全 +static int threadCountIncrease = 0; //线程增长数量 static bool isMonitor = false; @implementation SLAPMThreadCount +//调用startMonitor函数,开始监控线程数量。在这个函数里用global_semaphore来保证,task_threads获取的线程数量,到hook完成,线程数量不会变化(加解锁之间,没有线程新建跟销毁)。 + (void)startMonitor { global_semaphore = dispatch_semaphore_create(1); dispatch_semaphore_wait(global_semaphore, DISPATCH_TIME_FOREVER); @@ -47,6 +48,7 @@ + (void)startMonitor { [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(clearThreadCountIncrease) userInfo:nil repeats:YES]; }); } +//定时器每一秒都将线程增长数置0 + (void)clearThreadCountIncrease { threadCountIncrease = 0; From 65452dc36294e57096a5c9712ea1fcd40bdeb337 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 24 Jul 2020 17:56:29 +0800 Subject: [PATCH 099/356] =?UTF-8?q?iOS=20APM=E7=9B=91=E6=8E=A7=E4=B9=8B?= =?UTF-8?q?=E7=BA=BF=E7=A8=8B=E6=95=B0=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xcshareddata/xcschemes/DarkMode.xcscheme | 2 +- .../DarkMode/WorkIssues/APM/SLAPMFluency.h | 4 +- .../DarkMode/WorkIssues/APM/SLAPMFluency.m | 4 +- .../DarkMode/WorkIssues/APM/SLAPMManager.h | 4 +- .../DarkMode/WorkIssues/APM/SLAPMManager.m | 13 ++- .../WorkIssues/APM/SLAPMThreadCount.h | 7 +- .../WorkIssues/APM/SLAPMThreadCount.m | 81 +++++++++++++++---- .../WorkIssues/APM/SLAPMViewController.m | 7 +- .../SLBinaryResetViewController.m" | 21 +++-- .../wsl.order" | 17 ---- 10 files changed, 108 insertions(+), 52 deletions(-) diff --git a/iOS_Tips/DarkMode.xcodeproj/xcshareddata/xcschemes/DarkMode.xcscheme b/iOS_Tips/DarkMode.xcodeproj/xcshareddata/xcschemes/DarkMode.xcscheme index c3deb5d7..d70c5f89 100644 --- a/iOS_Tips/DarkMode.xcodeproj/xcshareddata/xcschemes/DarkMode.xcscheme +++ b/iOS_Tips/DarkMode.xcodeproj/xcshareddata/xcschemes/DarkMode.xcscheme @@ -51,7 +51,7 @@ @@ -49,17 +50,20 @@ - (void)startMonitoring { _isMonitoring = YES; if ((self.type & SLAPMTypeCpu) == SLAPMTypeCpu || (self.type & SLAPMTypeMemory) == SLAPMTypeMemory || self.type == SLAPMTypeAll) { - _taskName = [SLTimer execTask:self selector:@selector(monitoring) start:0 interval:1.0/60 repeats:YES async:YES]; + _taskName = [SLTimer execTask:self selector:@selector(monitoring) start:0.5 interval:1.0/60 repeats:YES async:YES]; } - if ((self.type & SLAPMTypeCpu) == SLAPMTypeCrash || self.type == SLAPMTypeAll) { [SLCrashHandler defaultCrashHandler].delegate = self; } if ((self.type & SLAPMTypeFluency) == SLAPMTypeFluency || self.type == SLAPMTypeAll) { [SLAPMFluency sharedInstance].delegate = self; - [[SLAPMFluency sharedInstance] startMonitoring]; + [[SLAPMFluency sharedInstance] startMonitorFluency]; + } + + if ((self.type & SLAPMTypeThreadCount) == SLAPMTypeThreadCount || self.type == SLAPMTypeAll) { + [SLAPMThreadCount startMonitorThreadCount]; } } @@ -70,7 +74,8 @@ - (void)stopMonitoring { [SLTimer cancelTask:_taskName]; [SLAPMFluency sharedInstance].delegate = nil; - [[SLAPMFluency sharedInstance] stopMonitoring]; + [[SLAPMFluency sharedInstance] stopMonitorFluency]; + [SLAPMThreadCount stopMonitorThreadCount]; } #pragma mark - Monitoring diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.h b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.h index bdfa9194..a3739c22 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.h +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.h @@ -10,9 +10,14 @@ NS_ASSUME_NONNULL_BEGIN -///监控线程数量 参考:https://juejin.im/post/5e92a113e51d4547134bdadb +///监控线程数量 来源:https://juejin.im/post/5e92a113e51d4547134bdadb @interface SLAPMThreadCount : NSObject +///开始监听 ++ (void)startMonitorThreadCount; +///结束监听 ++ (void)stopMonitorThreadCount; + @end NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.m index 8d87b38e..17ae5d8a 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.m @@ -9,43 +9,57 @@ #import "SLAPMThreadCount.h" #include #include +#import "SLTimer.h" + +#import "BSBacktraceLogger.h" #ifndef kk_dispatch_main_async_safe #define kk_dispatch_main_async_safe(block)\ if (dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) == dispatch_queue_get_label(dispatch_get_main_queue())) {\ - block();\ +block();\ } else {\ - dispatch_async(dispatch_get_main_queue(), block);\ +dispatch_async(dispatch_get_main_queue(), block);\ } #endif -static pthread_introspection_hook_t old_pthread_introspection_hook_t = NULL; +static pthread_introspection_hook_t old_pthread_introspection_hook_t = NULL; //hook前原来的函数指针 static int threadCount = 0; //线程数量 -#define KK_THRESHOLD 40 //线程数量阈值 -static const int threadIncreaseThreshold = 10; //线程增量阈值 +#define KK_THRESHOLD 40 //线程总数量阈值 +static const int threadIncreaseThreshold = 10; //线程1秒内的增量阈值 //线程数量超过40,就会弹窗警告,并且控制台打印所有线程的堆栈;之后阈值每增加5条(45、50、55...)同样警告+打印堆栈;如果线程数量再次少于40条,阈值恢复到40 static int maxThreadCountThreshold = KK_THRESHOLD; static dispatch_semaphore_t global_semaphore; //信号量 保证线程安全 static int threadCountIncrease = 0; //线程增长数量 -static bool isMonitor = false; +static bool isMonitor = false; //是否正在监测 +static NSString *taskName; //任务ID @implementation SLAPMThreadCount -//调用startMonitor函数,开始监控线程数量。在这个函数里用global_semaphore来保证,task_threads获取的线程数量,到hook完成,线程数量不会变化(加解锁之间,没有线程新建跟销毁)。 -+ (void)startMonitor { +///调用startMonitor函数,开始监控线程数量。在这个函数里用global_semaphore来保证,task_threads获取的线程数量,到hook完成,线程数量不会变化(加解锁之间,没有线程新建跟销毁)。 ++ (void)startMonitorThreadCount { + if (isMonitor) return; global_semaphore = dispatch_semaphore_create(1); dispatch_semaphore_wait(global_semaphore, DISPATCH_TIME_FOREVER); mach_msg_type_number_t count; thread_act_array_t threads; + //获取线程数量 task_threads(mach_task_self(), &threads, &count); - threadCount = count; //加解锁之间,保证线程的数量不变 + //加解锁之间,保证线程的数量不变 + threadCount = count; + /* + 看这个函数名,很像我们平时hook函数一样的。 + 返回值是上面声明的old_pthread_introspection_hook_t函数指针:返回原线程生命周期函数。 + 参数也是函数指针:传入的是我们自定义的线程生命周期函数 + */ old_pthread_introspection_hook_t = pthread_introspection_hook_install(kk_pthread_introspection_hook_t); dispatch_semaphore_signal(global_semaphore); isMonitor = true; + + //判断是否在主线程 kk_dispatch_main_async_safe(^{ - [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(clearThreadCountIncrease) userInfo:nil repeats:YES]; + taskName = [SLTimer execTask:self selector:@selector(clearThreadCountIncrease) start:0 interval:1.0 repeats:YES async:NO]; }); } //定时器每一秒都将线程增长数置0 @@ -53,43 +67,76 @@ + (void)clearThreadCountIncrease { threadCountIncrease = 0; } +///结束监听 ++ (void)stopMonitorThreadCount { + if (!global_semaphore || !taskName) { + return; + } + dispatch_semaphore_wait(global_semaphore, DISPATCH_TIME_FOREVER); + pthread_introspection_hook_t lastHook = pthread_introspection_hook_install(old_pthread_introspection_hook_t); + isMonitor = NO; + [SLTimer cancelTask:taskName]; + dispatch_semaphore_signal(global_semaphore); +} +/** + 定义函数指针:pthread_introspection_hook_t + event : 线程处于的生命周期(下面枚举了线程的4个生命周期) + thread :线程 + addr :线程栈内存基址 + size :线程栈内存可用大小 + enum { + PTHREAD_INTROSPECTION_THREAD_CREATE = 1, //创建线程 + PTHREAD_INTROSPECTION_THREAD_START, // 线程开始运行 + PTHREAD_INTROSPECTION_THREAD_TERMINATE, //线程运行终止 + PTHREAD_INTROSPECTION_THREAD_DESTROY, //销毁线程 + }; + */ void kk_pthread_introspection_hook_t(unsigned int event, -pthread_t thread, void *addr, size_t size) + pthread_t thread, void *addr, size_t size) { if (old_pthread_introspection_hook_t) { + //执行原来的线程生命周期函数 old_pthread_introspection_hook_t(event, thread, addr, size); } + + dispatch_semaphore_wait(global_semaphore, DISPATCH_TIME_FOREVER); if (event == PTHREAD_INTROSPECTION_THREAD_CREATE) { - threadCount = threadCount + 1; + //创建线程 + threadCount = threadCount + 1; //线程总量加1 if (isMonitor && (threadCount > maxThreadCountThreshold)) { + //如果线程总数大于监测的阈值,阈值+5;发出警告⚠️ maxThreadCountThreshold += 5; kk_Alert_Log_CallStack(false, 0); } threadCountIncrease = threadCountIncrease + 1; if (isMonitor && (threadCountIncrease > threadIncreaseThreshold)) { + //如果线程在1秒内的增长数超过了阈值,发出警告⚠️ kk_Alert_Log_CallStack(true, threadCountIncrease); } } else if (event == PTHREAD_INTROSPECTION_THREAD_DESTROY){ - threadCount = threadCount - 1; + //销毁线程 + threadCount = threadCount - 1; //线程总量-1 if (threadCount < KK_THRESHOLD) { + //如果线程数量再次少于40条,阈值恢复到40 maxThreadCountThreshold = KK_THRESHOLD; } if (threadCountIncrease > 0) { + //线程增量-1 threadCountIncrease = threadCountIncrease - 1; } } + dispatch_semaphore_signal(global_semaphore); } +///发出警告 输出调用堆栈 void kk_Alert_Log_CallStack(bool isIncreaseLog, int num) { - dispatch_semaphore_wait(global_semaphore, DISPATCH_TIME_FOREVER); if (isIncreaseLog) { - printf("\n🔥💥💥💥💥💥一秒钟开启 %d 条线程!💥💥💥💥💥🔥\n", num); + NSLog(@"⚠️ 1秒钟开启了 %d 条线程!", num); } -// [KKCallStack callStackWithType:KKCallStackTypeAll]; - dispatch_semaphore_signal(global_semaphore); + NSLog(@"⚠️ 线程监听:%@",[BSBacktraceLogger bs_backtraceOfAllThread]); } @end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m index 1598b0aa..5db5589e 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m @@ -28,13 +28,16 @@ - (void)viewDidLoad { self.view.backgroundColor = [UIColor whiteColor]; self.navigationItem.title = @"APM监控"; [self setupNavigationBar]; - [SLAPMManager manager].type = SLAPMTypeFluency; + [SLAPMManager manager].type = SLAPMTypeThreadCount; } //测试卡顿 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { //耗时任务 - sleep(1); +// sleep(1); + dispatch_async(dispatch_get_global_queue(0, 0), ^{ + sleep(1); + }); } #pragma mark - UI diff --git "a/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.m" "b/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.m" index 941e3929..5893b7e9 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.m" @@ -10,6 +10,7 @@ #import #import +static BOOL isBecomeActive = NO; //是否启动完成,即首页渲染完毕 @interface SLBinaryResetViewController () @property (nonatomic, strong) UITextView *textView; @end @@ -42,7 +43,7 @@ - (void)getOrderFile{ BOOL isObjc = [name hasPrefix:@"+["] || [name hasPrefix:@"-["]; NSString * symbolName = isObjc ? name: [@"_" stringByAppendingString:name]; [symbolNames addObject:symbolName]; -// NSLog(@"%@",symbolName); + // NSLog(@"%@",symbolName); } //取反 NSEnumerator * emt = [symbolNames reverseObjectEnumerator]; @@ -99,9 +100,14 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, 静态插桩,相当于此函数在编译时插在了每一个函数体里,这个函数会捕获到所有程序运行过程中执行的方法。 我们只需要捕获应用启动时执行的方法就行,把启动过程中执行的函数地址存储在symbolList中。 */ +static void*previousPc; void __sanitizer_cov_trace_pc_guard(uint32_t *guard) { // if (!*guard) return; // Duplicate the guard check. /* 精确定位 哪里开始 到哪里结束! 在这里面做判断写条件!*/ + if(isBecomeActive) { + //如果启动完成,后序的函数执行顺序完全取决于用户的操作,就不需要捕获了,只要捕获启动时首页渲染完毕时即可 + return; + } //它的作用其实就是去读取 x30寄存器 中所存储的要返回时下一条指令的地址. 所以他名称叫做 __builtin_return_address . 换句话说 , 这个地址就是我当前这个函数执行完毕后 , 要返回到哪里去的函数地址 . void *PC = __builtin_return_address(0); @@ -109,14 +115,19 @@ void __sanitizer_cov_trace_pc_guard(uint32_t *guard) { SLSymbolNode *node = malloc(sizeof(SLSymbolNode)); *node = (SLSymbolNode){PC,NULL}; - //根据内存地址获取函数名称 + //防止循环引用,故在此过滤 + if (previousPc == PC) { return; } + previousPc = PC; + Dl_info info; dladdr(node->pc, &info); + //根据内存地址获取函数名称 NSString * name = @(info.dli_sname); - //这个方法会导致循环引用,故在此过滤 - if ([name isEqualToString:@"-[NSMutableArray(SLCrashProtector) sl_insertObject:atIndex:]"] || [name isEqualToString:@"-[NSObject(SLCrashProtector) sl_KVODealloc]"]) { - return; + //首页渲染完毕,即-[SceneDelegate sceneDidBecomeActive:]执行完毕后 + if ([name isEqualToString:@"-[SceneDelegate sceneDidBecomeActive:]"]) { + isBecomeActive = YES; } + //入队 // offsetof 用在这里是为了入队添加下一个节点找到 前一个节点next指针的位置 OSAtomicEnqueue(&symbolList, node, offsetof(SLSymbolNode, next)); diff --git "a/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/wsl.order" "b/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/wsl.order" index 895addbb..3ff2cdf2 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/wsl.order" +++ "b/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/wsl.order" @@ -64,20 +64,3 @@ _SLSetUncaughtExceptionHandler -[ViewController viewWillAppear:] -[ViewController tableView:cellForRowAtIndexPath:] -[SceneDelegate sceneDidBecomeActive:] --[NSString(SLCrashProtector) sl_substringToIndex:] --[NSString(SLCrashProtector) sl_substringFromIndex:] --[SLNavigationController gestureRecognizer:shouldReceiveTouch:] --[ViewController tableView:didSelectRowAtIndexPath:] --[UINavigationController(SLMLeakFinder) sl_pushViewController:animated:] --[SLWorkIssuesViewController prefersStatusBarHidden] --[SLWorkIssuesViewController viewDidLoad] --[SLWorkIssuesViewController setupUI] --[SLWorkIssuesViewController getData] --[SLWorkIssuesViewController titlesArray] --[SLWorkIssuesViewController urlArray] --[SLWorkIssuesViewController classArray] --[SLWorkIssuesViewController tableView:numberOfRowsInSection:] --[SLWorkIssuesViewController viewWillAppear:] --[SLWorkIssuesViewController tableView:cellForRowAtIndexPath:] --[SLWorkIssuesViewController tableView:didSelectRowAtIndexPath:] --[SLBinaryResetViewController viewDidLoad] From 74fc310908e2722f6b034557a0459a5be90f8f68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Fri, 24 Jul 2020 18:01:15 +0800 Subject: [PATCH 100/356] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9727465a..99e93d9a 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ #### 6.7-[二进制重排优化启动速度](https://juejin.im/post/5ea79839f265da7bba509590) #### 6.8-[iOS APM应用性能监控管理(doing)]() -> CPU占用率、内存/磁盘使用率、卡顿监控定位 ...... +> CPU占用率、内存/磁盘使用率、卡顿监控定位、Crash防护、线程数量监控 ...... ## 7-iOSCrash防护 From da8ba276f6419e00dddd6939e6a4a566824090f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Fri, 24 Jul 2020 18:08:15 +0800 Subject: [PATCH 101/356] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 99e93d9a..bb94766a 100644 --- a/README.md +++ b/README.md @@ -143,7 +143,7 @@ > * 1、主工程就是iOS_Tips下的DarkMode,别怀疑🤣,历史遗留问题😁😀,大部分内容都在里面,run一下就明白了🤝; > * 2、该demo里面有些功能还没有写博客介绍,后期有时间会补上,不过代码我一般喜欢写注释,所以我相信大家读起来应该也容易理解,建议大家看完之后,自己也可以写写,把整个流程过一遍,也许会比我写的更好哟; -> * 3、[看过的高质量技术博客集合](iOS_Tips/DarkMode/WorkIssues/高质量技术博客.md),这些博客质量都挺高的,都出自各个大厂、大佬之后,认真看完绝对干活满满; +> * 3、[看过的高质量技术博客集合](iOS_Tips/DarkMode/WorkIssues/高质量技术博客.md),这些博客质量都挺高的,都出自各个大厂、大佬之手,认真看完绝对干活满满; > * 4、小视频拍摄录制失败,主要集中在plus和X系列手机上:可能是由于写入的视频宽高videoSize设置的问题,各位可以先试试这样设置 avCaptureTool.videoSize = CGSizeMake(self.view.width * 0.8, self.view.height * 0.8); From b84f9a572ab0279594d314661653c6712fabb2a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Fri, 24 Jul 2020 19:13:59 +0800 Subject: [PATCH 102/356] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index bb94766a..cf51b54a 100644 --- a/README.md +++ b/README.md @@ -146,6 +146,7 @@ > * 3、[看过的高质量技术博客集合](iOS_Tips/DarkMode/WorkIssues/高质量技术博客.md),这些博客质量都挺高的,都出自各个大厂、大佬之手,认真看完绝对干活满满; > * 4、小视频拍摄录制失败,主要集中在plus和X系列手机上:可能是由于写入的视频宽高videoSize设置的问题,各位可以先试试这样设置 avCaptureTool.videoSize = CGSizeMake(self.view.width * 0.8, self.view.height * 0.8); +> * 5、当你编译的时候,XCode出现Unable to load contents of file list 错误,导致出现此原因是pods版本不一致,请更新pods版本或者重新安装。 #### Welcome to you 👏 您的follow和start,是我前进的动力,Thanks♪(・ω・)ノ 🤝 From 10cef1511e2098f7e677fcea6cccfc676af4eb89 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 24 Jul 2020 19:23:02 +0800 Subject: [PATCH 103/356] =?UTF-8?q?=E4=BA=8C=E8=BF=9B=E5=88=B6=E9=87=8D?= =?UTF-8?q?=E6=8E=92=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m | 1 + 1 file changed, 1 insertion(+) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m index 5db5589e..7693b49e 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m @@ -14,6 +14,7 @@ 参考资料: https://www.jianshu.com/p/95df83780c8f https://www.jianshu.com/p/8123fc17fe0e + https://juejin.im/post/5e92a113e51d4547134bdadb */ @interface SLAPMViewController () From 4d0c88366185299fca82c23c7ff76e9917d86f0b Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 27 Jul 2020 20:31:47 +0800 Subject: [PATCH 104/356] =?UTF-8?q?=E9=AB=98=E8=B4=A8=E9=87=8F=E7=9A=84?= =?UTF-8?q?=E5=8D=9A=E5=AE=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 2 ++ ...\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 2 files changed, 3 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index ea0c6991..5eddee1a 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -8,6 +8,8 @@ 7. Crash防护 8. +二、[iOS程序员的自我修养](https://juejin.im/post/5d5273b1f265da03f233c2d6) + diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 4b6f3218..cdde78f8 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -25,3 +25,4 @@ * 22、[阿里巴巴淘系技术](https://juejin.im/user/5e8558f3518825738f2b1327) * 23、[欧阳大哥2013](https://juejin.im/user/593fb40eda2f6000673bdc61) * 24、[Wangkai](https://juejin.im/user/5bf20f696fb9a049fb4340b0) +* 25、[maniac_kk](https://juejin.im/user/5aaf755cf265da23870ea3cf/posts) From 77886f3ce171fbb8c217f724a42833f0bc23b0ae Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 29 Jul 2020 11:52:33 +0800 Subject: [PATCH 105/356] =?UTF-8?q?iOS=20=20Crash=E6=8D=95=E8=8E=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/.DS_Store | Bin 10244 -> 10244 bytes .../Crash/SLCrashProtector/SLCrashHandler.m | 128 ++++++++++++++---- .../DarkMode/Crash/SLCrashViewController.m | 13 +- .../WorkIssues/\347\254\224\350\256\260.md" | 6 +- 4 files changed, 116 insertions(+), 31 deletions(-) diff --git a/iOS_Tips/.DS_Store b/iOS_Tips/.DS_Store index 9963f42397c120b4c5e455f0a5600b2163f9f9e1..2673fac1a1a3f5cd6d9f279b0dd94795ad22cafb 100644 GIT binary patch delta 41 ucmZn(XbIS$D#^@JZan#ogpNQ#hGB4Wer^E+2(WBmm~0>=x4B8Oi4On +#import + @implementation SLCrashError + (instancetype)errorWithErrorType:(SLCrashErrorType)errorType errorDesc:(NSString *)errorDesc exception:(NSException *)exception callStack:(NSArray*)callStackSymbol { SLCrashError *crashError = [SLCrashError new]; @@ -31,21 +34,84 @@ + (instancetype)defaultCrashHandler { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ crashHandler = [[SLCrashHandler alloc] init]; - [crashHandler setUncaughtExceptionHandler]; + [crashHandler setCaughtCrashHandler]; }); return crashHandler; } -/// 其他三方注册的异常处理 handler -static NSUncaughtExceptionHandler *otherUncaughtExceptionHandler = NULL; -///设置异常捕获回调 -- (void)setUncaughtExceptionHandler{ - ///先获取保留其他三方的异常Handler - otherUncaughtExceptionHandler = NSGetUncaughtExceptionHandler(); - ///注册自己的异常Handler - NSSetUncaughtExceptionHandler (SL_UncaughtExceptionHandler); +/// 捕获Mach、Signal、NSException 异常Crash +- (void)setCaughtCrashHandler { + [self setMachHandler]; + [self setSignalHandler]; + [self setExceptionHandler]; +} + +#pragma mark - Mach异常捕获 +// 创建Mach Port并监听消息 +- (void)setMachHandler { + mach_port_t server_port; + ///创建异常端口 + kern_return_t kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &server_port); + assert(kr == KERN_SUCCESS); + NSLog(@"create a port: %d", server_port); + + ///申请set_exception_ports 的权限 + kr = mach_port_insert_right(mach_task_self(), server_port, server_port, MACH_MSG_TYPE_MAKE_SEND); + assert(kr == KERN_SUCCESS); - ///注册信号Handler + ///设置异常端口 EXC_MASK_CRASH 捕获Mach_CRASH时会导致死锁 + kr = task_set_exception_ports(mach_task_self(), EXC_MASK_BAD_ACCESS, server_port, EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE); + + ///循环等待异常消息 + [self setMachPortListener:server_port]; +} + +- (void)setMachPortListener:(mach_port_t)mach_port { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + + __Request__exception_raise_state_identity_t mach_message; + + mach_message.Head.msgh_size = 1024; + mach_message.Head.msgh_local_port = mach_port; + + mach_msg_return_t mr; + + while (true) { + mr = mach_msg(&mach_message.Head, + MACH_RCV_MSG | MACH_RCV_LARGE, + 0, + mach_message.Head.msgh_size, + mach_message.Head.msgh_local_port, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); + + if (mr != MACH_MSG_SUCCESS && mr != MACH_RCV_TOO_LARGE) { + NSLog(@"error!"); + } + + mach_msg_id_t msg_id = mach_message.Head.msgh_id; + mach_port_t remote_port = mach_message.Head.msgh_remote_port; + mach_port_t local_port = mach_message.Head.msgh_local_port; + + NSLog(@"Receive a mach message:[%d], remote_port: %d, local_port: %d, exception code: %d", + msg_id, + remote_port, + local_port, + mach_message.exception); + + dispatch_async(dispatch_get_main_queue(), ^{ + + + }); + + abort(); + } + }); +} + +#pragma mark - Unix signal信号捕获 +- (void)setSignalHandler { + ///注册信号Handler,Unix 信号捕获 signal(SIGABRT, SL_UncaughtSignalHandler); signal(SIGILL, SL_UncaughtSignalHandler); signal(SIGSEGV, SL_UncaughtSignalHandler); @@ -54,25 +120,13 @@ - (void)setUncaughtExceptionHandler{ signal(SIGPIPE, SL_UncaughtSignalHandler); signal(SIGKILL, SL_UncaughtSignalHandler); signal(SIGTRAP, SL_UncaughtSignalHandler); - } -///异常捕获处理 -void SL_UncaughtExceptionHandler(NSException *exception) { - if (otherUncaughtExceptionHandler) { - //如果其他三方也有注册,则也执行其他三方的Handle,然后在执行自己的 - otherUncaughtExceptionHandler(exception); - } - NSString *exceptionInfo = [NSString stringWithFormat:@"异常:%@, %@",exception.name, exception.reason]; - SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeUnknow errorDesc:exceptionInfo exception:exception callStack:exception.callStackSymbols]; - [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; -} - - ///异常信号处理回调 void SL_UncaughtSignalHandler(int signal) { NSString *exceptionInfo = [NSString stringWithFormat:@"异常信号:%@ Crash",signalName(signal)]; - SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeUnknow errorDesc:exceptionInfo exception:nil callStack:[NSThread callStackSymbols]]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeUnknow errorDesc:exceptionInfo exception:nil callStack:[NSThread callStackSymbols]]; [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; + } ///信号名称 关于信号这部分可以看 https://mp.weixin.qq.com/s/hVj-j61Br3dox37SN79fDQ NSString *signalName(int signal) { @@ -87,13 +141,13 @@ void SL_UncaughtSignalHandler(int signal) { /* 非法指令,即机器码指令不正确: 1, iOS 上偶现的问题,遇到之后用户会连续闪退,直到应用二进制的缓存重新加载 或重启手机。此问题挺影响体验,但是报给苹果不认,因为苹果那边没有收集到,目前没有太好办法。因为 iOS 应用内无法对一片内存同时获取 w+x 权限的,因此应用无法造成此类问题,所以判断是苹果的问题。 - */ + */ return @"SIGILL"; case SIGSEGV: /*段错误: 1、访问未申请的虚拟内存地址 2、没有写权限的内存写入 - */ + */ return @"SIGSEGV"; case SIGFPE: /* @@ -109,7 +163,7 @@ void SL_UncaughtSignalHandler(int signal) { case SIGPIPE: /*管道破裂 1, Socket通信是可能遇到,如读进程以及终止时,写进程继续写入数据。 - */ + */ return @"SIGPIPE"; case SIGKILL: /* @@ -127,6 +181,26 @@ void SL_UncaughtSignalHandler(int signal) { return @"UNKNOWN"; } } +#pragma mark - NSException捕获 +/// 其他三方注册的异常处理 handler +static NSUncaughtExceptionHandler *otherUncaughtExceptionHandler = NULL; +- (void)setExceptionHandler { + ///先获取保留其他三方的异常Handler + otherUncaughtExceptionHandler = NSGetUncaughtExceptionHandler(); + ///注册自己的异常Handler + NSSetUncaughtExceptionHandler (SL_UncaughtExceptionHandler); +} +///异常捕获处理 +void SL_UncaughtExceptionHandler(NSException *exception) { + if (otherUncaughtExceptionHandler) { + //如果其他三方也有注册,则也执行其他三方的Handle,然后在执行自己的 + otherUncaughtExceptionHandler(exception); + } + NSString *exceptionInfo = [NSString stringWithFormat:@"异常:%@, %@",exception.name, exception.reason]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeUnknow errorDesc:exceptionInfo exception:exception callStack:exception.callStackSymbols]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; +} + @end diff --git a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m index 91944a23..588eb60b 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m @@ -15,6 +15,9 @@ https://www.jianshu.com/p/29051908c74b iOS Crash分析 https://juejin.im/post/5d81fac66fb9a06af7126a44 iOS获取任意线程调用栈 https://blog.csdn.net/jasonblog/article/details/49909209 iOS中线程Call Stack的捕获和解析(二) + https://www.jianshu.com/p/b5304d3412e4 iOS app崩溃捕获 + https://www.jianshu.com/p/8d43b4b47913 Crash产生原因 + https://developer.aliyun.com/article/499180 iOS Mach异常和signal信号 */ @interface SLCrashViewController () @@ -130,7 +133,6 @@ - (void)testArray { strings[1] = nilStr; NSArray *array2 = [NSArray arrayWithObjects:strings count:2]; NSArray *array3 = [NSArray arrayWithObject:nil]; - } ///可变数组防护 越界和nil值 - (void)testMutableArray { @@ -149,6 +151,7 @@ - (void)testMutableArray { NSMutableArray *mArray1 = [NSMutableArray arrayWithObject:nil]; NSMutableArray *mArray2 = [NSMutableArray arrayWithObject:@[nilObj]]; [mArray addObject:nilObj]; + } ///不可变字典防护 nil值 @@ -294,4 +297,12 @@ - (void)testCallStack { // BSLOG_MAIN } + + +// 构造BAD MEM ACCESS Crash +- (void)makeCrash { + NSLog(@"********** Make a [BAD MEM ACCESS] now. **********"); + *((int *)(0x1234)) = 122; +} + @end diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 5eddee1a..bb71ba04 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -8,8 +8,8 @@ 7. Crash防护 8. -二、[iOS程序员的自我修养](https://juejin.im/post/5d5273b1f265da03f233c2d6) - - +二、程序员的自我修养 - 编译、链接、装载 +1. [趣探 Mach-O](https://juejin.im/post/5a0c5c5e51882555cc416602) +2. [iOS程序员的自我修养](https://juejin.im/post/5d5273b1f265da03f233c2d6) From 55565b7b2243f3865fb0dc7dbe9f1065e57b5dd7 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 29 Jul 2020 14:51:15 +0800 Subject: [PATCH 106/356] =?UTF-8?q?Crash=E5=BC=82=E5=B8=B8=E6=8D=95?= =?UTF-8?q?=E8=8E=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Crash/SLCrashProtector/SLCrashHandler.m | 12 +++++------- .../DarkMode/Crash/SLCrashViewController.m | 18 ++++++------------ 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m index aab91f99..e6579182 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m @@ -7,6 +7,7 @@ // #import "SLCrashHandler.h" +#import "BSBacktraceLogger.h" #import #import @@ -23,7 +24,6 @@ + (instancetype)errorWithErrorType:(SLCrashErrorType)errorType errorDesc:(NSStri } @end - @interface SLCrashHandler () @end @@ -99,10 +99,10 @@ - (void)setMachPortListener:(mach_port_t)mach_port { local_port, mach_message.exception); - dispatch_async(dispatch_get_main_queue(), ^{ - - - }); + NSString * callStack = [BSBacktraceLogger bs_backtraceOfAllThread]; + NSString *exceptionInfo = [NSString stringWithFormat:@"mach异常:%@",callStack]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeUnknow errorDesc:exceptionInfo exception:nil callStack:@[callStack]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; abort(); } @@ -201,6 +201,4 @@ void SL_UncaughtExceptionHandler(NSException *exception) { [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; } - - @end diff --git a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m index 588eb60b..658dfe2b 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m @@ -96,17 +96,19 @@ - (void)setupUI { #pragma mark - SLCrashHandlerDelegate ///异常捕获回调 提供给外界实现自定义处理 ,日志上报等(注意线程安全) - (void)crashHandlerDidOutputCrashError:(SLCrashError *)crashError { - [self.textView scrollsToTop]; NSString *errorInfo = [NSString stringWithFormat:@" 错误描述:%@ \n 调用栈:%@" ,crashError.errorDesc, crashError.callStackSymbol]; - self.textView.text = errorInfo; - + + SL_DISPATCH_ON_MAIN_THREAD((^{ + [self.textView scrollsToTop]; + self.textView.text = errorInfo; + })); ///日志写入缓存,适当时机上传后台 NSString *logPath = [SL_CachesDir stringByAppendingFormat:@"/com.wsl2ls.CrashLog"]; if(![[NSFileManager defaultManager] fileExistsAtPath:logPath]) { [[NSFileManager defaultManager] createDirectoryAtPath:logPath withIntermediateDirectories:NO attributes:nil error:nil]; } if(![[NSFileManager defaultManager] fileExistsAtPath:[logPath stringByAppendingFormat:@"/log"]]) { - NSError *error; + NSError *error; [errorInfo writeToFile:[logPath stringByAppendingFormat:@"/log"] atomically:YES encoding:NSUTF8StringEncoding error:&error]; }else { NSFileHandle * fileHandle = [NSFileHandle fileHandleForWritingAtPath:[logPath stringByAppendingFormat:@"/log"]]; @@ -297,12 +299,4 @@ - (void)testCallStack { // BSLOG_MAIN } - - -// 构造BAD MEM ACCESS Crash -- (void)makeCrash { - NSLog(@"********** Make a [BAD MEM ACCESS] now. **********"); - *((int *)(0x1234)) = 122; -} - @end From 4871208c9e391158769bee68cf70e46c31586442 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Wed, 29 Jul 2020 16:49:36 +0800 Subject: [PATCH 107/356] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cf51b54a..07a9db8f 100644 --- a/README.md +++ b/README.md @@ -151,9 +151,9 @@ avCaptureTool.videoSize = CGSizeMake(self.view.width * 0.8, self.view.height * 0 #### Welcome to you 👏 您的follow和start,是我前进的动力,Thanks♪(・ω・)ノ 🤝 -| [简书 ](https://www.jianshu.com/u/e15d1f644bea) | [掘金](https://juejin.im/user/5c00d97b6fb9a049fb436288) | QQ交流群 | 微信公众号 | 微信号 | +| [简书 ](https://www.jianshu.com/u/e15d1f644bea) | [掘金](https://juejin.im/user/5c00d97b6fb9a049fb436288) | QQ交流群 | 微信公众号 | 微信交流群 | | ---- | ---- | ---- | ---- | ---- | -| [CSDN](https://blog.csdn.net/wsl2ls) | [微博](https://weibo.com/5732733120/profile?rightmod=1&wvr=6&mod=personinfo&is_all=1) | [835303405](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/QQ交流群.png) | [iOS2679114653](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/微信公众号.png) | w2679114653 | +| [CSDN](https://blog.csdn.net/wsl2ls) | [微博](https://weibo.com/5732733120/profile?rightmod=1&wvr=6&mod=personinfo&is_all=1) | [835303405](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/QQ交流群.png) | [iOS2679114653](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/微信公众号.png) | w2679114653(加我拉入群) | [回到顶部](#iOS_Tips) From f2f746f3b74c3a8216d4b8f9d34a6e717e9b46b9 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 29 Jul 2020 20:20:19 +0800 Subject: [PATCH 108/356] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WKWebView/WebCache/SLWebCacheViewController.m | 5 ++++- ...7\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheViewController.m b/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheViewController.m index c58e14c7..bc4e58ee 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheViewController.m +++ b/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheViewController.m @@ -10,7 +10,10 @@ #import #import "SLWebCacheManager.h" -//实现原理参考 戴明大神:https://github.com/ming1016/STMURLCache +/* + https://zhuanlan.zhihu.com/p/148931732 WKWebView离线化方案——实现Service Worker API + https://github.com/ming1016/STMURLCache 戴明大神 + */ @interface SLWebCacheViewController () @property (nonatomic, strong) WKWebView * webView; diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index cdde78f8..7a999a9b 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -26,3 +26,4 @@ * 23、[欧阳大哥2013](https://juejin.im/user/593fb40eda2f6000673bdc61) * 24、[Wangkai](https://juejin.im/user/5bf20f696fb9a049fb4340b0) * 25、[maniac_kk](https://juejin.im/user/5aaf755cf265da23870ea3cf/posts) +* 27、[汇总各大互联网公司容易考察的高频leetcode题🔥](https://github.com/afatcoder/LeetcodeTop) From 38adcda76530e89ed558eca5ad5f446786e56607 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 30 Jul 2020 17:55:23 +0800 Subject: [PATCH 109/356] =?UTF-8?q?=E5=8D=9A=E5=AE=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...1\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 7a999a9b..96f9759d 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -27,3 +27,4 @@ * 24、[Wangkai](https://juejin.im/user/5bf20f696fb9a049fb4340b0) * 25、[maniac_kk](https://juejin.im/user/5aaf755cf265da23870ea3cf/posts) * 27、[汇总各大互联网公司容易考察的高频leetcode题🔥](https://github.com/afatcoder/LeetcodeTop) +* 28、[玉令天下-杨萧玉](http://yulingtianxia.com) From bc2b0de32616d76049b958bdc6d4aebfe737a5e4 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 31 Jul 2020 18:53:52 +0800 Subject: [PATCH 110/356] =?UTF-8?q?=E5=8D=9A=E5=AE=A2=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 8 +++++--- ...17\346\212\200\346\234\257\345\215\232\345\256\242.md" | 3 +++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index bb71ba04..8bbe5de1 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -1,4 +1,7 @@ - 一、APM/性能优化 + 一、APM/性能监控 + 1. [iOS-Monitor-Platform](https://github.com/aozhimin/iOS-Monitor-Platform) + + 二、[性能优化](https://github.com/skyming/iOS-Performance-Optimization) 1. 优化业务流程 2. 合理的线程分配 3. 预处理、延时加载、按需加载 @@ -6,9 +9,8 @@ 5. 使用正确的API 6. 启动连续闪退保护 7. Crash防护 -8. -二、程序员的自我修养 - 编译、链接、装载 +三、程序员的自我修养 - 编译、链接、装载 1. [趣探 Mach-O](https://juejin.im/post/5a0c5c5e51882555cc416602) 2. [iOS程序员的自我修养](https://juejin.im/post/5d5273b1f265da03f233c2d6) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 96f9759d..deeb2ddb 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -28,3 +28,6 @@ * 25、[maniac_kk](https://juejin.im/user/5aaf755cf265da23870ea3cf/posts) * 27、[汇总各大互联网公司容易考察的高频leetcode题🔥](https://github.com/afatcoder/LeetcodeTop) * 28、[玉令天下-杨萧玉](http://yulingtianxia.com) +* 29、[唐巧](http://blog.devtang.com) +* 30、[Lision](https://juejin.im/user/2189882891443278) +*31、[小鱼周凌宇](https://juejin.im/post/6844903616696844302) From d77477d4e6637be1a14dda5c693d5ec632a64f40 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 31 Jul 2020 19:05:07 +0800 Subject: [PATCH 111/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 7 +++++++ 1 file changed, 7 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 8bbe5de1..fc8fe0b6 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -1,3 +1,7 @@ + + 0、底层基础 + 1. [analyze](https://github.com/draveness/analyze) + 一、APM/性能监控 1. [iOS-Monitor-Platform](https://github.com/aozhimin/iOS-Monitor-Platform) @@ -15,3 +19,6 @@ 2. [iOS程序员的自我修养](https://juejin.im/post/5d5273b1f265da03f233c2d6) +四、数据结构与算法 +1. []() + From 0ce9891c9daac6b49b05b9bab4713418922d7d98 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 31 Jul 2020 19:39:16 +0800 Subject: [PATCH 112/356] =?UTF-8?q?APM=E7=9B=AE=E5=BD=95=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 36 +++++++++++++------ .../APM/{ => APMMonitor}/SLAPMCpu.h | 0 .../APM/{ => APMMonitor}/SLAPMCpu.m | 0 .../APM/{ => APMMonitor}/SLAPMFluency.h | 0 .../APM/{ => APMMonitor}/SLAPMFluency.m | 0 .../APM/{ => APMMonitor}/SLAPMManager.h | 0 .../APM/{ => APMMonitor}/SLAPMManager.m | 0 .../APM/{ => APMMonitor}/SLAPMMemoryDisk.h | 0 .../APM/{ => APMMonitor}/SLAPMMemoryDisk.m | 0 .../APM/{ => APMMonitor}/SLAPMThreadCount.h | 0 .../APM/{ => APMMonitor}/SLAPMThreadCount.m | 0 11 files changed, 26 insertions(+), 10 deletions(-) rename iOS_Tips/DarkMode/WorkIssues/APM/{ => APMMonitor}/SLAPMCpu.h (100%) rename iOS_Tips/DarkMode/WorkIssues/APM/{ => APMMonitor}/SLAPMCpu.m (100%) rename iOS_Tips/DarkMode/WorkIssues/APM/{ => APMMonitor}/SLAPMFluency.h (100%) rename iOS_Tips/DarkMode/WorkIssues/APM/{ => APMMonitor}/SLAPMFluency.m (100%) rename iOS_Tips/DarkMode/WorkIssues/APM/{ => APMMonitor}/SLAPMManager.h (100%) rename iOS_Tips/DarkMode/WorkIssues/APM/{ => APMMonitor}/SLAPMManager.m (100%) rename iOS_Tips/DarkMode/WorkIssues/APM/{ => APMMonitor}/SLAPMMemoryDisk.h (100%) rename iOS_Tips/DarkMode/WorkIssues/APM/{ => APMMonitor}/SLAPMMemoryDisk.m (100%) rename iOS_Tips/DarkMode/WorkIssues/APM/{ => APMMonitor}/SLAPMThreadCount.h (100%) rename iOS_Tips/DarkMode/WorkIssues/APM/{ => APMMonitor}/SLAPMThreadCount.m (100%) diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 226ae41b..9d298898 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -623,16 +623,7 @@ children = ( 784C4BDF24BC40D200D5C199 /* SLAPMViewController.h */, 784C4BE024BC40D200D5C199 /* SLAPMViewController.m */, - 784C4BE224BC4C5E00D5C199 /* SLAPMManager.h */, - 784C4BE324BC4C5E00D5C199 /* SLAPMManager.m */, - 784C4BE524BC53D500D5C199 /* SLAPMCpu.h */, - 784C4BE624BC53D500D5C199 /* SLAPMCpu.m */, - 784C4C3824C2EE6600D5C199 /* SLAPMMemoryDisk.h */, - 784C4C3924C2EE6600D5C199 /* SLAPMMemoryDisk.m */, - 784C4BEB24BDA5D700D5C199 /* SLAPMFluency.h */, - 784C4BEC24BDA5D700D5C199 /* SLAPMFluency.m */, - 789AD16124C99DCA00CB0B4C /* SLAPMThreadCount.h */, - 789AD16224C99DCA00CB0B4C /* SLAPMThreadCount.m */, + 789AD1C524D43A3700CB0B4C /* APMMonitor */, ); path = APM; sourceTree = ""; @@ -892,6 +883,31 @@ path = Crash; sourceTree = ""; }; + 789AD1C424D439EF00CB0B4C /* Network */ = { + isa = PBXGroup; + children = ( + ); + path = Network; + sourceTree = ""; + }; + 789AD1C524D43A3700CB0B4C /* APMMonitor */ = { + isa = PBXGroup; + children = ( + 784C4BE224BC4C5E00D5C199 /* SLAPMManager.h */, + 784C4BE324BC4C5E00D5C199 /* SLAPMManager.m */, + 784C4BE524BC53D500D5C199 /* SLAPMCpu.h */, + 784C4BE624BC53D500D5C199 /* SLAPMCpu.m */, + 784C4C3824C2EE6600D5C199 /* SLAPMMemoryDisk.h */, + 784C4C3924C2EE6600D5C199 /* SLAPMMemoryDisk.m */, + 784C4BEB24BDA5D700D5C199 /* SLAPMFluency.h */, + 784C4BEC24BDA5D700D5C199 /* SLAPMFluency.m */, + 789AD16124C99DCA00CB0B4C /* SLAPMThreadCount.h */, + 789AD16224C99DCA00CB0B4C /* SLAPMThreadCount.m */, + 789AD1C424D439EF00CB0B4C /* Network */, + ); + path = APMMonitor; + sourceTree = ""; + }; 78AA10F32371A1EF0044A6F8 /* FaceDetect */ = { isa = PBXGroup; children = ( diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMCpu.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMCpu.h similarity index 100% rename from iOS_Tips/DarkMode/WorkIssues/APM/SLAPMCpu.h rename to iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMCpu.h diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMCpu.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMCpu.m similarity index 100% rename from iOS_Tips/DarkMode/WorkIssues/APM/SLAPMCpu.m rename to iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMCpu.m diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMFluency.h similarity index 100% rename from iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.h rename to iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMFluency.h diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMFluency.m similarity index 100% rename from iOS_Tips/DarkMode/WorkIssues/APM/SLAPMFluency.m rename to iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMFluency.m diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMManager.h similarity index 100% rename from iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.h rename to iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMManager.h diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMManager.m similarity index 100% rename from iOS_Tips/DarkMode/WorkIssues/APM/SLAPMManager.m rename to iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMManager.m diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMMemoryDisk.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMMemoryDisk.h similarity index 100% rename from iOS_Tips/DarkMode/WorkIssues/APM/SLAPMMemoryDisk.h rename to iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMMemoryDisk.h diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMMemoryDisk.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMMemoryDisk.m similarity index 100% rename from iOS_Tips/DarkMode/WorkIssues/APM/SLAPMMemoryDisk.m rename to iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMMemoryDisk.m diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMThreadCount.h similarity index 100% rename from iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.h rename to iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMThreadCount.h diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMThreadCount.m similarity index 100% rename from iOS_Tips/DarkMode/WorkIssues/APM/SLAPMThreadCount.m rename to iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMThreadCount.m From db213779268f51f9687c289e6c01962bff1c94e3 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sun, 2 Aug 2020 11:24:20 +0800 Subject: [PATCH 113/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\347\254\224\350\256\260.md" | 15 +++++++++------ ...12\200\346\234\257\345\215\232\345\256\242.md" | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index fc8fe0b6..9014ce6a 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -1,7 +1,3 @@ - - 0、底层基础 - 1. [analyze](https://github.com/draveness/analyze) - 一、APM/性能监控 1. [iOS-Monitor-Platform](https://github.com/aozhimin/iOS-Monitor-Platform) @@ -18,7 +14,14 @@ 1. [趣探 Mach-O](https://juejin.im/post/5a0c5c5e51882555cc416602) 2. [iOS程序员的自我修养](https://juejin.im/post/5d5273b1f265da03f233c2d6) - 四、数据结构与算法 -1. []() +1. [LeetcodeTop](https://github.com/afatcoder/LeetcodeTop) + +五、面试题相关 +1. [iOS-InterviewQuestion-collection](https://github.com/liberalisman/iOS-InterviewQuestion-collection) +2. [阿里、字节 一套高效的iOS面试题解答](https://github.com/colourful987/bytedance-alibaba-interview) +3. [2019年iOS面试反思总结](https://juejin.im/post/6844903942644563982) +4. [IOS面试考察(九):性能优化相关问题](https://juejin.im/post/6844904131941892110#heading-50) +5. [Theendisthebegi ](https://www.jianshu.com/u/b836babfef41) +6. [analyze](https://github.com/draveness/analyze) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index deeb2ddb..c02dfcf2 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -30,4 +30,4 @@ * 28、[玉令天下-杨萧玉](http://yulingtianxia.com) * 29、[唐巧](http://blog.devtang.com) * 30、[Lision](https://juejin.im/user/2189882891443278) -*31、[小鱼周凌宇](https://juejin.im/post/6844903616696844302) +* 31、[小鱼周凌宇](https://juejin.im/post/6844903616696844302) From ad3cc6e619c446604a4a2cc5902e1cab87e95326 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 3 Aug 2020 18:14:36 +0800 Subject: [PATCH 114/356] =?UTF-8?q?=E7=BD=91=E7=BB=9C=E7=9B=91=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 6 + .../APM/APMMonitor/Network/SLAPMURLProtocol.h | 22 ++++ .../APM/APMMonitor/Network/SLAPMURLProtocol.m | 116 ++++++++++++++++++ .../WorkIssues/APM/SLAPMViewController.m | 24 +++- 4 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.h create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.m diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 9d298898..567fa7f2 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -122,6 +122,7 @@ 788ACD652390EA3A00737EC2 /* SLCubeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 788ACD642390EA3A00737EC2 /* SLCubeViewController.m */; }; 788ADB382441F48F00302CD9 /* SLCrashViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 788ADB362441F48F00302CD9 /* SLCrashViewController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 789AD16324C99DCA00CB0B4C /* SLAPMThreadCount.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD16224C99DCA00CB0B4C /* SLAPMThreadCount.m */; }; + 789AD1C824D7FA5F00CB0B4C /* SLAPMURLProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD1C724D7FA5F00CB0B4C /* SLAPMURLProtocol.m */; }; 78A179A8249B0AA8006F52E3 /* NSDictionary+SLExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A179A6249B0AA8006F52E3 /* NSDictionary+SLExtension.m */; }; 78A1998C2451BEE7005B2B4B /* UIButton+SLTitleImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A1998B2451BEE7005B2B4B /* UIButton+SLTitleImage.m */; }; 78A1998F2451C049005B2B4B /* SLButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A1998E2451C049005B2B4B /* SLButton.m */; }; @@ -381,6 +382,8 @@ 788ADB362441F48F00302CD9 /* SLCrashViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLCrashViewController.m; sourceTree = ""; }; 789AD16124C99DCA00CB0B4C /* SLAPMThreadCount.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMThreadCount.h; sourceTree = ""; }; 789AD16224C99DCA00CB0B4C /* SLAPMThreadCount.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMThreadCount.m; sourceTree = ""; }; + 789AD1C624D7FA5F00CB0B4C /* SLAPMURLProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMURLProtocol.h; sourceTree = ""; }; + 789AD1C724D7FA5F00CB0B4C /* SLAPMURLProtocol.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMURLProtocol.m; sourceTree = ""; }; 78A179A6249B0AA8006F52E3 /* NSDictionary+SLExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+SLExtension.m"; sourceTree = ""; }; 78A179A7249B0AA8006F52E3 /* NSDictionary+SLExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+SLExtension.h"; sourceTree = ""; }; 78A1998A2451BEE7005B2B4B /* UIButton+SLTitleImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIButton+SLTitleImage.h"; sourceTree = ""; }; @@ -886,6 +889,8 @@ 789AD1C424D439EF00CB0B4C /* Network */ = { isa = PBXGroup; children = ( + 789AD1C624D7FA5F00CB0B4C /* SLAPMURLProtocol.h */, + 789AD1C724D7FA5F00CB0B4C /* SLAPMURLProtocol.m */, ); path = Network; sourceTree = ""; @@ -1453,6 +1458,7 @@ 7862533F24599D420017F8F1 /* NSObject+SLCrashProtector.m in Sources */, 787C7DC2245D74E4005DF7ED /* NSMutableString+SLCrashProtector.m in Sources */, 782E3EB12373D889001E0DF9 /* SLAvCaptureSession.m in Sources */, + 789AD1C824D7FA5F00CB0B4C /* SLAPMURLProtocol.m in Sources */, 78842464248F964000C2E505 /* SLAVListViewController.m in Sources */, 78E179362351A40D0007E4BB /* SLEditMenuView.m in Sources */, 78BDE04B248A6A74002ED386 /* SLUrlProtocolAddCookie.m in Sources */, diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.h new file mode 100644 index 00000000..eb9b8361 --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.h @@ -0,0 +1,22 @@ +// +// SLAPMURLProtocol.h +// DarkMode +// +// Created by wsl on 2020/8/3. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface SLAPMURLProtocol : NSURLProtocol + +///开始监听网络 ++ (void)startMonitorNetwork; +///结束监听网络 ++ (void)stopMonitorNetwork; + +@end + +NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.m new file mode 100644 index 00000000..0bdb2bbb --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.m @@ -0,0 +1,116 @@ +// +// SLAPMURLProtocol.m +// DarkMode +// +// Created by wsl on 2020/8/3. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLAPMURLProtocol.h" + +//为了避免 canInitWithRequest 和 canonicalRequestForRequest 出现死循环 +static NSString * const SLHTTPHandledIdentifier = @"SLHTTPHandledIdentifier"; + +@interface SLAPMURLProtocol () + +@property (nonatomic, strong) NSURLSessionDataTask *dataTask; +@property (nonatomic, strong) NSOperationQueue *sessionDelegateQueue; +@property (nonatomic, strong) NSURLResponse *response; +@property (nonatomic, strong) NSMutableData *data; +@property (nonatomic, strong) NSDate *startDate; +//@property (nonatomic, strong) HJHTTPModel *httpModel; + +@end + +@implementation SLAPMURLProtocol + +#pragma mark - Public +///开始监听网络 ++ (void)startMonitorNetwork { + [NSURLProtocol registerClass:[SLAPMURLProtocol class]]; +} +///结束监听网络 ++ (void)stopMonitorNetwork { + [NSURLProtocol unregisterClass:[SLAPMURLProtocol class]]; +} + +#pragma mark - Override ++ (BOOL)canInitWithRequest:(NSURLRequest *)request { + if (![request.URL.scheme isEqualToString:@"http"] && + ![request.URL.scheme isEqualToString:@"https"]) { + return NO; + } + if ([NSURLProtocol propertyForKey:SLHTTPHandledIdentifier inRequest:request] ) { + return NO; + } + return YES; +} ++ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request { + return request; +} +- (void)startLoading { + NSMutableURLRequest *mutableReqeust = [[self request] mutableCopy]; + //标示该request已经处理过了,防止无限循环 + [NSURLProtocol setProperty:@(YES) forKey:SLHTTPHandledIdentifier inRequest:mutableReqeust]; + + self.startDate = [NSDate date]; + self.data = [NSMutableData data]; + NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; + self.sessionDelegateQueue = [[NSOperationQueue alloc] init]; + self.sessionDelegateQueue.maxConcurrentOperationCount = 1; + self.sessionDelegateQueue.name = @"com.wsl2ls.APMURLProtocol.queue"; + NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:self.sessionDelegateQueue]; + self.dataTask = [session dataTaskWithRequest:self.request]; + [self.dataTask resume]; + + // httpModel = [[NEHTTPModel alloc] init]; + // httpModel.request = self.request; + // httpModel.startDateString = [self stringWithDate:[NSDate date]]; + // + // NSTimeInterval myID = [[NSDate date] timeIntervalSince1970]; + // double randomNum = ((double)(arc4random() % 100))/10000; + // httpModel.myID = myID+randomNum; +} +- (void)stopLoading { + [self.dataTask cancel]; + self.dataTask = nil; + // httpModel.response = (NSHTTPURLResponse *)self.response; + // httpModel.endDateString = [self stringWithDate:[NSDate date]]; + NSString *mimeType = self.response.MIMEType; + + // 解析 response,流量统计等 +} + +#pragma mark - NSURLSessionDataDelegate +//接收到返回的响应信息时(还未开始下载), 执行的代理方法 +- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler { + [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed]; + completionHandler(NSURLSessionResponseAllow); + self.response = response; +} +//接收到服务器返回的数据 调用多次,数据是分批返回的 +- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask + didReceiveData:(NSData *)data { + [self.client URLProtocol:self didLoadData:data]; +} + +#pragma mark - NSURLSessionTaskDelegate +//请求结束或者是失败的时候调用 +- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { + if (!error) { + [self.client URLProtocolDidFinishLoading:self]; + } else if ([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorCancelled) { + } else { + [self.client URLProtocol:self didFailWithError:error]; + } + self.dataTask = nil; +} +//告诉代理,远程服务器请求了HTTP重定向 +- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler { + if (response != nil){ + self.response = response; + [[self client] URLProtocol:self wasRedirectedToRequest:request redirectResponse:response]; + } +} + +@end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m index 7693b49e..9f335f1b 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m @@ -9,6 +9,7 @@ #import "SLAPMViewController.h" #import "SLAPMManager.h" +#import "SLAPMURLProtocol.h" /* 参考资料: @@ -30,12 +31,14 @@ - (void)viewDidLoad { self.navigationItem.title = @"APM监控"; [self setupNavigationBar]; [SLAPMManager manager].type = SLAPMTypeThreadCount; + + [self testNetworkMonitor]; } //测试卡顿 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { //耗时任务 -// sleep(1); + // sleep(1); dispatch_async(dispatch_get_global_queue(0, 0), ^{ sleep(1); }); @@ -46,6 +49,25 @@ - (void)setupNavigationBar { self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:([SLAPMManager manager].isMonitoring ? @"停止":@"开始") style:UIBarButtonItemStyleDone target:self action:@selector(changeMonitorState)]; } +#pragma mark - Help Methods +///测试网络监控 +- (void)testNetworkMonitor { + UIImageView *imageView = [[UIImageView alloc] init]; + imageView.contentMode = UIViewContentModeScaleAspectFit; + [self.view addSubview:imageView]; + [imageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.left.right.bottom.mas_equalTo(0); + }]; + + [SLAPMURLProtocol startMonitorNetwork]; + dispatch_async(dispatch_get_global_queue(0, 0), ^{ + UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://b-ssl.duitang.com/uploads/item/201507/13/20150713182820_5mHce.jpeg"]]]; + dispatch_async(dispatch_get_main_queue(), ^{ + imageView.image = image; + }); + }); +} + #pragma mark - Events Handle ///改变监听状态 - (void)changeMonitorState{ From 9bfa780a7ad03b118d189aca9e53605fab261335 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 3 Aug 2020 19:33:05 +0800 Subject: [PATCH 115/356] =?UTF-8?q?=E6=B5=81=E9=87=8F=E7=9B=91=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../APM/APMMonitor/Network/SLAPMURLProtocol.m | 141 +++++++++++++----- 1 file changed, 107 insertions(+), 34 deletions(-) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.m index 0bdb2bbb..c5a91265 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.m @@ -8,17 +8,87 @@ #import "SLAPMURLProtocol.h" +@interface NSURLRequest (SLDataLength) +@end +@implementation NSURLRequest (SLDataLength) +- (NSUInteger)sl_getLineLength { + NSString *lineStr = [NSString stringWithFormat:@"%@ %@ %@\n", self.HTTPMethod, self.URL.path, @"HTTP/1.1"]; + NSData *lineData = [lineStr dataUsingEncoding:NSUTF8StringEncoding]; + return lineData.length; +} +- (NSUInteger)sl_getHeadersLengthWithCookie { + NSUInteger headersLength = 0; + + NSDictionary *headerFields = self.allHTTPHeaderFields; + NSDictionary *cookiesHeader = [self sl_getCookies]; + + // 添加 cookie 信息 + if (cookiesHeader.count) { + NSMutableDictionary *headerFieldsWithCookies = [NSMutableDictionary dictionaryWithDictionary:headerFields]; + [headerFieldsWithCookies addEntriesFromDictionary:cookiesHeader]; + headerFields = [headerFieldsWithCookies copy]; + } + // NSLog(@"%@", headerFields); + NSString *headerStr = @""; + + for (NSString *key in headerFields.allKeys) { + headerStr = [headerStr stringByAppendingString:key]; + headerStr = [headerStr stringByAppendingString:@": "]; + if ([headerFields objectForKey:key]) { + headerStr = [headerStr stringByAppendingString:headerFields[key]]; + } + headerStr = [headerStr stringByAppendingString:@"\n"]; + } + NSData *headerData = [headerStr dataUsingEncoding:NSUTF8StringEncoding]; + headersLength = headerData.length; + return headersLength; +} +- (NSDictionary *)sl_getCookies { + NSDictionary *cookiesHeader; + NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; + NSArray *cookies = [cookieStorage cookiesForURL:self.URL]; + if (cookies.count) { + cookiesHeader = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies]; + } + return cookiesHeader; +} +- (NSUInteger)sl_getBodyLength { + NSDictionary *headerFields = self.allHTTPHeaderFields; + NSUInteger bodyLength = [self.HTTPBody length]; + if ([headerFields objectForKey:@"Content-Encoding"]) { + NSData *bodyData; + if (self.HTTPBody == nil) { + uint8_t d[1024] = {0}; + NSInputStream *stream = self.HTTPBodyStream; + NSMutableData *data = [[NSMutableData alloc] init]; + [stream open]; + while ([stream hasBytesAvailable]) { + NSInteger len = [stream read:d maxLength:1024]; + if (len > 0 && stream.streamError == nil) { + [data appendBytes:(void *)d length:len]; + } + } + bodyData = [data copy]; + [stream close]; + } else { + bodyData = self.HTTPBody; + } + bodyLength = bodyData.length; + } + return bodyLength; +} +@end + + //为了避免 canInitWithRequest 和 canonicalRequestForRequest 出现死循环 static NSString * const SLHTTPHandledIdentifier = @"SLHTTPHandledIdentifier"; - @interface SLAPMURLProtocol () +@property (nonatomic, strong) NSURLSession *session; //会话 @property (nonatomic, strong) NSURLSessionDataTask *dataTask; -@property (nonatomic, strong) NSOperationQueue *sessionDelegateQueue; -@property (nonatomic, strong) NSURLResponse *response; -@property (nonatomic, strong) NSMutableData *data; -@property (nonatomic, strong) NSDate *startDate; -//@property (nonatomic, strong) HJHTTPModel *httpModel; + +@property (nonatomic, strong) NSURLResponse *response; //响应头 +@property (nonatomic, strong) NSMutableData *data; //返回的数据 @end @@ -40,45 +110,48 @@ + (BOOL)canInitWithRequest:(NSURLRequest *)request { ![request.URL.scheme isEqualToString:@"https"]) { return NO; } + //拦截过的请求不再拦截 if ([NSURLProtocol propertyForKey:SLHTTPHandledIdentifier inRequest:request] ) { return NO; } return YES; } + (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request { - return request; + //标示该request已经处理过了,防止无限循环 + NSMutableURLRequest *mutableReqeust = [request mutableCopy]; + [NSURLProtocol setProperty:@YES + forKey:SLHTTPHandledIdentifier + inRequest:mutableReqeust]; + return [mutableReqeust copy]; } - (void)startLoading { - NSMutableURLRequest *mutableReqeust = [[self request] mutableCopy]; - //标示该request已经处理过了,防止无限循环 - [NSURLProtocol setProperty:@(YES) forKey:SLHTTPHandledIdentifier inRequest:mutableReqeust]; - - self.startDate = [NSDate date]; - self.data = [NSMutableData data]; NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; - self.sessionDelegateQueue = [[NSOperationQueue alloc] init]; - self.sessionDelegateQueue.maxConcurrentOperationCount = 1; - self.sessionDelegateQueue.name = @"com.wsl2ls.APMURLProtocol.queue"; - NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:self.sessionDelegateQueue]; - self.dataTask = [session dataTaskWithRequest:self.request]; - [self.dataTask resume]; - - // httpModel = [[NEHTTPModel alloc] init]; - // httpModel.request = self.request; - // httpModel.startDateString = [self stringWithDate:[NSDate date]]; - // - // NSTimeInterval myID = [[NSDate date] timeIntervalSince1970]; - // double randomNum = ((double)(arc4random() % 100))/10000; - // httpModel.myID = myID+randomNum; + NSOperationQueue *sessionDelegateQueue = [[NSOperationQueue alloc] init]; + sessionDelegateQueue.maxConcurrentOperationCount = 1; + sessionDelegateQueue.name = @"com.wsl2ls.APMURLProtocol.queue"; + _session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:sessionDelegateQueue]; + _dataTask = [_session dataTaskWithRequest:self.request]; + [_dataTask resume]; } - (void)stopLoading { - [self.dataTask cancel]; - self.dataTask = nil; - // httpModel.response = (NSHTTPURLResponse *)self.response; - // httpModel.endDateString = [self stringWithDate:[NSDate date]]; - NSString *mimeType = self.response.MIMEType; + [_dataTask cancel]; + _dataTask = nil; + [_session invalidateAndCancel]; + _session = nil; + + //接收流量 不包括响应头NSURLResponse + NSLog(@"接收流量大小:%.2fM",self.data.length/(1024.0*1024.0)); - // 解析 response,流量统计等 + NSUInteger sendLength = [self.request sl_getLineLength] + [self.request sl_getBodyLength] + [self.request sl_getHeadersLengthWithCookie]; + NSLog(@"发送流量大小:%ldB",sendLength); +} + +#pragma mark - Getter +- (NSMutableData *)data { + if (!_data) { + _data = [NSMutableData data]; + } + return _data; } #pragma mark - NSURLSessionDataDelegate @@ -91,6 +164,7 @@ - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)data //接收到服务器返回的数据 调用多次,数据是分批返回的 - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data { + [self.data appendData:data]; [self.client URLProtocol:self didLoadData:data]; } @@ -103,7 +177,6 @@ - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didComp } else { [self.client URLProtocol:self didFailWithError:error]; } - self.dataTask = nil; } //告诉代理,远程服务器请求了HTTP重定向 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler { From 60d9667f15916746aa8dc7f93230757cc56285a0 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 4 Aug 2020 10:53:53 +0800 Subject: [PATCH 116/356] =?UTF-8?q?APM=20=20=E7=BD=91=E7=BB=9C=E7=9B=91?= =?UTF-8?q?=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 14 + .../ThirdLibary/Reachability/Reachability.h | 64 +++++ .../ThirdLibary/Reachability/Reachability.m | 242 ++++++++++++++++++ .../APM/APMMonitor/Network/SLAPMURLProtocol.m | 1 + .../WorkIssues/APM/APMMonitor/SLAPMManager.h | 4 +- .../WorkIssues/APM/APMMonitor/SLAPMManager.m | 7 +- .../WorkIssues/APM/SLAPMViewController.m | 11 +- 7 files changed, 334 insertions(+), 9 deletions(-) create mode 100644 iOS_Tips/DarkMode/ThirdLibary/Reachability/Reachability.h create mode 100644 iOS_Tips/DarkMode/ThirdLibary/Reachability/Reachability.m diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 567fa7f2..d4be0b3f 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -123,6 +123,7 @@ 788ADB382441F48F00302CD9 /* SLCrashViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 788ADB362441F48F00302CD9 /* SLCrashViewController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 789AD16324C99DCA00CB0B4C /* SLAPMThreadCount.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD16224C99DCA00CB0B4C /* SLAPMThreadCount.m */; }; 789AD1C824D7FA5F00CB0B4C /* SLAPMURLProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD1C724D7FA5F00CB0B4C /* SLAPMURLProtocol.m */; }; + 789AD1CF24D9024300CB0B4C /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD1CD24D9024300CB0B4C /* Reachability.m */; }; 78A179A8249B0AA8006F52E3 /* NSDictionary+SLExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A179A6249B0AA8006F52E3 /* NSDictionary+SLExtension.m */; }; 78A1998C2451BEE7005B2B4B /* UIButton+SLTitleImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A1998B2451BEE7005B2B4B /* UIButton+SLTitleImage.m */; }; 78A1998F2451C049005B2B4B /* SLButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A1998E2451C049005B2B4B /* SLButton.m */; }; @@ -384,6 +385,8 @@ 789AD16224C99DCA00CB0B4C /* SLAPMThreadCount.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMThreadCount.m; sourceTree = ""; }; 789AD1C624D7FA5F00CB0B4C /* SLAPMURLProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMURLProtocol.h; sourceTree = ""; }; 789AD1C724D7FA5F00CB0B4C /* SLAPMURLProtocol.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMURLProtocol.m; sourceTree = ""; }; + 789AD1CD24D9024300CB0B4C /* Reachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Reachability.m; sourceTree = ""; }; + 789AD1CE24D9024300CB0B4C /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reachability.h; sourceTree = ""; }; 78A179A6249B0AA8006F52E3 /* NSDictionary+SLExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+SLExtension.m"; sourceTree = ""; }; 78A179A7249B0AA8006F52E3 /* NSDictionary+SLExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+SLExtension.h"; sourceTree = ""; }; 78A1998A2451BEE7005B2B4B /* UIButton+SLTitleImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIButton+SLTitleImage.h"; sourceTree = ""; }; @@ -564,6 +567,7 @@ 7835047E24586BA30071283E /* ThirdLibary */ = { isa = PBXGroup; children = ( + 789AD1CC24D9024300CB0B4C /* Reachability */, 7857FD4824729E8500D3D986 /* BSBacktraceLogger */, 78D3095D239688EF00DC373A /* OpenGLUtils */, 7835047F24586BAC0071283E /* Fishhook */, @@ -913,6 +917,15 @@ path = APMMonitor; sourceTree = ""; }; + 789AD1CC24D9024300CB0B4C /* Reachability */ = { + isa = PBXGroup; + children = ( + 789AD1CE24D9024300CB0B4C /* Reachability.h */, + 789AD1CD24D9024300CB0B4C /* Reachability.m */, + ); + path = Reachability; + sourceTree = ""; + }; 78AA10F32371A1EF0044A6F8 /* FaceDetect */ = { isa = PBXGroup; children = ( @@ -1455,6 +1468,7 @@ 783504642452C20B0071283E /* SLMethod.m in Sources */, 784C4BE124BC40D200D5C199 /* SLAPMViewController.m in Sources */, 787C7E4524656524005DF7ED /* UIView+SLMLeakFinder.m in Sources */, + 789AD1CF24D9024300CB0B4C /* Reachability.m in Sources */, 7862533F24599D420017F8F1 /* NSObject+SLCrashProtector.m in Sources */, 787C7DC2245D74E4005DF7ED /* NSMutableString+SLCrashProtector.m in Sources */, 782E3EB12373D889001E0DF9 /* SLAvCaptureSession.m in Sources */, diff --git a/iOS_Tips/DarkMode/ThirdLibary/Reachability/Reachability.h b/iOS_Tips/DarkMode/ThirdLibary/Reachability/Reachability.h new file mode 100644 index 00000000..50c048c1 --- /dev/null +++ b/iOS_Tips/DarkMode/ThirdLibary/Reachability/Reachability.h @@ -0,0 +1,64 @@ +/* + Copyright (C) 2016 Apple Inc. All Rights Reserved. + See LICENSE.txt for this sample’s licensing information + + Abstract: + Basic demonstration of how to use the SystemConfiguration Reachablity APIs. + */ + +#import +#import +#import + + +typedef enum : NSInteger { + NotReachable = 0, + ReachableViaWiFi, + ReachableViaWWAN +} NetworkStatus; + +#pragma mark IPv6 Support +//Reachability fully support IPv6. For full details, see ReadMe.md. + + +extern NSString *kReachabilityChangedNotification; + + +@interface Reachability : NSObject + +/*! + * Use to check the reachability of a given host name. + */ ++ (instancetype)reachabilityWithHostName:(NSString *)hostName; + +/*! + * Use to check the reachability of a given IP address. + */ ++ (instancetype)reachabilityWithAddress:(const struct sockaddr *)hostAddress; + +/*! + * Checks whether the default route is available. Should be used by applications that do not connect to a particular host. + */ ++ (instancetype)reachabilityForInternetConnection; + + +#pragma mark reachabilityForLocalWiFi +//reachabilityForLocalWiFi has been removed from the sample. See ReadMe.md for more information. +//+ (instancetype)reachabilityForLocalWiFi; + +/*! + * Start listening for reachability notifications on the current run loop. + */ +- (BOOL)startNotifier; +- (void)stopNotifier; + +- (NetworkStatus)currentReachabilityStatus; + +/*! + * WWAN may be available, but not active until a connection has been established. WiFi may require a connection for VPN on Demand. + */ +- (BOOL)connectionRequired; + +@end + + diff --git a/iOS_Tips/DarkMode/ThirdLibary/Reachability/Reachability.m b/iOS_Tips/DarkMode/ThirdLibary/Reachability/Reachability.m new file mode 100644 index 00000000..f081a16a --- /dev/null +++ b/iOS_Tips/DarkMode/ThirdLibary/Reachability/Reachability.m @@ -0,0 +1,242 @@ +/* + Copyright (C) 2016 Apple Inc. All Rights Reserved. + See LICENSE.txt for this sample’s licensing information + + Abstract: + Basic demonstration of how to use the SystemConfiguration Reachablity APIs. + */ + +#import +#import +#import +#import +#import + +#import + +#import "Reachability.h" + +#pragma mark IPv6 Support +//Reachability fully support IPv6. For full details, see ReadMe.md. + + +NSString *kReachabilityChangedNotification = @"kNetworkReachabilityChangedNotification"; + + +#pragma mark - Supporting functions + +#define kShouldPrintReachabilityFlags 1 + +static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char* comment) +{ +#if kShouldPrintReachabilityFlags + + NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n", + (flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-', + (flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-', + + (flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-', + (flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-', + (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-', + (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-', + (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-', + (flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-', + (flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-', + comment + ); +#endif +} + + +static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) +{ +#pragma unused (target, flags) + NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback"); + NSCAssert([(__bridge NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback"); + + Reachability* noteObject = (__bridge Reachability *)info; + // Post a notification to notify the client that the network reachability changed. + [[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject]; +} + + +#pragma mark - Reachability implementation + +@implementation Reachability +{ + SCNetworkReachabilityRef _reachabilityRef; +} + ++ (instancetype)reachabilityWithHostName:(NSString *)hostName +{ + Reachability* returnValue = NULL; + SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]); + if (reachability != NULL) + { + returnValue= [[self alloc] init]; + if (returnValue != NULL) + { + returnValue->_reachabilityRef = reachability; + } + else { + CFRelease(reachability); + } + } + return returnValue; +} + + ++ (instancetype)reachabilityWithAddress:(const struct sockaddr *)hostAddress +{ + SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, hostAddress); + + Reachability* returnValue = NULL; + + if (reachability != NULL) + { + returnValue = [[self alloc] init]; + if (returnValue != NULL) + { + returnValue->_reachabilityRef = reachability; + } + else { + CFRelease(reachability); + } + } + return returnValue; +} + + ++ (instancetype)reachabilityForInternetConnection +{ + struct sockaddr_in zeroAddress; + bzero(&zeroAddress, sizeof(zeroAddress)); + zeroAddress.sin_len = sizeof(zeroAddress); + zeroAddress.sin_family = AF_INET; + + return [self reachabilityWithAddress: (const struct sockaddr *) &zeroAddress]; +} + +#pragma mark reachabilityForLocalWiFi +//reachabilityForLocalWiFi has been removed from the sample. See ReadMe.md for more information. +//+ (instancetype)reachabilityForLocalWiFi + + + +#pragma mark - Start and stop notifier + +- (BOOL)startNotifier +{ + BOOL returnValue = NO; + SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL}; + + if (SCNetworkReachabilitySetCallback(_reachabilityRef, ReachabilityCallback, &context)) + { + if (SCNetworkReachabilityScheduleWithRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) + { + returnValue = YES; + } + } + + return returnValue; +} + + +- (void)stopNotifier +{ + if (_reachabilityRef != NULL) + { + SCNetworkReachabilityUnscheduleFromRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + } +} + + +- (void)dealloc +{ + [self stopNotifier]; + if (_reachabilityRef != NULL) + { + CFRelease(_reachabilityRef); + } +} + + +#pragma mark - Network Flag Handling + +- (NetworkStatus)networkStatusForFlags:(SCNetworkReachabilityFlags)flags +{ + PrintReachabilityFlags(flags, "networkStatusForFlags"); + if ((flags & kSCNetworkReachabilityFlagsReachable) == 0) + { + // The target host is not reachable. + return NotReachable; + } + + NetworkStatus returnValue = NotReachable; + + if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0) + { + /* + If the target host is reachable and no connection is required then we'll assume (for now) that you're on Wi-Fi... + */ + returnValue = ReachableViaWiFi; + } + + if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || + (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)) + { + /* + ... and the connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs... + */ + + if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0) + { + /* + ... and no [user] intervention is needed... + */ + returnValue = ReachableViaWiFi; + } + } + + if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN) + { + /* + ... but WWAN connections are OK if the calling application is using the CFNetwork APIs. + */ + returnValue = ReachableViaWWAN; + } + + return returnValue; +} + + +- (BOOL)connectionRequired +{ + NSAssert(_reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef"); + SCNetworkReachabilityFlags flags; + + if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags)) + { + return (flags & kSCNetworkReachabilityFlagsConnectionRequired); + } + + return NO; +} + + +- (NetworkStatus)currentReachabilityStatus +{ + NSAssert(_reachabilityRef != NULL, @"currentNetworkStatus called with NULL SCNetworkReachabilityRef"); + NetworkStatus returnValue = NotReachable; + SCNetworkReachabilityFlags flags; + + if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags)) + { + returnValue = [self networkStatusForFlags:flags]; + } + + return returnValue; +} + + +@end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.m index c5a91265..66c2d1b1 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.m @@ -8,6 +8,7 @@ #import "SLAPMURLProtocol.h" +///计算请求报文的大小 即上行流量 @interface NSURLRequest (SLDataLength) @end @implementation NSURLRequest (SLDataLength) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMManager.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMManager.h index 7d8b85ab..bb21f987 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMManager.h +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMManager.h @@ -24,8 +24,10 @@ typedef NS_ENUM(NSInteger, SLAPMType) { SLAPMTypeCrash = 1 << 3, /*线程数量监控,防止线程爆炸*/ SLAPMTypeThreadCount = 1 << 4, + /*网络监控*/ + SLAPMTypeNetwork = 1 << 5, /*所有策略*/ - SLAPMTypeAll = 1 << 5 + SLAPMTypeAll = 1 << 6 }; diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMManager.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMManager.m index 2cabb189..f9200b71 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMManager.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMManager.m @@ -14,7 +14,7 @@ #import "SLAPMFluency.h" #import "SLCrashProtector.h" #import "SLAPMThreadCount.h" - +#import "SLAPMURLProtocol.h" @interface SLAPMManager () ///任务名称 @@ -66,6 +66,10 @@ - (void)startMonitoring { [SLAPMThreadCount startMonitorThreadCount]; } + if ((self.type & SLAPMTypeNetwork) == SLAPMTypeNetwork || self.type == SLAPMTypeAll) { + [SLAPMURLProtocol startMonitorNetwork]; + } + } ///结束监控 - (void)stopMonitoring { @@ -76,6 +80,7 @@ - (void)stopMonitoring { [SLAPMFluency sharedInstance].delegate = nil; [[SLAPMFluency sharedInstance] stopMonitorFluency]; [SLAPMThreadCount stopMonitorThreadCount]; + [SLAPMURLProtocol stopMonitorNetwork]; } #pragma mark - Monitoring diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m index 9f335f1b..65f9f471 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m @@ -9,8 +9,6 @@ #import "SLAPMViewController.h" #import "SLAPMManager.h" -#import "SLAPMURLProtocol.h" - /* 参考资料: https://www.jianshu.com/p/95df83780c8f @@ -30,9 +28,7 @@ - (void)viewDidLoad { self.view.backgroundColor = [UIColor whiteColor]; self.navigationItem.title = @"APM监控"; [self setupNavigationBar]; - [SLAPMManager manager].type = SLAPMTypeThreadCount; - - [self testNetworkMonitor]; + [SLAPMManager manager].type = SLAPMTypeNetwork; } //测试卡顿 @@ -47,6 +43,8 @@ - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { #pragma mark - UI - (void)setupNavigationBar { self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:([SLAPMManager manager].isMonitoring ? @"停止":@"开始") style:UIBarButtonItemStyleDone target:self action:@selector(changeMonitorState)]; + + [self testNetworkMonitor]; } #pragma mark - Help Methods @@ -58,8 +56,7 @@ - (void)testNetworkMonitor { [imageView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.left.right.bottom.mas_equalTo(0); }]; - - [SLAPMURLProtocol startMonitorNetwork]; + dispatch_async(dispatch_get_global_queue(0, 0), ^{ UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://b-ssl.duitang.com/uploads/item/201507/13/20150713182820_5mHce.jpeg"]]]; dispatch_async(dispatch_get_main_queue(), ^{ From 75061acaadbb34d87a68823f167ec72ab377c010 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 4 Aug 2020 11:43:19 +0800 Subject: [PATCH 117/356] =?UTF-8?q?APM=20=20=E7=BD=91=E7=BB=9C=E7=9B=91?= =?UTF-8?q?=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../APM/APMMonitor/Network/SLAPMURLProtocol.m | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.m index 66c2d1b1..ffa38742 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.m @@ -170,6 +170,42 @@ - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)data } #pragma mark - NSURLSessionTaskDelegate +///告诉代理会话已收集完任务的度量 实现对网络请求中 DNS 查询/TCP 建立连接/TLS 握手/请求响应等各环节时间的统计 +- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0)) { + + //数组包含了在执行任务时产生的每个请求/响应事务中收集的指标。 + NSArray *array = metrics.transactionMetrics; + //任务从创建到完成花费的总时间,任务的创建时间是任务被实例化时的时间;任务完成时间是任务的内部状态将要变为完成的时间。 + NSDateInterval *taskInterval = metrics.taskInterval; + NSLog(@"请求时长:%f",taskInterval.duration); + + for (NSURLSessionTaskTransactionMetrics*transactionMetrics in array) { + NSLog(@"请求开始:%@",transactionMetrics.fetchStartDate); + NSLog(@"请求完成:%@",transactionMetrics.responseEndDate); + NSLog(@"请求协议:%@",transactionMetrics.networkProtocolName); + NSLog(@"DNS 解析开始时间:%@",transactionMetrics.domainLookupStartDate); + NSLog(@"DNS 解析完成时间:%@",transactionMetrics.domainLookupEndDate); + NSLog(@"客户端与服务器开始建立 TCP 连接的时间:%@",transactionMetrics.connectStartDate); + NSLog(@"HTTPS 的 TLS 握手开始时间:%@",transactionMetrics.secureConnectionStartDate); + NSLog(@"HTTPS 的 TLS 握手结束时间:%@",transactionMetrics.secureConnectionEndDate); + NSLog(@"客户端与服务器建立 TCP 连接完成时间:%@",transactionMetrics.connectEndDate); + + NSLog(@"开始传输 HTTP请求header 第一个字节的时间:%@",transactionMetrics.requestStartDate); + NSLog(@"HTTP请求最后一个字节传输完成的时间:%@",transactionMetrics.requestEndDate); + NSLog(@"客户端从服务器接收到响应的第一个字节的时间:%@",transactionMetrics.responseStartDate); + NSLog(@"客户端从服务器接收到最后一个字节的时间:%@",transactionMetrics.responseEndDate); + } +} + +- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task + didSendBodyData:(int64_t)bytesSent + totalBytesSent:(int64_t)totalBytesSent +totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend { + + +} + + //请求结束或者是失败的时候调用 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { if (!error) { From c017dbc1186cc61324802689eae834a5fd221c75 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 4 Aug 2020 17:19:26 +0800 Subject: [PATCH 118/356] =?UTF-8?q?iOS=20APM=E4=B9=8B=E7=BD=91=E7=BB=9C?= =?UTF-8?q?=E7=9B=91=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 12 ++---------- iOS_Tips/DarkMode/SLCategory/UIImage+SLCommon.h | 4 ++++ iOS_Tips/DarkMode/SLCategory/UIImage+SLCommon.m | 12 ++++++++++++ .../APM/APMMonitor/{Network => }/SLAPMURLProtocol.h | 1 + .../APM/APMMonitor/{Network => }/SLAPMURLProtocol.m | 0 .../DarkMode/WorkIssues/APM/SLAPMViewController.m | 4 +--- .../DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 2 +- ...6\212\200\346\234\257\345\215\232\345\256\242.md" | 3 ++- 8 files changed, 23 insertions(+), 15 deletions(-) rename iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/{Network => }/SLAPMURLProtocol.h (78%) rename iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/{Network => }/SLAPMURLProtocol.m (100%) diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index d4be0b3f..51ebf18e 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -890,15 +890,6 @@ path = Crash; sourceTree = ""; }; - 789AD1C424D439EF00CB0B4C /* Network */ = { - isa = PBXGroup; - children = ( - 789AD1C624D7FA5F00CB0B4C /* SLAPMURLProtocol.h */, - 789AD1C724D7FA5F00CB0B4C /* SLAPMURLProtocol.m */, - ); - path = Network; - sourceTree = ""; - }; 789AD1C524D43A3700CB0B4C /* APMMonitor */ = { isa = PBXGroup; children = ( @@ -912,7 +903,8 @@ 784C4BEC24BDA5D700D5C199 /* SLAPMFluency.m */, 789AD16124C99DCA00CB0B4C /* SLAPMThreadCount.h */, 789AD16224C99DCA00CB0B4C /* SLAPMThreadCount.m */, - 789AD1C424D439EF00CB0B4C /* Network */, + 789AD1C624D7FA5F00CB0B4C /* SLAPMURLProtocol.h */, + 789AD1C724D7FA5F00CB0B4C /* SLAPMURLProtocol.m */, ); path = APMMonitor; sourceTree = ""; diff --git a/iOS_Tips/DarkMode/SLCategory/UIImage+SLCommon.h b/iOS_Tips/DarkMode/SLCategory/UIImage+SLCommon.h index 74889a70..c4c0fd6f 100644 --- a/iOS_Tips/DarkMode/SLCategory/UIImage+SLCommon.h +++ b/iOS_Tips/DarkMode/SLCategory/UIImage+SLCommon.h @@ -15,9 +15,13 @@ NS_ASSUME_NONNULL_BEGIN /// 将图片旋转弧度radians - (UIImage *)sl_imageRotatedByRadians:(CGFloat)radians; + /// 提取图片上某位置像素的颜色 - (UIColor *)sl_colorAtPixel:(CGPoint)point; +/// 图片缩放,针对大图片处理 ++ (UIImage *)sl_scaledImageWithData:(NSData *)data withSize:(CGSize)size scale:(CGFloat)scale orientation:(UIImageOrientation)orientation; + @end NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/SLCategory/UIImage+SLCommon.m b/iOS_Tips/DarkMode/SLCategory/UIImage+SLCommon.m index bd351721..b64d4ba0 100644 --- a/iOS_Tips/DarkMode/SLCategory/UIImage+SLCommon.m +++ b/iOS_Tips/DarkMode/SLCategory/UIImage+SLCommon.m @@ -78,4 +78,16 @@ - (UIColor *)sl_colorAtPixel:(CGPoint)point { return [UIColor colorWithRed:red green:green blue:blue alpha:alpha]; } +/// 图片缩放,针对大图片处理 ++ (UIImage *)sl_scaledImageWithData:(NSData *)data withSize:(CGSize)size scale:(CGFloat)scale orientation:(UIImageOrientation)orientation { + CGFloat maxPixelSize = MAX(size.width, size.height); + CGImageSourceRef sourceRef = CGImageSourceCreateWithData((__bridge CFDataRef)data,nil); + NSDictionary *optoins = @{(__bridge id)kCGImageSourceCreateThumbnailFromImageAlways:(__bridge id)kCFBooleanTrue,(__bridge id)kCGImageSourceThumbnailMaxPixelSize:[NSNumber numberWithFloat:maxPixelSize]}; + CGImageRef imageRef = CGImageSourceCreateThumbnailAtIndex(sourceRef, 0, (__bridge CFDictionaryRef)optoins); + UIImage *image = [UIImage imageWithCGImage:imageRef scale:scale orientation:orientation]; + CGImageRelease(imageRef); + CFRelease(sourceRef); + return image; +} + @end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMURLProtocol.h similarity index 78% rename from iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.h rename to iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMURLProtocol.h index eb9b8361..3a94f668 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.h +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMURLProtocol.h @@ -10,6 +10,7 @@ NS_ASSUME_NONNULL_BEGIN +///网络监控 TCP 建立连接时间 、DNS 时间、 SSL时间、首包时间、响应时间 、流量 @interface SLAPMURLProtocol : NSURLProtocol ///开始监听网络 diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMURLProtocol.m similarity index 100% rename from iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/Network/SLAPMURLProtocol.m rename to iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMURLProtocol.m diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m index 65f9f471..3d713d15 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m @@ -42,9 +42,7 @@ - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { #pragma mark - UI - (void)setupNavigationBar { - self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:([SLAPMManager manager].isMonitoring ? @"停止":@"开始") style:UIBarButtonItemStyleDone target:self action:@selector(changeMonitorState)]; - - [self testNetworkMonitor]; + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:([SLAPMManager manager].isMonitoring ? @"停止监控":@"开始监控") style:UIBarButtonItemStyleDone target:self action:@selector(changeMonitorState)]; } #pragma mark - Help Methods diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 9014ce6a..f7f32206 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -9,6 +9,7 @@ 5. 使用正确的API 6. 启动连续闪退保护 7. Crash防护 +8. APM监控 三、程序员的自我修养 - 编译、链接、装载 1. [趣探 Mach-O](https://juejin.im/post/5a0c5c5e51882555cc416602) @@ -17,7 +18,6 @@ 四、数据结构与算法 1. [LeetcodeTop](https://github.com/afatcoder/LeetcodeTop) - 五、面试题相关 1. [iOS-InterviewQuestion-collection](https://github.com/liberalisman/iOS-InterviewQuestion-collection) 2. [阿里、字节 一套高效的iOS面试题解答](https://github.com/colourful987/bytedance-alibaba-interview) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index c02dfcf2..dc467e40 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -1,5 +1,5 @@ -## 看过的高质量技术博客集合 +## 高质量技术博客集合 * 1、[WeRead团队博客](https://wereadteam.github.io/) * 2、[美团技术团队](https://tech.meituan.com/) @@ -31,3 +31,4 @@ * 29、[唐巧](http://blog.devtang.com) * 30、[Lision](https://juejin.im/user/2189882891443278) * 31、[小鱼周凌宇](https://juejin.im/post/6844903616696844302) +* 32、[satanwoo](http://satanwoo.github.io/) From cd739f739c343da3b1e162f747433cc90a9263c2 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 4 Aug 2020 20:16:03 +0800 Subject: [PATCH 119/356] APM --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 12 ++++++ .../DarkMode/General/Tool/PrefixHeader.pch | 8 ++-- .../APM/APMMonitor/SLSystemAppInfo.h | 17 +++++++++ .../APM/APMMonitor/SLSystemAppInfo.m | 17 +++++++++ .../APMMonitor/UIViewController+SLAPMTime.h | 17 +++++++++ .../APMMonitor/UIViewController+SLAPMTime.m | 13 +++++++ .../WorkIssues/APM/SLAPMViewController.m | 37 ++++++++++++++----- ...00\346\234\257\345\215\232\345\256\242.md" | 1 + 8 files changed, 109 insertions(+), 13 deletions(-) create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMTime.h create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMTime.m diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 51ebf18e..a04f7d0b 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -124,6 +124,8 @@ 789AD16324C99DCA00CB0B4C /* SLAPMThreadCount.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD16224C99DCA00CB0B4C /* SLAPMThreadCount.m */; }; 789AD1C824D7FA5F00CB0B4C /* SLAPMURLProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD1C724D7FA5F00CB0B4C /* SLAPMURLProtocol.m */; }; 789AD1CF24D9024300CB0B4C /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD1CD24D9024300CB0B4C /* Reachability.m */; }; + 789AD1D224D9622B00CB0B4C /* UIViewController+SLAPMTime.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD1D124D9622B00CB0B4C /* UIViewController+SLAPMTime.m */; }; + 789AD1D524D97F8500CB0B4C /* SLSystemAppInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD1D424D97F8500CB0B4C /* SLSystemAppInfo.m */; }; 78A179A8249B0AA8006F52E3 /* NSDictionary+SLExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A179A6249B0AA8006F52E3 /* NSDictionary+SLExtension.m */; }; 78A1998C2451BEE7005B2B4B /* UIButton+SLTitleImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A1998B2451BEE7005B2B4B /* UIButton+SLTitleImage.m */; }; 78A1998F2451C049005B2B4B /* SLButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A1998E2451C049005B2B4B /* SLButton.m */; }; @@ -387,6 +389,10 @@ 789AD1C724D7FA5F00CB0B4C /* SLAPMURLProtocol.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMURLProtocol.m; sourceTree = ""; }; 789AD1CD24D9024300CB0B4C /* Reachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Reachability.m; sourceTree = ""; }; 789AD1CE24D9024300CB0B4C /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reachability.h; sourceTree = ""; }; + 789AD1D024D9622B00CB0B4C /* UIViewController+SLAPMTime.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIViewController+SLAPMTime.h"; sourceTree = ""; }; + 789AD1D124D9622B00CB0B4C /* UIViewController+SLAPMTime.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+SLAPMTime.m"; sourceTree = ""; }; + 789AD1D324D97F8500CB0B4C /* SLSystemAppInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLSystemAppInfo.h; sourceTree = ""; }; + 789AD1D424D97F8500CB0B4C /* SLSystemAppInfo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLSystemAppInfo.m; sourceTree = ""; }; 78A179A6249B0AA8006F52E3 /* NSDictionary+SLExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+SLExtension.m"; sourceTree = ""; }; 78A179A7249B0AA8006F52E3 /* NSDictionary+SLExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+SLExtension.h"; sourceTree = ""; }; 78A1998A2451BEE7005B2B4B /* UIButton+SLTitleImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIButton+SLTitleImage.h"; sourceTree = ""; }; @@ -905,6 +911,10 @@ 789AD16224C99DCA00CB0B4C /* SLAPMThreadCount.m */, 789AD1C624D7FA5F00CB0B4C /* SLAPMURLProtocol.h */, 789AD1C724D7FA5F00CB0B4C /* SLAPMURLProtocol.m */, + 789AD1D024D9622B00CB0B4C /* UIViewController+SLAPMTime.h */, + 789AD1D124D9622B00CB0B4C /* UIViewController+SLAPMTime.m */, + 789AD1D324D97F8500CB0B4C /* SLSystemAppInfo.h */, + 789AD1D424D97F8500CB0B4C /* SLSystemAppInfo.m */, ); path = APMMonitor; sourceTree = ""; @@ -1415,6 +1425,7 @@ 784B72062334685E006AEE47 /* SLAvPlayer.m in Sources */, 78DAA113235FF61E00A60F64 /* SLEditVideoClipping.m in Sources */, 782E3EB42373D8C7001E0DF9 /* SLAvWriterInput.m in Sources */, + 789AD1D524D97F8500CB0B4C /* SLSystemAppInfo.m in Sources */, 78804A7E237D5E3E0087E152 /* SLWaterMarkController.m in Sources */, 78EF8B6024162B96008D0CD7 /* SLMenuViewController.m in Sources */, 7869C72224A8B6D200527546 /* SLPictureBrowseController.m in Sources */, @@ -1495,6 +1506,7 @@ 784C4BE424BC4C5E00D5C199 /* SLAPMManager.m in Sources */, 784C4C3A24C2EE6600D5C199 /* SLAPMMemoryDisk.m in Sources */, 78842468248FAED100C2E505 /* SLColorPickerViewController.m in Sources */, + 789AD1D224D9622B00CB0B4C /* UIViewController+SLAPMTime.m in Sources */, 787C7DCF2462B03D005DF7ED /* UINavigationController+SLMLeakFinder.m in Sources */, 789AD16324C99DCA00CB0B4C /* SLAPMThreadCount.m in Sources */, 788ACD622390BFD400737EC2 /* SLLoadImageVC.m in Sources */, diff --git a/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch b/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch index 9b9d0e20..8c623156 100644 --- a/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch +++ b/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch @@ -98,12 +98,12 @@ /** 快速查询一段代码的执行时间 */ /** 用法 - TICK + SL_StartTime do your work here - TOCK + SL_EndDuration */ -#define TICK NSDate *startTime = [NSDate date]; -#define TOCK NSLog(@"Time:%f", -[startTime timeIntervalSinceNow]); +#define SL_StartTime NSDate *startTime = [NSDate date] +#define SL_EndDuration -[startTime timeIntervalSinceNow] // STRING容错机制 #define SL_IS_NULL(x) (!x || [x isKindOfClass:[NSNull class]]) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h new file mode 100644 index 00000000..79dad3e1 --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h @@ -0,0 +1,17 @@ +// +// SLSystemAppInfo.h +// DarkMode +// +// Created by wsl on 2020/8/4. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface SLSystemAppInfo : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m new file mode 100644 index 00000000..f66013af --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m @@ -0,0 +1,17 @@ +// +// SLSystemAppInfo.m +// DarkMode +// +// Created by wsl on 2020/8/4. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLSystemAppInfo.h" + +@interface SLSystemAppInfo () + +@end + +@implementation SLSystemAppInfo + +@end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMTime.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMTime.h new file mode 100644 index 00000000..659a2782 --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMTime.h @@ -0,0 +1,17 @@ +// +// UIViewController+SLAPMTime.h +// DarkMode +// +// Created by wsl on 2020/8/4. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIViewController (SLAPMTime) + +@end + +NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMTime.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMTime.m new file mode 100644 index 00000000..c909f10e --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMTime.m @@ -0,0 +1,13 @@ +// +// UIViewController+SLAPMTime.m +// DarkMode +// +// Created by wsl on 2020/8/4. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "UIViewController+SLAPMTime.h" + +@implementation UIViewController (SLAPMTime) + +@end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m index 3d713d15..cbd50350 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m @@ -17,12 +17,19 @@ */ @interface SLAPMViewController () - +{ + NSDate *_date; +} @end @implementation SLAPMViewController #pragma mark - Override + +- (void)loadView { + [super loadView]; + _date = [NSDate date]; +} - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; @@ -30,14 +37,18 @@ - (void)viewDidLoad { [self setupNavigationBar]; [SLAPMManager manager].type = SLAPMTypeNetwork; } - -//测试卡顿 -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { - //耗时任务 - // sleep(1); - dispatch_async(dispatch_get_global_queue(0, 0), ^{ - sleep(1); - }); +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; +} +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + NSLog(@"Time: %f",-[_date timeIntervalSinceNow]); +} +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; +} +- (void)viewDidDisappear:(BOOL)animated { + [super viewDidDisappear:animated]; } #pragma mark - UI @@ -46,6 +57,14 @@ - (void)setupNavigationBar { } #pragma mark - Help Methods +///测试卡顿/流畅度 +- (void)testFluency { + //耗时任务 + // sleep(1); + dispatch_async(dispatch_get_global_queue(0, 0), ^{ + sleep(1); + }); +} ///测试网络监控 - (void)testNetworkMonitor { UIImageView *imageView = [[UIImageView alloc] init]; diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index dc467e40..da772ea8 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -32,3 +32,4 @@ * 30、[Lision](https://juejin.im/user/2189882891443278) * 31、[小鱼周凌宇](https://juejin.im/post/6844903616696844302) * 32、[satanwoo](http://satanwoo.github.io/) +* 33、[景铭巴巴](https://www.jianshu.com/u/c3c893a27097) From eb941f7852913c329f0d56b2532d90a810c16761 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 5 Aug 2020 17:00:45 +0800 Subject: [PATCH 120/356] =?UTF-8?q?APM=20=E4=B9=8BVC=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E8=80=97=E6=97=B6=E6=A3=80=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 12 +- .../Crash/SLCrashProtector/SLCrashProtector.h | 1 + .../APMMonitor/UIViewController+SLAPMTime.m | 13 -- ...MTime.h => UIViewController+SLAPMVCTime.h} | 10 +- .../APMMonitor/UIViewController+SLAPMVCTime.m | 176 ++++++++++++++++++ .../WorkIssues/APM/SLAPMViewController.m | 16 +- ...00\346\234\257\345\215\232\345\256\242.md" | 2 + 7 files changed, 194 insertions(+), 36 deletions(-) delete mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMTime.m rename iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/{UIViewController+SLAPMTime.h => UIViewController+SLAPMVCTime.h} (50%) create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMVCTime.m diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index a04f7d0b..81b8b684 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -124,7 +124,7 @@ 789AD16324C99DCA00CB0B4C /* SLAPMThreadCount.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD16224C99DCA00CB0B4C /* SLAPMThreadCount.m */; }; 789AD1C824D7FA5F00CB0B4C /* SLAPMURLProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD1C724D7FA5F00CB0B4C /* SLAPMURLProtocol.m */; }; 789AD1CF24D9024300CB0B4C /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD1CD24D9024300CB0B4C /* Reachability.m */; }; - 789AD1D224D9622B00CB0B4C /* UIViewController+SLAPMTime.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD1D124D9622B00CB0B4C /* UIViewController+SLAPMTime.m */; }; + 789AD1D224D9622B00CB0B4C /* UIViewController+SLAPMVCTime.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD1D124D9622B00CB0B4C /* UIViewController+SLAPMVCTime.m */; }; 789AD1D524D97F8500CB0B4C /* SLSystemAppInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD1D424D97F8500CB0B4C /* SLSystemAppInfo.m */; }; 78A179A8249B0AA8006F52E3 /* NSDictionary+SLExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A179A6249B0AA8006F52E3 /* NSDictionary+SLExtension.m */; }; 78A1998C2451BEE7005B2B4B /* UIButton+SLTitleImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A1998B2451BEE7005B2B4B /* UIButton+SLTitleImage.m */; }; @@ -389,8 +389,8 @@ 789AD1C724D7FA5F00CB0B4C /* SLAPMURLProtocol.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMURLProtocol.m; sourceTree = ""; }; 789AD1CD24D9024300CB0B4C /* Reachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Reachability.m; sourceTree = ""; }; 789AD1CE24D9024300CB0B4C /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reachability.h; sourceTree = ""; }; - 789AD1D024D9622B00CB0B4C /* UIViewController+SLAPMTime.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIViewController+SLAPMTime.h"; sourceTree = ""; }; - 789AD1D124D9622B00CB0B4C /* UIViewController+SLAPMTime.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+SLAPMTime.m"; sourceTree = ""; }; + 789AD1D024D9622B00CB0B4C /* UIViewController+SLAPMVCTime.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIViewController+SLAPMVCTime.h"; sourceTree = ""; }; + 789AD1D124D9622B00CB0B4C /* UIViewController+SLAPMVCTime.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+SLAPMVCTime.m"; sourceTree = ""; }; 789AD1D324D97F8500CB0B4C /* SLSystemAppInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLSystemAppInfo.h; sourceTree = ""; }; 789AD1D424D97F8500CB0B4C /* SLSystemAppInfo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLSystemAppInfo.m; sourceTree = ""; }; 78A179A6249B0AA8006F52E3 /* NSDictionary+SLExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+SLExtension.m"; sourceTree = ""; }; @@ -911,8 +911,8 @@ 789AD16224C99DCA00CB0B4C /* SLAPMThreadCount.m */, 789AD1C624D7FA5F00CB0B4C /* SLAPMURLProtocol.h */, 789AD1C724D7FA5F00CB0B4C /* SLAPMURLProtocol.m */, - 789AD1D024D9622B00CB0B4C /* UIViewController+SLAPMTime.h */, - 789AD1D124D9622B00CB0B4C /* UIViewController+SLAPMTime.m */, + 789AD1D024D9622B00CB0B4C /* UIViewController+SLAPMVCTime.h */, + 789AD1D124D9622B00CB0B4C /* UIViewController+SLAPMVCTime.m */, 789AD1D324D97F8500CB0B4C /* SLSystemAppInfo.h */, 789AD1D424D97F8500CB0B4C /* SLSystemAppInfo.m */, ); @@ -1506,7 +1506,7 @@ 784C4BE424BC4C5E00D5C199 /* SLAPMManager.m in Sources */, 784C4C3A24C2EE6600D5C199 /* SLAPMMemoryDisk.m in Sources */, 78842468248FAED100C2E505 /* SLColorPickerViewController.m in Sources */, - 789AD1D224D9622B00CB0B4C /* UIViewController+SLAPMTime.m in Sources */, + 789AD1D224D9622B00CB0B4C /* UIViewController+SLAPMVCTime.m in Sources */, 787C7DCF2462B03D005DF7ED /* UINavigationController+SLMLeakFinder.m in Sources */, 789AD16324C99DCA00CB0B4C /* SLAPMThreadCount.m in Sources */, 788ACD622390BFD400737EC2 /* SLLoadImageVC.m in Sources */, diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashProtector.h b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashProtector.h index 064ab968..93575826 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashProtector.h +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashProtector.h @@ -17,6 +17,7 @@ /*交换实例方法*/ static inline void SL_ExchangeInstanceMethod(Class _originalClass ,SEL _originalSel, Class _targetClass, SEL _targetSel){ + //此处获得的方法可能是父类对象的 Method methodOriginal = class_getInstanceMethod(_originalClass, _originalSel); Method methodNew = class_getInstanceMethod(_targetClass, _targetSel); // class_addMethod 返回成功表示被替换的方法没实现,然后会通过 class_addMethod 方法先实现;返回失败则表示被替换方法已存在,可以直接进行 IMP 指针交换 diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMTime.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMTime.m deleted file mode 100644 index c909f10e..00000000 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMTime.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// UIViewController+SLAPMTime.m -// DarkMode -// -// Created by wsl on 2020/8/4. -// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. -// - -#import "UIViewController+SLAPMTime.h" - -@implementation UIViewController (SLAPMTime) - -@end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMTime.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMVCTime.h similarity index 50% rename from iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMTime.h rename to iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMVCTime.h index 659a2782..2ede78c9 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMTime.h +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMVCTime.h @@ -1,5 +1,5 @@ // -// UIViewController+SLAPMTime.h +// UIViewController+SLAPMVCTime.h // DarkMode // // Created by wsl on 2020/8/4. @@ -10,7 +10,13 @@ NS_ASSUME_NONNULL_BEGIN -@interface UIViewController (SLAPMTime) +///ViewController启动耗时监测 +@interface UIViewController (SLAPMVCTime) + +///开始监听网络 ++ (void)startMonitorVC; +///结束监听网络 ++ (void)stopMonitorVC; @end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMVCTime.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMVCTime.m new file mode 100644 index 00000000..b393b5b3 --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMVCTime.m @@ -0,0 +1,176 @@ +// +// UIViewController+SLAPMVCTime.m +// DarkMode +// +// Created by wsl on 2020/8/4. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "UIViewController+SLAPMVCTime.h" +#import + +static char const kSLFakeKVORemoverKey; //关联的对象Key +static char const kSLVCBeginDateKey; //vc开始加载时间的key + +static NSString *const kSLFakeKeyPath = @"SL_FakeKeyPath"; //假冒的被观察属性key + +///冒充KVO观察者,是为了生成观察目标的KVO子类 +@interface SLFakeKVOObserver : NSObject +@end +@implementation SLFakeKVOObserver ++ (instancetype)shared { + static id sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[self alloc] init]; + }); + return sharedInstance; +} +@end +///负责移除冒充的KVO观察者 +@interface SLFakeKVORemover : NSObject +@property (nonatomic, weak) id target; //被观察的目标 +@end +@implementation SLFakeKVORemover +- (void)dealloc { + [_target removeObserver:[SLFakeKVOObserver shared] forKeyPath:kSLFakeKeyPath]; +} +@end + +@implementation UIViewController (SLAPMVCTime) + +#pragma mark - Public +///开始监听网络 ++ (void)startMonitorVC { + +} +///结束监听网络 ++ (void)stopMonitorVC { + +} + ++ (void)load { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + Class class = [UIViewController class]; + ///hook vc的初始化方法 + [self swizzleMethodInClass:class originalMethod:@selector(initWithNibName:bundle:) swizzledSelector:@selector(apm_initWithNibName:bundle:)]; + [self swizzleMethodInClass:class originalMethod:@selector(initWithCoder:) swizzledSelector:@selector(apm_initWithCoder:)]; + }); +} +- (instancetype)apm_initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil { + [self createAndHookKVOClass]; + [self apm_initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + return self; +} +- (nullable instancetype)apm_initWithCoder:(NSCoder *)aDecoder { + [self createAndHookKVOClass]; + [self apm_initWithCoder:aDecoder]; + return self; +} +///创建vc的KVO子类并hook子类的相关方法 +- (void)createAndHookKVOClass { + //设置KVO,会触发runtime来创建VC的KVO子类 + [self addObserver:[SLFakeKVOObserver shared] forKeyPath:kSLFakeKeyPath options:NSKeyValueObservingOptionNew context:nil]; + + //保存观察目标VC,当VC实例释放时,移除KVO + SLFakeKVORemover *remover = [[SLFakeKVORemover alloc] init]; + remover.target = self; + objc_setAssociatedObject(self, &kSLFakeKVORemoverKey, remover, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + //获取VC的KVO子类 NSKVONotifying_ViewController + Class kvoClass = object_getClass(self); + + //判断当前的IMP和我们的IMP在之前是否已hook + IMP currentViewDidLoadImp = class_getMethodImplementation(kvoClass, @selector(viewDidLoad)); + if (currentViewDidLoadImp == (IMP)apm_viewDidLoad) { + return; + } + + //KVO子类的父类,即当前类,原来的类 + Class originCls = class_getSuperclass(kvoClass); + + // 获取原来实现的encoding + const char *originLoadViewEncoding = method_getTypeEncoding(class_getInstanceMethod(originCls, @selector(loadView))); + const char *originViewDidLoadEncoding = method_getTypeEncoding(class_getInstanceMethod(originCls, @selector(viewDidLoad))); + const char *originViewWillAppearEncoding = method_getTypeEncoding(class_getInstanceMethod(originCls, @selector(viewWillAppear:))); + const char *originViewDidAppearEncoding = method_getTypeEncoding(class_getInstanceMethod(originCls, @selector(viewDidAppear:))); + const char *originViewDidDisappearEncoding = method_getTypeEncoding(class_getInstanceMethod(originCls, @selector(viewDidDisappear:))); + + // 添加方法,因为生成的KVO子类本身并没有实现loadView等方法,如果已实现了会添加失败。 + class_addMethod(kvoClass, @selector(loadView), (IMP)apm_loadView, originLoadViewEncoding); + class_addMethod(kvoClass, @selector(viewDidLoad), (IMP)apm_viewDidLoad, originViewDidLoadEncoding); + class_addMethod(kvoClass, @selector(viewWillAppear:), (IMP)apm_viewWillAppear, originViewWillAppearEncoding); + class_addMethod(kvoClass, @selector(viewDidAppear:), (IMP)apm_viewDidAppear, originViewDidAppearEncoding); + class_addMethod(kvoClass, @selector(viewDidDisappear:), (IMP)apm_viewDidDisappear, originViewDidDisappearEncoding); +} +///方法实现交换 ++ (void)swizzleMethodInClass:(Class) class originalMethod:(SEL)originalSelector swizzledSelector:(SEL)swizzledSelector { + Method originalMethod = class_getInstanceMethod(class, originalSelector); + Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); + BOOL didAddMethod = class_addMethod(class, + originalSelector, + method_getImplementation(swizzledMethod), + method_getTypeEncoding(swizzledMethod)); + + if (didAddMethod) { + class_replaceMethod(class, + swizzledSelector, + method_getImplementation(originalMethod), + method_getTypeEncoding(originalMethod)); + } else { + method_exchangeImplementations(originalMethod, swizzledMethod); + } +} + +#pragma mark - IMP of hook +static void apm_loadView(UIViewController *kvo_self, SEL _sel) { + IMP origin_imp = apm_originalMethodImplementation(kvo_self, _sel); + void (*func)(UIViewController *, SEL) = (void (*)(UIViewController *, SEL))origin_imp; + + //记录开始加载的时间 + objc_setAssociatedObject(kvo_self, &kSLVCBeginDateKey, [NSDate date], OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + //执行原来origin_cls的方法实现 + func(kvo_self, _sel); +} +static void apm_viewDidLoad(UIViewController *kvo_self, SEL _sel) { + IMP origin_imp = apm_originalMethodImplementation(kvo_self, _sel); + void (*func)(UIViewController *, SEL) = (void (*)(UIViewController *, SEL))origin_imp; + func(kvo_self, _sel); +} +static void apm_viewWillAppear(UIViewController *kvo_self, SEL _sel, BOOL animated) { + IMP origin_imp = apm_originalMethodImplementation(kvo_self, _sel); + void (*func)(UIViewController *, SEL, BOOL) = (void (*)(UIViewController *, SEL, BOOL))origin_imp; + func(kvo_self, _sel, animated); +} +static void apm_viewDidAppear(UIViewController *kvo_self, SEL _sel, BOOL animated) { + IMP origin_imp = apm_originalMethodImplementation(kvo_self, _sel); + void (*func)(UIViewController *, SEL, BOOL) = (void (*)(UIViewController *, SEL, BOOL))origin_imp; + func(kvo_self, _sel, animated); + + NSDate *beginDate = objc_getAssociatedObject(kvo_self, &kSLVCBeginDateKey); + //计算方法耗时 + NSTimeInterval duration = -[beginDate timeIntervalSinceNow]; + if (beginDate) { + NSLog(@"VC: %@ -loadView --> -viewDidAppear 用时: %f", [kvo_self class], duration); + } +} +static void apm_viewDidDisappear(UIViewController *kvo_self, SEL _sel, BOOL animated) { + IMP origin_imp = apm_originalMethodImplementation(kvo_self, _sel); + void (*func)(UIViewController *, SEL, BOOL) = (void (*)(UIViewController *, SEL, BOOL))origin_imp; + func(kvo_self, _sel, animated); + //重置记录的开始时间 + objc_setAssociatedObject(kvo_self, &kSLVCBeginDateKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +///返回原方法的IMP实现 +static IMP apm_originalMethodImplementation(UIViewController *kvo_self, SEL _sel) { + Class kvo_cls = object_getClass(kvo_self); + Class origin_cls = class_getSuperclass(kvo_cls); + IMP origin_imp = method_getImplementation(class_getInstanceMethod(origin_cls, _sel)); + assert(origin_imp != NULL); + return origin_imp; +} + +@end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m index cbd50350..df97a783 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m @@ -17,19 +17,11 @@ */ @interface SLAPMViewController () -{ - NSDate *_date; -} @end @implementation SLAPMViewController #pragma mark - Override - -- (void)loadView { - [super loadView]; - _date = [NSDate date]; -} - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; @@ -39,16 +31,10 @@ - (void)viewDidLoad { } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; + sleep(3); } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; - NSLog(@"Time: %f",-[_date timeIntervalSinceNow]); -} -- (void)viewWillDisappear:(BOOL)animated { - [super viewWillDisappear:animated]; -} -- (void)viewDidDisappear:(BOOL)animated { - [super viewDidDisappear:animated]; } #pragma mark - UI diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index da772ea8..e2410c81 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -33,3 +33,5 @@ * 31、[小鱼周凌宇](https://juejin.im/post/6844903616696844302) * 32、[satanwoo](http://satanwoo.github.io/) * 33、[景铭巴巴](https://www.jianshu.com/u/c3c893a27097) +* 34、[punmy](https://punmy.cn/) +* 35、[LearnOpengl](https://learnopengl-cn.github.io) From 1b2489fcc5820d1d18a8043f28ebc81e6dde114e Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 5 Aug 2020 17:13:55 +0800 Subject: [PATCH 121/356] =?UTF-8?q?APM=20=E4=B9=8BVC=E7=9A=84=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E8=80=97=E6=97=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/APM/APMMonitor/SLAPMManager.h | 4 ++- .../APMMonitor/UIViewController+SLAPMVCTime.h | 7 +---- .../APMMonitor/UIViewController+SLAPMVCTime.m | 27 +++++-------------- 3 files changed, 11 insertions(+), 27 deletions(-) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMManager.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMManager.h index bb21f987..f4951887 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMManager.h +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMManager.h @@ -26,8 +26,10 @@ typedef NS_ENUM(NSInteger, SLAPMType) { SLAPMTypeThreadCount = 1 << 4, /*网络监控*/ SLAPMTypeNetwork = 1 << 5, + /*VC启动耗时监测*/ + SLAPMTypeVCTime = 1 << 6, /*所有策略*/ - SLAPMTypeAll = 1 << 6 + SLAPMTypeAll = 1 << 7 }; diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMVCTime.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMVCTime.h index 2ede78c9..ea3e7117 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMVCTime.h +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMVCTime.h @@ -10,14 +10,9 @@ NS_ASSUME_NONNULL_BEGIN -///ViewController启动耗时监测 +///ViewController启动耗时监测 -loadView --> -viewDidAppear @interface UIViewController (SLAPMVCTime) -///开始监听网络 -+ (void)startMonitorVC; -///结束监听网络 -+ (void)stopMonitorVC; - @end NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMVCTime.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMVCTime.m index b393b5b3..a198b185 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMVCTime.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/UIViewController+SLAPMVCTime.m @@ -39,20 +39,14 @@ - (void)dealloc { @implementation UIViewController (SLAPMVCTime) -#pragma mark - Public -///开始监听网络 -+ (void)startMonitorVC { - -} -///结束监听网络 -+ (void)stopMonitorVC { - -} - + (void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ Class class = [UIViewController class]; + if (![NSStringFromClass(class) hasPrefix:@"SL"]) { + //仅仅测自己创建的VC + return; + } ///hook vc的初始化方法 [self swizzleMethodInClass:class originalMethod:@selector(initWithNibName:bundle:) swizzledSelector:@selector(apm_initWithNibName:bundle:)]; [self swizzleMethodInClass:class originalMethod:@selector(initWithCoder:) swizzledSelector:@selector(apm_initWithCoder:)]; @@ -95,14 +89,12 @@ - (void)createAndHookKVOClass { const char *originViewDidLoadEncoding = method_getTypeEncoding(class_getInstanceMethod(originCls, @selector(viewDidLoad))); const char *originViewWillAppearEncoding = method_getTypeEncoding(class_getInstanceMethod(originCls, @selector(viewWillAppear:))); const char *originViewDidAppearEncoding = method_getTypeEncoding(class_getInstanceMethod(originCls, @selector(viewDidAppear:))); - const char *originViewDidDisappearEncoding = method_getTypeEncoding(class_getInstanceMethod(originCls, @selector(viewDidDisappear:))); // 添加方法,因为生成的KVO子类本身并没有实现loadView等方法,如果已实现了会添加失败。 class_addMethod(kvoClass, @selector(loadView), (IMP)apm_loadView, originLoadViewEncoding); class_addMethod(kvoClass, @selector(viewDidLoad), (IMP)apm_viewDidLoad, originViewDidLoadEncoding); class_addMethod(kvoClass, @selector(viewWillAppear:), (IMP)apm_viewWillAppear, originViewWillAppearEncoding); class_addMethod(kvoClass, @selector(viewDidAppear:), (IMP)apm_viewDidAppear, originViewDidAppearEncoding); - class_addMethod(kvoClass, @selector(viewDidDisappear:), (IMP)apm_viewDidDisappear, originViewDidDisappearEncoding); } ///方法实现交换 + (void)swizzleMethodInClass:(Class) class originalMethod:(SEL)originalSelector swizzledSelector:(SEL)swizzledSelector { @@ -123,7 +115,7 @@ + (void)swizzleMethodInClass:(Class) class originalMethod:(SEL)originalSelector } } -#pragma mark - IMP of hook +#pragma mark - IMP of Hook static void apm_loadView(UIViewController *kvo_self, SEL _sel) { IMP origin_imp = apm_originalMethodImplementation(kvo_self, _sel); void (*func)(UIViewController *, SEL) = (void (*)(UIViewController *, SEL))origin_imp; @@ -150,16 +142,11 @@ static void apm_viewDidAppear(UIViewController *kvo_self, SEL _sel, BOOL animate func(kvo_self, _sel, animated); NSDate *beginDate = objc_getAssociatedObject(kvo_self, &kSLVCBeginDateKey); - //计算方法耗时 - NSTimeInterval duration = -[beginDate timeIntervalSinceNow]; if (beginDate) { + //计算方法耗时 + NSTimeInterval duration = -[beginDate timeIntervalSinceNow]; NSLog(@"VC: %@ -loadView --> -viewDidAppear 用时: %f", [kvo_self class], duration); } -} -static void apm_viewDidDisappear(UIViewController *kvo_self, SEL _sel, BOOL animated) { - IMP origin_imp = apm_originalMethodImplementation(kvo_self, _sel); - void (*func)(UIViewController *, SEL, BOOL) = (void (*)(UIViewController *, SEL, BOOL))origin_imp; - func(kvo_self, _sel, animated); //重置记录的开始时间 objc_setAssociatedObject(kvo_self, &kSLVCBeginDateKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } From 3e8dbb03fba074278640721100019486fdcb0746 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 5 Aug 2020 17:23:08 +0800 Subject: [PATCH 122/356] =?UTF-8?q?=E5=8D=9A=E5=AE=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 7 +++++++ 1 file changed, 7 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index e2410c81..8a0da1de 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -35,3 +35,10 @@ * 33、[景铭巴巴](https://www.jianshu.com/u/c3c893a27097) * 34、[punmy](https://punmy.cn/) * 35、[LearnOpengl](https://learnopengl-cn.github.io) + + +## 高质量微信公众号 + +* 1、[一瓜技术](公众号:tech_gua) +* 2、[奔跑的程序猿iOSer](公众号:iOS2679114653) +* 3、[知识小集](公众号:zsxjtip) From 8c6cd32001a8b6b4dbbbb629ab9fccc9e755c204 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Wed, 5 Aug 2020 18:15:43 +0800 Subject: [PATCH 123/356] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 07a9db8f..eaffd9f2 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ #### 6.7-[二进制重排优化启动速度](https://juejin.im/post/5ea79839f265da7bba509590) #### 6.8-[iOS APM应用性能监控管理(doing)]() -> CPU占用率、内存/磁盘使用率、卡顿监控定位、Crash防护、线程数量监控 ...... +> CPU占用率、内存/磁盘使用率、卡顿监控定位、Crash防护、线程数量监控、网络监控(TCP 建立连接时间 、DNS 时间、 SSL时间、首包时间、响应时间 、流量)、ViewController启动耗时监测 ...... ## 7-iOSCrash防护 From 207204d9d76d4a9e2a58648e811d367657bc3f76 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 5 Aug 2020 20:31:34 +0800 Subject: [PATCH 124/356] =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E5=BA=94=E7=94=A8?= =?UTF-8?q?=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/APM/APMMonitor/SLAPMManager.m | 2 +- .../APM/APMMonitor/SLAPMMemoryDisk.h | 4 +- .../APM/APMMonitor/SLAPMMemoryDisk.m | 4 +- .../APM/APMMonitor/SLSystemAppInfo.h | 5 + .../APM/APMMonitor/SLSystemAppInfo.m | 153 ++++++++++++++++++ .../WorkIssues/APM/SLAPMViewController.m | 6 +- 6 files changed, 168 insertions(+), 6 deletions(-) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMManager.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMManager.m index f9200b71..3aacf02f 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMManager.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMManager.m @@ -93,7 +93,7 @@ - (void)monitoring { } if ((self.type & SLAPMTypeMemory) == SLAPMTypeMemory || self.type == SLAPMTypeAll) { - double useMemory = [SLAPMMemoryDisk getUsageMemory]; + double useMemory = [SLAPMMemoryDisk getAppUsageMemory]; double freeMemory = [SLAPMMemoryDisk getFreeMemory]; double totalMemory = [SLAPMMemoryDisk getTotalMemory]; NSLog(@" Memory占用:%.1fM 空闲:%.1fM 总共:%.1fM",useMemory, freeMemory, totalMemory); diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMMemoryDisk.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMMemoryDisk.h index cea3c063..67f7f2bd 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMMemoryDisk.h +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMMemoryDisk.h @@ -14,14 +14,14 @@ NS_ASSUME_NONNULL_BEGIN @interface SLAPMMemoryDisk : NSObject ///当前应用的内存占用情况,和Xcode数值相近 单位MB -+ (double)getUsageMemory; ++ (double)getAppUsageMemory; ///剩余空闲内存 单位MB + (double)getFreeMemory; /// 总共的内存大小 单位MB + (double)getTotalMemory; ///filePath目录下的文件 占用的磁盘大小 单位MB 默认沙盒Caches目录 此句代码不要频繁定时执行,比较耗内存 -+ (double)getUsageDisk:(NSString *)filePath; ++ (double)getFileUsageDisk:(NSString *)filePath; ///剩余空闲的磁盘容量 单位G + (double)getFreeDisk; ///总磁盘容量 单位G diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMMemoryDisk.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMMemoryDisk.m index d7b8bfff..f07432bb 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMMemoryDisk.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMMemoryDisk.m @@ -14,7 +14,7 @@ @implementation SLAPMMemoryDisk #pragma mark - Memory / Disk ///当前应用的内存占用情况,和Xcode数值相近 单位MB -+ (double)getUsageMemory { ++ (double)getAppUsageMemory { task_vm_info_data_t vmInfo; mach_msg_type_number_t count = TASK_VM_INFO_COUNT; if(task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &count) == KERN_SUCCESS) { @@ -45,7 +45,7 @@ + (double)getTotalMemory { } ///filePath目录下的文件 占用的磁盘大小 单位MB 默认沙盒Caches目录 -+ (double)getUsageDisk:(NSString *)filePath { ++ (double)getFileUsageDisk:(NSString *)filePath { if (filePath.length == 0) filePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject; ///定时执行时,此句代码会导致内存不断增长?0.1M 合理安排执行时机 NSArray *filesArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:filePath error:nil] ; diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h index 79dad3e1..65956b6e 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h @@ -12,6 +12,11 @@ NS_ASSUME_NONNULL_BEGIN @interface SLSystemAppInfo : NSObject ++ (void)test; + +///获取手机型号 ++ (NSString *)iphoneType; + @end NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m index f66013af..6f2133cd 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m @@ -7,6 +7,10 @@ // #import "SLSystemAppInfo.h" +#import "sys/utsname.h" +#import +#import + @interface SLSystemAppInfo () @@ -14,4 +18,153 @@ @interface SLSystemAppInfo () @implementation SLSystemAppInfo + ++ (void)test { + [self iphoneType]; + + [self systemVersion]; + [self deviceModel]; + [self userPhoneName]; + [self systemName]; + [self uuidString]; + [self localDeviceModel]; + [self telephonyInfo]; + [self networkType]; + + + [self appBundleId]; + [self appVersion]; + [self appBuild]; + [self appName]; + +} + +///获取手机型号 iPhone 8... ++ (NSString *)iphoneType{ + struct utsname systemInfo; + uname(&systemInfo); + NSString *deviceString = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; + NSDictionary *dict = @{@"iPhone1,1":@"iPhone 1G", + @"iPhone1,2":@"iPhone 3G", + @"iPhone2,1":@"iPhone 3GS", + @"iPhone3,1":@"iPhone 4", + @"iPhone3,2":@"iPhone 4", + @"iPhone4,1":@"iPhone 4S", + @"iPhone5,1":@"iPhone 5", + @"iPhone5,2":@"iPhone 5", + @"iPhone5,3":@"iPhone 5C", + @"iPhone5,4":@"iPhone 5C", + @"iPhone6,1":@"iPhone 5S", + @"iPhone6,2":@"iPhone 5S", + @"iPhone7,1":@"iPhone 6 Plus", + @"iPhone7,2":@"iPhone 6", + @"iPhone8,1":@"iPhone 6S", + @"iPhone8,2":@"iPhone 6S Plus", + @"iPhone8,4":@"iPhone SE", + @"iPhone9,1":@"iPhone 7", + @"iPhone9,3":@"iPhone 7", + @"iPhone9,2":@"iPhone 7 Plus", + @"iPhone9,4":@"iPhone 7 Plus", + @"iPhone10,1":@"iPhone 8", + @"iPhone10.4":@"iPhone 8", + @"iPhone10,2":@"iPhone 8 Plus", + @"iPhone10,5":@"iPhone 8 Plus", + @"iPhone10,3":@"iPhone X", + @"iPhone10,6":@"iPhone X", + @"iPhone11,8":@"iPhone XR", + @"iPhone11,2":@"iPhone XS", + @"iPhone11,4":@"iPhone XS Max", + @"iPhone11,6":@"iPhone XS Max", + @"i386":@"Simulator", + @"x86_64":@"Simulator" + }; + return dict[deviceString] == nil ? deviceString : dict[deviceString]; +} +///获取手机系统版本 13.4 ++ (NSString *)systemVersion { + NSString *systemVersion = [[UIDevice currentDevice] systemVersion]; + return systemVersion; +} +///获取设备类型 iPhone/iPad/iPod touch ++ (NSString *)deviceModel { + NSString* deviceModel = [[UIDevice currentDevice] model]; + return deviceModel; +} +///根据地区语言返回设备类型字符串 (国际化区域名称) ++(NSString *)localDeviceModel { + NSString* localizedModel = [[UIDevice currentDevice] localizedModel]; + return localizedModel;; +} +///操作系统名称 iOS ++ (NSString *)systemName { + NSString* systemName = [[UIDevice currentDevice] systemName]; + return systemName; +} +///获取用户手机别名 用户定义的名称 通用-关于本机-名称 wsl的iphone ++ (NSString *)userPhoneName { + NSString* userPhoneName = [[UIDevice currentDevice] name]; + return userPhoneName; +} +///设备唯一标识的字母数字字符串 C5668446-C443-4898-A213-209AECE3626C ++ (NSString *)uuidString { + NSString *UUIDString = [[UIDevice currentDevice] identifierForVendor].UUIDString; + return UUIDString; +} +/// 获取电话运营商信息 ++ (NSString *)telephonyInfo { + CTTelephonyNetworkInfo *info = [[CTTelephonyNetworkInfo alloc] init]; + CTCarrier *carrier = [info subscriberCellularProvider]; + NSString *mCarrier = [NSString stringWithFormat:@"%@",[carrier carrierName]]; + return mCarrier; +} +// 获取网络类型 ++(NSString*)networkType { + /** + CORETELEPHONY_EXTERN NSString * const CTRadioAccessTechnologyGPRS __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0); + CORETELEPHONY_EXTERN NSString * const CTRadioAccessTechnologyEdge __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0); + CORETELEPHONY_EXTERN NSString * const CTRadioAccessTechnologyWCDMA __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0); + CORETELEPHONY_EXTERN NSString * const CTRadioAccessTechnologyHSDPA __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0); + CORETELEPHONY_EXTERN NSString * const CTRadioAccessTechnologyHSUPA __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0); + CORETELEPHONY_EXTERN NSString * const CTRadioAccessTechnologyCDMA1x __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0); + CORETELEPHONY_EXTERN NSString * const CTRadioAccessTechnologyCDMAEVDORev0 __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0); + CORETELEPHONY_EXTERN NSString * const CTRadioAccessTechnologyCDMAEVDORevA __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0); + CORETELEPHONY_EXTERN NSString * const CTRadioAccessTechnologyCDMAEVDORevB __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0); + CORETELEPHONY_EXTERN NSString * const CTRadioAccessTechnologyeHRPD __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0); + CORETELEPHONY_EXTERN NSString * const CTRadioAccessTechnologyLTE __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0); + **/ + // + CTTelephonyNetworkInfo* info=[[CTTelephonyNetworkInfo alloc] init]; + if (@available(iOS 12.0, *)) { + NSDictionary *dict= info.serviceCurrentRadioAccessTechnology; + // NSLog(@"%@",dict); + } else { + } + NSString *networkType = info.currentRadioAccessTechnology; + return networkType; +} + +///获取APP名字 ++ (NSString *)appName { + NSString *appCurName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"]; + return appCurName; +} +///获取APP bundle id ++ (NSString *)appBundleId { + NSString *appBundleId = [[NSBundle mainBundle] bundleIdentifier]; + return appBundleId; +} +///获取当前App版本号 ++ (NSString *)appVersion { + NSString *appCurVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]; + return appCurVersion; +} +///获取当前App编译版本号 ++ (NSString *)appBuild { + NSString *appBuildVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]; + return appBuildVersion; +} + + + + @end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m index df97a783..f0038576 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m @@ -9,6 +9,8 @@ #import "SLAPMViewController.h" #import "SLAPMManager.h" +#import "SLSystemAppInfo.h" + /* 参考资料: https://www.jianshu.com/p/95df83780c8f @@ -28,10 +30,12 @@ - (void)viewDidLoad { self.navigationItem.title = @"APM监控"; [self setupNavigationBar]; [SLAPMManager manager].type = SLAPMTypeNetwork; + + [SLSystemAppInfo test]; + } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - sleep(3); } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; From 3585b74bcffdb1a0d70306478c78327fa05c5cc0 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 6 Aug 2020 20:15:23 +0800 Subject: [PATCH 125/356] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 4 +- .../Crash/SLCrashProtector/SLCrashHandler.m | 4 +- iOS_Tips/DarkMode/Info.plist | 40 +- .../APM/APMMonitor/SLSystemAppInfo.h | 20 +- .../APM/APMMonitor/SLSystemAppInfo.m | 378 +++++++++++++++++- .../WorkIssues/APM/SLAPMViewController.m | 2 +- ...00\346\234\257\345\215\232\345\256\242.md" | 2 +- 7 files changed, 427 insertions(+), 23 deletions(-) diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 81b8b684..2c6bc32e 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -1713,7 +1713,7 @@ NEW_SETTING = ""; ORDER_FILE = "$(SRCROOT)/DarkMode/WorkIssues/二进制重排/wsl.order"; OTHER_CFLAGS = "-fsanitize-coverage=func,trace-pc-guard"; - PRODUCT_BUNDLE_IDENTIFIER = com.wsl2ls.tip; + PRODUCT_BUNDLE_IDENTIFIER = com.wsl2ls.tips; PRODUCT_NAME = SLTips; PROVISIONING_PROFILE_SPECIFIER = ""; TARGETED_DEVICE_FAMILY = "1,2"; @@ -1744,7 +1744,7 @@ NEW_SETTING = ""; ORDER_FILE = "$(SRCROOT)/DarkMode/WorkIssues/二进制重排/wsl.order"; OTHER_CFLAGS = "-fsanitize-coverage=func,trace-pc-guard"; - PRODUCT_BUNDLE_IDENTIFIER = com.wsl2ls.tip; + PRODUCT_BUNDLE_IDENTIFIER = com.wsl2ls.tips; PRODUCT_NAME = SLTips; PROVISIONING_PROFILE_SPECIFIER = ""; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m index e6579182..7f1659dd 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m @@ -103,8 +103,8 @@ - (void)setMachPortListener:(mach_port_t)mach_port { NSString *exceptionInfo = [NSString stringWithFormat:@"mach异常:%@",callStack]; SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeUnknow errorDesc:exceptionInfo exception:nil callStack:@[callStack]]; [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; - - abort(); + //mach异常就终止当前程序 +// abort(); } }); } diff --git a/iOS_Tips/DarkMode/Info.plist b/iOS_Tips/DarkMode/Info.plist index c37014be..02e052e3 100644 --- a/iOS_Tips/DarkMode/Info.plist +++ b/iOS_Tips/DarkMode/Info.plist @@ -38,19 +38,51 @@ LSRequiresIPhoneOS + NFCReaderUsageDescription + 访问NFC NSAppTransportSecurity NSAllowsArbitraryLoads + NSAppleMusicUsageDescription + 访问媒体资料库 + NSBluetoothPeripheralUsageDescription + 访问蓝牙 + NSCalendarsUsageDescription + 访问日历 NSCameraUsageDescription - 此功能需要获取你的相机权限 + 获取相机权限 + NSContactsUsageDescription + 访问通讯录 + NSFaceIDUsageDescription + 访问Face ID + NSHealthShareUsageDescription + 访问健康分享 + NSHealthUpdateUsageDescription + 访问健康更新 + NSHomeKitUsageDescription + 访问住宅配件 + NSLocationAlwaysUsageDescription + 始终访问位置 + NSLocationWhenInUseUsageDescription + 在使用期间访问位置 NSMicrophoneUsageDescription - 此功能需要你的麦克风权限 + 获取你的麦克风权限 + NSMotionUsageDescription + 访问运动与健身 NSPhotoLibraryAddUsageDescription - 此功能需要获取你的相册权限 + 保存到相册需要获取你的相册权限 NSPhotoLibraryUsageDescription - 此功能需要获取你的相册权限 + 相册浏览需要获取你的相册权限 + NSRemindersUsageDescription + 访问提醒事项 + NSSiriUsageDescription + 使用Siri功能 + NSSpeechRecognitionUsageDescription + 使用语音识别功能 + NSVideoSubscriberAccountUsageDescription + 访问电视提供商 UIApplicationSceneManifest UIApplicationSupportsMultipleScenes diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h index 65956b6e..f77515e1 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h @@ -8,14 +8,28 @@ #import +typedef NS_ENUM(NSInteger, SLAuthorizationStatus) { + SLAuthorizationStatusUnknow = -1, //未知的 + SLAuthorizationStatusNotDetermined = 0, //用户还没有选择过(第一次) + SLAuthorizationStatusRestricted, //家长控制,限制用户授权的权限 + SLAuthorizationStatusDenied, //用户拒绝授权 + SLAuthorizationStatusAuthorized, //已授权 + SLAuthorizationStatusAuthorizedAlways, //始终都授权,比如定位,蓝牙 + SLAuthorizationStatusAuthorizedWhenInUse, //仅当应用使用时授权 比如定位 + SLAuthorizationStatusProvisional, //临时授权,用完一次即权利解除,下次再申请 + SLAuthorizationStatusUnsupported, //该硬件不支持授权的功能,比如蓝牙、FaceID、摄像头,设备可能不支持 + SLAuthorizationStatusOff //请求授权的功能处于关闭状态,比如蓝牙 +}; + NS_ASSUME_NONNULL_BEGIN +///包含系统、应用、隐私权限的信息 @interface SLSystemAppInfo : NSObject -+ (void)test; ++ (instancetype)manager; -///获取手机型号 -+ (NSString *)iphoneType; + ++ (void)test; @end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m index 6f2133cd..83caa70e 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m @@ -10,18 +10,32 @@ #import "sys/utsname.h" #import #import +#import +#include +#include +#include +#import +#import +#import +#import +#import +#import +#import -@interface SLSystemAppInfo () +#define SL_IOS_CELLULAR @"pdp_ip0" +#define SL_IOS_WIFI @"en0" +//#define IOS_VPN @"utun0" +#define SL_IP_ADDR_IPv4 @"ipv4" +#define SL_IP_ADDR_IPv6 @"ipv6" +@interface SLSystemAppInfo () @end - @implementation SLSystemAppInfo - + (void)test { - [self iphoneType]; + [self iphoneType]; [self systemVersion]; [self deviceModel]; [self userPhoneName]; @@ -30,15 +44,43 @@ + (void)test { [self localDeviceModel]; [self telephonyInfo]; [self networkType]; - + [self getIPAddress:YES]; [self appBundleId]; [self appVersion]; [self appBuild]; [self appName]; + [self checkPushAuthorization]; + [self checkPhotoLibraryAuthorization]; + [self checkLocationAuthorization]; + [self checkCameraAuthorization]; + [self checkMicrophoneAuthorization]; + } +#pragma mark - Override +/// 重写allocWithZone方法,保证alloc或者init创建的实例不会产生新实例,因为该类覆盖了allocWithZone方法,所以只能通过其父类分配内存,即[super allocWithZone] ++ (instancetype)allocWithZone:(struct _NSZone *)zone { + return [self manager]; +} +/// 重写copyWithZone方法,保证复制返回的是同一份实例 +- (nonnull id)copyWithZone:(nullable NSZone *)zone { + return [SLSystemAppInfo manager]; +} + +#pragma mark - Public ++ (instancetype)manager { + static SLSystemAppInfo *manager = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + manager = [[super allocWithZone:NULL] init]; + }); + return manager; +} + +#pragma mark - System Info + ///获取手机型号 iPhone 8... + (NSString *)iphoneType{ struct utsname systemInfo; @@ -75,6 +117,9 @@ + (NSString *)iphoneType{ @"iPhone11,2":@"iPhone XS", @"iPhone11,4":@"iPhone XS Max", @"iPhone11,6":@"iPhone XS Max", + @"iPhone12,1":@"iPhone 11", + @"iPhone12,3":@"iPhone 11 Pro", + @"iPhone12,5":@"iPhone 11 Pro Max", @"i386":@"Simulator", @"x86_64":@"Simulator" }; @@ -110,6 +155,35 @@ + (NSString *)uuidString { NSString *UUIDString = [[UIDevice currentDevice] identifierForVendor].UUIDString; return UUIDString; } +///是否是iPhoneX系列/刘海屏 ++ (BOOL)isIPhoneXSeries{ + BOOL iPhoneXSeries = NO; + if (UIDevice.currentDevice.userInterfaceIdiom != UIUserInterfaceIdiomPhone) { + return iPhoneXSeries; + } + if (@available(iOS 11.0, *)) { + UIWindow *mainWindow = [self getKeyWindow]; + if (mainWindow.safeAreaInsets.bottom > 0.0) { + iPhoneXSeries = YES; + } + } + return iPhoneXSeries; +} ++ (UIWindow *)getKeyWindow{ + UIWindow *keyWindow = nil; + if ([[UIApplication sharedApplication].delegate respondsToSelector:@selector(window)]) { + keyWindow = [[UIApplication sharedApplication].delegate window]; + }else{ + NSArray *windows = [UIApplication sharedApplication].windows; + for (UIWindow *window in windows) { + if (!window.hidden) { + keyWindow = window; + break; + } + } + } + return keyWindow; +} /// 获取电话运营商信息 + (NSString *)telephonyInfo { CTTelephonyNetworkInfo *info = [[CTTelephonyNetworkInfo alloc] init]; @@ -117,7 +191,7 @@ + (NSString *)telephonyInfo { NSString *mCarrier = [NSString stringWithFormat:@"%@",[carrier carrierName]]; return mCarrier; } -// 获取网络类型 +/// 获取网络类型 +(NSString*)networkType { /** CORETELEPHONY_EXTERN NSString * const CTRadioAccessTechnologyGPRS __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_7_0); @@ -142,29 +216,313 @@ +(NSString*)networkType { NSString *networkType = info.currentRadioAccessTechnology; return networkType; } +///获取设备当前网络IP地址 ++ (NSString *)getIPAddress:(BOOL)preferIPv4 { + NSArray *searchArray = preferIPv4 ? + @[ /*IOS_VPN @"/" SL_IP_ADDR_IPv4, IOS_VPN @"/" SL_IP_ADDR_IPv6,*/ SL_IOS_WIFI @"/" SL_IP_ADDR_IPv4, SL_IOS_WIFI @"/" SL_IP_ADDR_IPv6, SL_IOS_CELLULAR @"/" SL_IP_ADDR_IPv4, SL_IOS_CELLULAR @"/" SL_IP_ADDR_IPv6 ] : + @[ /*IOS_VPN @"/" SL_IP_ADDR_IPv6, IOS_VPN @"/" SL_IP_ADDR_IPv4,*/ SL_IOS_WIFI @"/" SL_IP_ADDR_IPv6, SL_IOS_WIFI @"/" SL_IP_ADDR_IPv4, SL_IOS_CELLULAR @"/" SL_IP_ADDR_IPv6, SL_IOS_CELLULAR @"/" SL_IP_ADDR_IPv4 ] ; + + NSDictionary *addresses = [[self class] getIPAddresses]; + __block NSString *address; + [searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop) + { + address = addresses[key]; + if(address) *stop = YES; + } ]; + return address ? address : @"0.0.0.0"; +} +//获取所有相关IP信息 ++ (NSDictionary *)getIPAddresses { + NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8]; + + // retrieve the current interfaces - returns 0 on success + struct ifaddrs *interfaces; + if(!getifaddrs(&interfaces)) { + // Loop through linked list of interfaces + struct ifaddrs *interface; + for(interface=interfaces; interface; interface=interface->ifa_next) { + if(!(interface->ifa_flags & IFF_UP) /* || (interface->ifa_flags & IFF_LOOPBACK) */ ) { + continue; // deeply nested code harder to read + } + const struct sockaddr_in *addr = (const struct sockaddr_in*)interface->ifa_addr; + char addrBuf[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) ]; + if(addr && (addr->sin_family==AF_INET || addr->sin_family==AF_INET6)) { + NSString *name = [NSString stringWithUTF8String:interface->ifa_name]; + NSString *type; + if(addr->sin_family == AF_INET) { + if(inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN)) { + type = SL_IP_ADDR_IPv4; + } + } else { + const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)interface->ifa_addr; + if(inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN)) { + type = SL_IP_ADDR_IPv6; + } + } + if(type) { + NSString *key = [NSString stringWithFormat:@"%@/%@", name, type]; + addresses[key] = [NSString stringWithUTF8String:addrBuf]; + } + } + } + // Free memory + freeifaddrs(interfaces); + } + return [addresses count] ? addresses : nil; +} -///获取APP名字 + + +#pragma mark - App Info +///获取APP名字 SLTips + (NSString *)appName { NSString *appCurName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"]; + if (!appCurName) { + appCurName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; + } return appCurName; } -///获取APP bundle id +///获取APP bundle id com.wsl2ls.tips + (NSString *)appBundleId { NSString *appBundleId = [[NSBundle mainBundle] bundleIdentifier]; return appBundleId; } -///获取当前App版本号 +///获取当前App版本号 1.1.0 + (NSString *)appVersion { NSString *appCurVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]; return appCurVersion; } -///获取当前App编译版本号 +///获取当前App编译版本号 1 + (NSString *)appBuild { NSString *appBuildVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]; return appBuildVersion; } +#pragma mark - 隐私权限 + +///检测推送通知权限 ++ (SLAuthorizationStatus)checkPushAuthorization{ + __block SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; +#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0 + if ([[UIApplication sharedApplication] currentUserNotificationSettings].types == UIUserNotificationTypeNone) { + authorizationStatus = SLAuthorizationStatusDenied; + return authorizationStatus; + }else { + authorizationStatus = SLAuthorizationStatusAuthorized; + return authorizationStatus; + } +#else + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + [[UNUserNotificationCenter currentNotificationCenter] getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) { + UNAuthorizationStatus pushAuthorizationStatus = settings.authorizationStatus; + switch (pushAuthorizationStatus) { + case UNAuthorizationStatusNotDetermined: + authorizationStatus = SLAuthorizationStatusNotDetermined; + break; + case UNAuthorizationStatusDenied: + authorizationStatus = SLAuthorizationStatusDenied; + break; + case UNAuthorizationStatusAuthorized: + authorizationStatus = SLAuthorizationStatusAuthorized; + break; + case UNAuthorizationStatusProvisional: + ///临时授权,用完权利解除,下次再申请 + authorizationStatus = SLAuthorizationStatusProvisional; + break; + default: + authorizationStatus = SLAuthorizationStatusUnknow; + break; + } + dispatch_semaphore_signal(semaphore); + }]; + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); +#endif + return authorizationStatus; +} + +///检查相册访问权限 ++ (SLAuthorizationStatus)checkPhotoLibraryAuthorization { + SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; +#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0 //iOS 8.0以下使用AssetsLibrary.framework + ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus]; + authorizationStatus = (SLAuthorizationStatus)status; +#else //iOS 8.0以上使用Photos.framework + PHAuthorizationStatus current = [PHPhotoLibrary authorizationStatus]; + authorizationStatus = (SLAuthorizationStatus)current; +#endif + return authorizationStatus; +} + +///检查定位权限 ++ (SLAuthorizationStatus)checkLocationAuthorization { + SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; + //定位服务是否可用 + if ([CLLocationManager locationServicesEnabled]) { + CLAuthorizationStatus state = [CLLocationManager authorizationStatus]; + if (state == kCLAuthorizationStatusNotDetermined) { + authorizationStatus = SLAuthorizationStatusNotDetermined; + }else if(state == kCLAuthorizationStatusRestricted){ + authorizationStatus = SLAuthorizationStatusRestricted; + }else if(state == kCLAuthorizationStatusDenied){ + authorizationStatus = SLAuthorizationStatusDenied; + }else if(state == kCLAuthorizationStatusAuthorizedAlways){ + authorizationStatus = SLAuthorizationStatusAuthorizedAlways; + }else if(state == kCLAuthorizationStatusAuthorizedWhenInUse){ + authorizationStatus = SLAuthorizationStatusAuthorizedWhenInUse; + } + }else{ + //定位服务不可用 + authorizationStatus = SLAuthorizationStatusUnsupported; + } + return authorizationStatus; +} + +///检查相机/摄像头权限 ++ (SLAuthorizationStatus)checkCameraAuthorization { + SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; + NSString *mediaType = AVMediaTypeVideo;//读取媒体类型 + AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType];//读取设备授权状态 + authorizationStatus = (SLAuthorizationStatus)authStatus; + return authorizationStatus; +} + +///检查话筒/麦克风权限 ++ (SLAuthorizationStatus)checkMicrophoneAuthorization { + SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; + NSString *mediaType = AVMediaTypeAudio;//读取媒体类型 + AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType];//读取设备授权状态 + authorizationStatus = (SLAuthorizationStatus)authStatus; + return authorizationStatus; +} + +///检测通讯录权限 ++ (SLAuthorizationStatus)checkContactsAuthorization{ + SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; + if (@available(iOS 9.0, *)) {//iOS9.0之后 + CNAuthorizationStatus authStatus = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts]; + authorizationStatus = (SLAuthorizationStatus)authStatus; + }else{//iOS9.0之前 + ABAuthorizationStatus authorStatus = ABAddressBookGetAuthorizationStatus(); + authorizationStatus = (SLAuthorizationStatus)authorStatus; + } + return authorizationStatus; +} + +///检测日历权限 ++ (SLAuthorizationStatus)checkCalendarAuthorization { + SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; + EKAuthorizationStatus status = [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent]; + authorizationStatus = (SLAuthorizationStatus)status; + return authorizationStatus; +} + +///检测提醒事项权限 ++ (SLAuthorizationStatus)checkRemindAuthorization { + SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; + EKAuthorizationStatus status = [EKEventStore authorizationStatusForEntityType:EKEntityTypeReminder]; + authorizationStatus = (SLAuthorizationStatus)status; + return authorizationStatus; +} +///检测蓝牙权限 +- (void)checkBluetoothAuthorization { + if (@available(iOS 13.1, *)) { + CBManagerAuthorization authorization = [CBManager authorization]; + SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; + if (authorization == CBManagerAuthorizationAllowedAlways) { + authorizationStatus = SLAuthorizationStatusAuthorizedAlways; + }else { + authorizationStatus = (SLAuthorizationStatus)authorization; + } + } else { + CBCentralManager *bluetoothManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil]; + } +} +///CBCentralManagerDelegate +- (void)centralManagerDidUpdateState:(CBCentralManager *)central { + SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; + CBManagerState state = central.state; + if (state == CBManagerStateResetting) { + //重置或重新连接 + authorizationStatus = SLAuthorizationStatusUnknow; + } else if (state == CBManagerStateUnsupported) { + //不支持蓝牙功能 + authorizationStatus = SLAuthorizationStatusUnsupported; + } else if (state == CBManagerStateUnauthorized) { + //拒绝授权 + authorizationStatus = SLAuthorizationStatusDenied; + } else if (state == CBManagerStatePoweredOff) { + //蓝牙处于关闭状态 + authorizationStatus = SLAuthorizationStatusOff; + } else if (state == CBManagerStatePoweredOn) { + //已授权 + authorizationStatus = SLAuthorizationStatusAuthorized; + } +} + +///请求FaceID权限 ++ (void)checkFaceIDAuthorization { + __block SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; + if (@available(iOS 11.0, *)) { + LAContext *authenticationContext = [[LAContext alloc]init]; + NSError *error = nil; + ///是否能验证人脸数据 + BOOL canEvaluatePolicy = [authenticationContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]; + if (canEvaluatePolicy) { + if (authenticationContext.biometryType == LABiometryTypeFaceID) { + //验证当前人脸数据 + [authenticationContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:@"开始验证" reply:^(BOOL success, NSError * _Nullable error) { + if (error) { + } else { + if (success) { + + } + } + }]; + } else { + + } + }else { + if (error.code == -8) { + NSLog(@"错误次数太多,被锁定"); + }else{ + NSLog(@"没有设置人脸数据,请前往设置"); + } + } + }else { + authorizationStatus = SLAuthorizationStatusUnsupported; + } + +} + + + +///请求相册权限 ++ (void)requestAuthorizationLibrary { + ///相册授权状态 + PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus]; + if (status == PHAuthorizationStatusNotDetermined) { + // 用户还没有做出过是否授权的选择 + // 只有第一次请求授权时才会自动出现系统弹窗,之后再请求授权时也不会弹出系统询问弹窗 + [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) { + dispatch_async(dispatch_get_main_queue(), ^{ + if (status == PHAuthorizationStatusAuthorized) { + // 用户第一次同意了访问相册权限 + NSLog(@"用户同意授权"); + }else if (status == PHAuthorizationStatusDenied){ + NSLog(@"用户拒绝授权"); + } + }); + }]; + NSLog(@"用户还没有过选择"); + }else if (status == PHAuthorizationStatusRestricted) { + NSLog(@"用户无法授予此类权限,比如家长控制"); + }else if (status == PHAuthorizationStatusDenied) { + NSLog(@"用户已拒绝授权"); + }else if (status == PHAuthorizationStatusAuthorized) { + NSLog(@"用户已同意授权"); + } +} @end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m index f0038576..a58e1be2 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m @@ -31,7 +31,7 @@ - (void)viewDidLoad { [self setupNavigationBar]; [SLAPMManager manager].type = SLAPMTypeNetwork; - [SLSystemAppInfo test]; +// [SLSystemAppInfo test]; } - (void)viewWillAppear:(BOOL)animated { diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 8a0da1de..6942c060 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -20,7 +20,7 @@ * 17、[阿里、字节 一套高效的iOS面试题解答](https://github.com/colourful987/bytedance-alibaba-interview) * 18、[面试题、基础知识点](https://github.com/liberalisman/iOS-InterviewQuestion-collection) * 19、[音视频笔记-雷霄骅](https://blog.csdn.net/leixiaohua1020) -* 20、[Joy___](https://www.jianshu.com/u/9c51a213b02e) +* 20、[乐少joy0304](https://github.com/joy0304/Joy-Blog) * 21、[maniac_kk](https://juejin.im/user/5aaf755cf265da23870ea3cf/posts) * 22、[阿里巴巴淘系技术](https://juejin.im/user/5e8558f3518825738f2b1327) * 23、[欧阳大哥2013](https://juejin.im/user/593fb40eda2f6000673bdc61) From 5fb20ed5ef68342f1e78e2d218372a337145d79b Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 7 Aug 2020 11:30:20 +0800 Subject: [PATCH 126/356] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../APM/APMMonitor/SLSystemAppInfo.h | 2 +- .../APM/APMMonitor/SLSystemAppInfo.m | 174 ++++++++++++------ .../WorkIssues/APM/SLAPMViewController.m | 2 - 3 files changed, 123 insertions(+), 55 deletions(-) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h index f77515e1..9bb7eeb6 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h @@ -10,7 +10,7 @@ typedef NS_ENUM(NSInteger, SLAuthorizationStatus) { SLAuthorizationStatusUnknow = -1, //未知的 - SLAuthorizationStatusNotDetermined = 0, //用户还没有选择过(第一次) + SLAuthorizationStatusNotDetermined = 0, //用户还没有选择过(第一次) 这时会自动出现系统询问授权弹窗,之后不会 SLAuthorizationStatusRestricted, //家长控制,限制用户授权的权限 SLAuthorizationStatusDenied, //用户拒绝授权 SLAuthorizationStatusAuthorized, //已授权 diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m index 83caa70e..2094a5b6 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m @@ -52,10 +52,10 @@ + (void)test { [self appName]; [self checkPushAuthorization]; - [self checkPhotoLibraryAuthorization]; + [self checkPhotoLibraryAuthorization:nil]; [self checkLocationAuthorization]; - [self checkCameraAuthorization]; - [self checkMicrophoneAuthorization]; + [self checkCameraAuthorization:nil]; + [self checkMicrophoneAuthorization:nil]; } @@ -299,9 +299,10 @@ + (NSString *)appBuild { } #pragma mark - 隐私权限 +/*资料:https://www.jianshu.com/p/5f05bc8395f1 */ ///检测推送通知权限 -+ (SLAuthorizationStatus)checkPushAuthorization{ ++ (SLAuthorizationStatus)checkPushAuthorization { __block SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0 if ([[UIApplication sharedApplication] currentUserNotificationSettings].types == UIUserNotificationTypeNone) { @@ -340,16 +341,31 @@ + (SLAuthorizationStatus)checkPushAuthorization{ return authorizationStatus; } -///检查相册访问权限 -+ (SLAuthorizationStatus)checkPhotoLibraryAuthorization { - SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; +///检查相册访问权限 handler 用户授权结果的回调 ++ (SLAuthorizationStatus)checkPhotoLibraryAuthorization:(void(^)(SLAuthorizationStatus status))handler { + __block SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0 //iOS 8.0以下使用AssetsLibrary.framework ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus]; authorizationStatus = (SLAuthorizationStatus)status; #else //iOS 8.0以上使用Photos.framework PHAuthorizationStatus current = [PHPhotoLibrary authorizationStatus]; authorizationStatus = (SLAuthorizationStatus)current; + //用户还没有做出过是否授权的选择时 + if (current == PHAuthorizationStatusNotDetermined) { + //只有第一次请求授权时才会自动出现系统弹窗,之后再请求授权时也不会弹出系统询问弹窗 + [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) { + dispatch_async(dispatch_get_main_queue(), ^{ + if (handler) { + authorizationStatus = (SLAuthorizationStatus)status; + handler(authorizationStatus); + } + }); + }]; + } #endif + if (handler) { + handler(authorizationStatus); + } return authorizationStatus; } @@ -378,49 +394,134 @@ + (SLAuthorizationStatus)checkLocationAuthorization { } ///检查相机/摄像头权限 -+ (SLAuthorizationStatus)checkCameraAuthorization { - SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; ++ (SLAuthorizationStatus)checkCameraAuthorization:(void(^)(SLAuthorizationStatus status))handler { + __block SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; NSString *mediaType = AVMediaTypeVideo;//读取媒体类型 AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType];//读取设备授权状态 authorizationStatus = (SLAuthorizationStatus)authStatus; + if (authStatus == AVAuthorizationStatusNotDetermined) { + [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) { + if (granted) { + authorizationStatus = SLAuthorizationStatusAuthorized; + }else{ + authorizationStatus = SLAuthorizationStatusDenied; + } + if (handler) { + handler(authorizationStatus); + } + }]; + } + if (handler) { + handler(authorizationStatus); + } return authorizationStatus; } ///检查话筒/麦克风权限 -+ (SLAuthorizationStatus)checkMicrophoneAuthorization { - SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; ++ (SLAuthorizationStatus)checkMicrophoneAuthorization:(void(^)(SLAuthorizationStatus status))handler { + __block SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; NSString *mediaType = AVMediaTypeAudio;//读取媒体类型 AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType];//读取设备授权状态 authorizationStatus = (SLAuthorizationStatus)authStatus; + if (authStatus == AVAuthorizationStatusNotDetermined) { + [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) { + if (granted) { + authorizationStatus = SLAuthorizationStatusAuthorized; + } else { + authorizationStatus = SLAuthorizationStatusDenied; + } + if (handler) { + handler(authorizationStatus); + } + }]; + } + if (handler) { + handler(authorizationStatus); + } return authorizationStatus; } ///检测通讯录权限 -+ (SLAuthorizationStatus)checkContactsAuthorization{ - SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; ++ (SLAuthorizationStatus)checkContactsAuthorization:(void(^)(SLAuthorizationStatus status))handler { + __block SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; if (@available(iOS 9.0, *)) {//iOS9.0之后 CNAuthorizationStatus authStatus = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts]; authorizationStatus = (SLAuthorizationStatus)authStatus; + if (authStatus == CNAuthorizationStatusNotDetermined) { + CNContactStore *contactStore = [[CNContactStore alloc] init]; + [contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError *error) { + if (!error){ + if (granted) { + authorizationStatus = SLAuthorizationStatusAuthorized; + } else { + authorizationStatus = SLAuthorizationStatusDenied; + } + if (handler) { + handler(authorizationStatus); + } + } + + }]; + } }else{//iOS9.0之前 ABAuthorizationStatus authorStatus = ABAddressBookGetAuthorizationStatus(); authorizationStatus = (SLAuthorizationStatus)authorStatus; } + if (handler) { + handler(authorizationStatus); + } return authorizationStatus; } ///检测日历权限 -+ (SLAuthorizationStatus)checkCalendarAuthorization { - SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; ++ (SLAuthorizationStatus)checkCalendarAuthorization:(void(^)(SLAuthorizationStatus status))handler { + __block SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; EKAuthorizationStatus status = [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent]; authorizationStatus = (SLAuthorizationStatus)status; + if (status == EKAuthorizationStatusNotDetermined) { + EKEventStore *store = [[EKEventStore alloc] init]; + [store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) { + if (error) {} else { + if (granted) { + authorizationStatus = SLAuthorizationStatusAuthorized; + } else { + authorizationStatus = SLAuthorizationStatusDenied; + } + if (handler) { + handler(authorizationStatus); + } + } + }]; + } + if (handler) { + handler(authorizationStatus); + } return authorizationStatus; } ///检测提醒事项权限 -+ (SLAuthorizationStatus)checkRemindAuthorization { - SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; ++ (SLAuthorizationStatus)checkRemindAuthorization:(void(^)(SLAuthorizationStatus status))handler { + __block SLAuthorizationStatus authorizationStatus = SLAuthorizationStatusUnknow; EKAuthorizationStatus status = [EKEventStore authorizationStatusForEntityType:EKEntityTypeReminder]; authorizationStatus = (SLAuthorizationStatus)status; + if (status == EKAuthorizationStatusNotDetermined) { + EKEventStore *store = [[EKEventStore alloc] init]; + [store requestAccessToEntityType:EKEntityTypeReminder completion:^(BOOL granted, NSError * _Nullable error) { + if (!error){ + if (granted) { + authorizationStatus = SLAuthorizationStatusAuthorized; + } else { + authorizationStatus = SLAuthorizationStatusDenied; + } + if (handler) { + handler(authorizationStatus); + } + } + }]; + } + if (handler) { + handler(authorizationStatus); + } return authorizationStatus; } @@ -472,15 +573,14 @@ + (void)checkFaceIDAuthorization { if (authenticationContext.biometryType == LABiometryTypeFaceID) { //验证当前人脸数据 [authenticationContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:@"开始验证" reply:^(BOOL success, NSError * _Nullable error) { - if (error) { - } else { + if (!error) { if (success) { - + //验证通过 + }else { + //验证失败 } } }]; - } else { - } }else { if (error.code == -8) { @@ -495,34 +595,4 @@ + (void)checkFaceIDAuthorization { } - - -///请求相册权限 -+ (void)requestAuthorizationLibrary { - ///相册授权状态 - PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus]; - if (status == PHAuthorizationStatusNotDetermined) { - // 用户还没有做出过是否授权的选择 - // 只有第一次请求授权时才会自动出现系统弹窗,之后再请求授权时也不会弹出系统询问弹窗 - [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) { - dispatch_async(dispatch_get_main_queue(), ^{ - if (status == PHAuthorizationStatusAuthorized) { - // 用户第一次同意了访问相册权限 - NSLog(@"用户同意授权"); - }else if (status == PHAuthorizationStatusDenied){ - NSLog(@"用户拒绝授权"); - } - }); - }]; - NSLog(@"用户还没有过选择"); - }else if (status == PHAuthorizationStatusRestricted) { - NSLog(@"用户无法授予此类权限,比如家长控制"); - }else if (status == PHAuthorizationStatusDenied) { - NSLog(@"用户已拒绝授权"); - }else if (status == PHAuthorizationStatusAuthorized) { - NSLog(@"用户已同意授权"); - } -} - - @end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m index a58e1be2..0478ea16 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/SLAPMViewController.m @@ -31,8 +31,6 @@ - (void)viewDidLoad { [self setupNavigationBar]; [SLAPMManager manager].type = SLAPMTypeNetwork; -// [SLSystemAppInfo test]; - } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; From 7c7db0f9debba2ea6c25ed3936b897438b45a828 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 7 Aug 2020 18:21:19 +0800 Subject: [PATCH 127/356] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../APM/APMMonitor/SLSystemAppInfo.h | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h index 9bb7eeb6..83334dca 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h @@ -27,9 +27,41 @@ NS_ASSUME_NONNULL_BEGIN @interface SLSystemAppInfo : NSObject + (instancetype)manager; ++ (void)test; +#pragma mark - System Info +///获取手机型号 iPhone 8... ++ (NSString *)iphoneType; +///获取手机系统版本 13.4 ++ (NSString *)systemVersion; +///获取设备类型 iPhone/iPad/iPod touch ++ (NSString *)deviceModel; +///根据地区语言返回设备类型字符串 (国际化区域名称) ++(NSString *)localDeviceModel; +///操作系统名称 iOS ++ (NSString *)systemName; +///获取用户手机别名 用户定义的名称 通用-关于本机-名称 wsl的iphone ++ (NSString *)userPhoneName; +///设备唯一标识的字母数字字符串 C5668446-C443-4898-A213-209AECE3626C ++ (NSString *)uuidString; +///是否是iPhoneX系列/刘海屏 ++ (BOOL)isIPhoneXSeries; +/// 获取电话运营商信息 ++ (NSString *)telephonyInfo; +/// 获取网络类型 ++(NSString*)networkType; +///获取设备当前网络IP地址 ++ (NSString *)getIPAddress:(BOOL)preferIPv4; -+ (void)test; +#pragma mark - App Info +///获取APP名字 SLTips ++ (NSString *)appName; +///获取APP bundle id com.wsl2ls.tips ++ (NSString *)appBundleId; +///获取当前App版本号 1.1.0 ++ (NSString *)appVersion; +///获取当前App编译版本号 1 ++ (NSString *)appBuild; @end From 7ce7dac00a3b1640ba2da0abcf8745c9b6f6bf4f Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 7 Aug 2020 19:05:29 +0800 Subject: [PATCH 128/356] =?UTF-8?q?=E5=BC=82=E6=AD=A5=E7=BA=BF=E7=A8=8B?= =?UTF-8?q?=E5=88=B7=E6=96=B0UI=E9=98=B2=E6=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 6 ++ .../Crash/SLCrashProtector/SLCrashHandler.h | 2 + .../SLCrashProtector/UIView+SLAsynUpdateUI.h | 18 ++++++ .../SLCrashProtector/UIView+SLAsynUpdateUI.m | 64 +++++++++++++++++++ .../DarkMode/Crash/SLCrashViewController.m | 27 ++++++-- 5 files changed, 111 insertions(+), 6 deletions(-) create mode 100644 iOS_Tips/DarkMode/Crash/SLCrashProtector/UIView+SLAsynUpdateUI.h create mode 100644 iOS_Tips/DarkMode/Crash/SLCrashProtector/UIView+SLAsynUpdateUI.m diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 2c6bc32e..4ea4e2bd 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ 7811F7AD24B32A1E000AA044 /* Write Link Map File.png in Resources */ = {isa = PBXBuildFile; fileRef = 7811F7AA24B32A1E000AA044 /* Write Link Map File.png */; }; 7811F7AE24B32A1E000AA044 /* Other c Flags.png in Resources */ = {isa = PBXBuildFile; fileRef = 7811F7AB24B32A1E000AA044 /* Other c Flags.png */; }; 7811F7AF24B32A1E000AA044 /* Order File.png in Resources */ = {isa = PBXBuildFile; fileRef = 7811F7AC24B32A1E000AA044 /* Order File.png */; }; + 781D9D0624DD662E00FAE73D /* UIView+SLAsynUpdateUI.m in Sources */ = {isa = PBXBuildFile; fileRef = 781D9D0524DD662E00FAE73D /* UIView+SLAsynUpdateUI.m */; }; 7822CCF8235B054200E70C29 /* SLPaddingLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 7822CCF7235B054200E70C29 /* SLPaddingLabel.m */; }; 782CFB1D239DDE95001B5528 /* SLSplitScreenViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 782CFB1C239DDE95001B5528 /* SLSplitScreenViewController.m */; }; 782CFB20239DEA05001B5528 /* SLSplitScreenCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 782CFB1F239DEA05001B5528 /* SLSplitScreenCell.m */; }; @@ -212,6 +213,8 @@ 7811F7AA24B32A1E000AA044 /* Write Link Map File.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Write Link Map File.png"; sourceTree = ""; }; 7811F7AB24B32A1E000AA044 /* Other c Flags.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Other c Flags.png"; sourceTree = ""; }; 7811F7AC24B32A1E000AA044 /* Order File.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Order File.png"; sourceTree = ""; }; + 781D9D0424DD662E00FAE73D /* UIView+SLAsynUpdateUI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIView+SLAsynUpdateUI.h"; sourceTree = ""; }; + 781D9D0524DD662E00FAE73D /* UIView+SLAsynUpdateUI.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIView+SLAsynUpdateUI.m"; sourceTree = ""; }; 7822CCF6235B054200E70C29 /* SLPaddingLabel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLPaddingLabel.h; sourceTree = ""; }; 7822CCF7235B054200E70C29 /* SLPaddingLabel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLPaddingLabel.m; sourceTree = ""; }; 782CFB1B239DDE95001B5528 /* SLSplitScreenViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLSplitScreenViewController.h; sourceTree = ""; }; @@ -712,6 +715,8 @@ 787C7DBA245D74E4005DF7ED /* NSMutableString+SLCrashProtector.m */, 7862533724599D420017F8F1 /* NSObject+SLCrashProtector.h */, 7862532C24599D420017F8F1 /* NSObject+SLCrashProtector.m */, + 781D9D0424DD662E00FAE73D /* UIView+SLAsynUpdateUI.h */, + 781D9D0524DD662E00FAE73D /* UIView+SLAsynUpdateUI.m */, 7862532F24599D420017F8F1 /* SLKVODelegate.h */, 7862533A24599D420017F8F1 /* SLKVODelegate.m */, 787C7DC4245D77D8005DF7ED /* SLZombieCatcher.h */, @@ -1519,6 +1524,7 @@ 787C7DCC2462ADE5005DF7ED /* NSObject+SLMLeakFinder.m in Sources */, 78E72D792480B36800751373 /* SLScrollViewController.m in Sources */, 782CFB20239DEA05001B5528 /* SLSplitScreenCell.m in Sources */, + 781D9D0624DD662E00FAE73D /* UIView+SLAsynUpdateUI.m in Sources */, 7830A59E2358520200BC79BA /* SLEditTextView.m in Sources */, 7860D78E2398D34E008C53EC /* SLMixColorTextureVC.m in Sources */, 78E72D7F24810ECC00751373 /* UIScrollView+SLCommon.m in Sources */, diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h index 75ac952a..55e5c6ad 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h @@ -31,6 +31,8 @@ typedef NS_ENUM(NSInteger, SLCrashErrorType) { SLCrashErrorTypeKVO, /*KVC异常*/ SLCrashErrorTypeKVC, + /*异步线程更新UI*/ + SLCrashErrorTypeAsynUpdateUI, /*野指针*/ SLCrashErrorTypeZombie, /*内存泄漏/循环引用*/ diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/UIView+SLAsynUpdateUI.h b/iOS_Tips/DarkMode/Crash/SLCrashProtector/UIView+SLAsynUpdateUI.h new file mode 100644 index 00000000..64d866bc --- /dev/null +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/UIView+SLAsynUpdateUI.h @@ -0,0 +1,18 @@ +// +// UIView+SLAsynUpdateUI.h +// DarkMode +// +// Created by wsl on 2020/8/7. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +///异步更新UI 防护 +@interface UIView (SLAsynUpdateUI) + +@end + +NS_ASSUME_NONNULL_END diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/UIView+SLAsynUpdateUI.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/UIView+SLAsynUpdateUI.m new file mode 100644 index 00000000..207dc33d --- /dev/null +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/UIView+SLAsynUpdateUI.m @@ -0,0 +1,64 @@ +// +// UIView+SLAsynUpdateUI.m +// DarkMode +// +// Created by wsl on 2020/8/7. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "UIView+SLAsynUpdateUI.h" +#import "SLCrashProtector.h" + +@implementation UIView (SLAsynUpdateUI) + ++ (void)load { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + SL_ExchangeInstanceMethod([UIView class], @selector(setNeedsLayout), [UIView class], @selector(sl_setNeedsLayout)); + SL_ExchangeInstanceMethod([UIView class], @selector(setNeedsDisplay), [UIView class], @selector(sl_setNeedsDisplay)); + SL_ExchangeInstanceMethod([UIView class], @selector(setNeedsDisplayInRect:), [UIView class], @selector(sl_setNeedsDisplayInRect:)); + }); +} + +- (void)sl_setNeedsLayout{ + if ([self isAsynUpdateUI]) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self sl_setNeedsLayout]; + }); + }else { + [self sl_setNeedsLayout]; + } +} +- (void)sl_setNeedsDisplay{ + if ([self isAsynUpdateUI]) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self sl_setNeedsDisplay]; + }); + }else { + [self sl_setNeedsDisplay]; + } + +} +- (void)sl_setNeedsDisplayInRect:(CGRect)rect{ + if ([self isAsynUpdateUI]) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self sl_setNeedsDisplayInRect:rect]; + }); + }else { + [self sl_setNeedsDisplayInRect:rect]; + } + +} + +- (BOOL)isAsynUpdateUI{ + if(![NSThread isMainThread]){ + NSString *reason = [NSString stringWithFormat:@"异常:异步线程刷新UI"]; + SLCrashError *crashError = [SLCrashError errorWithErrorType:SLCrashErrorTypeAsynUpdateUI errorDesc:reason exception:nil callStack:[NSThread callStackSymbols]]; + [[SLCrashHandler defaultCrashHandler].delegate crashHandlerDidOutputCrashError:crashError]; + return YES; + } + return NO; +} + + +@end diff --git a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m index 658dfe2b..ae3a0214 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m @@ -55,9 +55,9 @@ - (void)setupUI { @"testUnrecognizedSelector", @"testKVO", @"testKVC", + @"testAsynUpdateUI", @"testWildPointer", - @"testMemoryLeak", - @"testCallStack"]; + @"testMemoryLeak"]; NSArray *titles = @[@"数组越界、空值", @"可变数组越界、空值", @"字典越界、空值", @@ -67,9 +67,9 @@ - (void)setupUI { @"未实现方法", @"KVO", @"KVC", + @"异步刷新UI", @"野指针", - @"内存泄漏/循环引用", - @"回调栈"]; + @"内存泄漏/循环引用"]; CGSize size = CGSizeMake(self.view.sl_width/4.0, 66); int i = 0; for (NSString *method in methods) { @@ -97,7 +97,7 @@ - (void)setupUI { ///异常捕获回调 提供给外界实现自定义处理 ,日志上报等(注意线程安全) - (void)crashHandlerDidOutputCrashError:(SLCrashError *)crashError { NSString *errorInfo = [NSString stringWithFormat:@" 错误描述:%@ \n 调用栈:%@" ,crashError.errorDesc, crashError.callStackSymbol]; - + SL_DISPATCH_ON_MAIN_THREAD((^{ [self.textView scrollsToTop]; self.textView.text = errorInfo; @@ -242,6 +242,21 @@ - (void)testKVC { [self setValue:@"wsl" forKeyPath:@"self.noProperty"]; } +#pragma mark - 异步刷新UI +///异步刷新UI +- (void)testAsynUpdateUI { + dispatch_async(dispatch_get_global_queue(0, 0), ^{ + UILabel* newView = [[UILabel alloc] initWithFrame:CGRectMake(0,0,150, 88)]; + newView.center = CGPointMake(self.view.sl_width/2.0, self.view.sl_height/2.0); + newView.backgroundColor = [UIColor greenColor]; + newView.text = @"异步刷新UI"; + [self.view addSubview:newView]; + [SLDelayPerform sl_startDelayPerform:^{ + [newView removeFromSuperview]; + } afterDelay:2.0]; + }); +} + #pragma mark - 野指针 ///野指针 随机性太强,不方便复现和定位问题,我们需要做的就是把随机变为必现,并且定位到对应的代码,方便查找解决 ///思路来源: https://www.jianshu.com/p/9fd4dc046046?utm_source=oschina-app @@ -286,7 +301,7 @@ - (void)testMemoryLeak { // self.testMArray = [[NSMutableArray alloc] initWithObjects:self, nil]; } -#pragma mark - 函数调用栈 +#pragma mark - 获取函数调用栈 ///获取任意线程的函数调用栈 https://toutiao.io/posts/aveig6/preview - (void)testCallStack { //打印当前线程调用栈 From 9ec3aa56fd984b37444bbe96e5c69fd2a62cbbf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Fri, 7 Aug 2020 19:06:15 +0800 Subject: [PATCH 129/356] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index eaffd9f2..635e8b20 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ ## 7-iOSCrash防护 -> Crash防护内容涉及 NSArray/NSMutableArray、NSDictionary/NSMutableDictionary、NSString/NSMutableString、Unrecognized Selector、KVO、KVC 、野指针定位、内存泄漏/循环引用;主要是对常见易错的地方进行容错处理,避免崩溃,并保存出错时的函数调用栈,以方便快速定位代码,主要是利用的runtime和fishook知识。 +> Crash防护内容涉及 NSArray/NSMutableArray、NSDictionary/NSMutableDictionary、NSString/NSMutableString、Unrecognized Selector、KVO、KVC 、异步线程刷新UI、野指针定位、内存泄漏/循环引用;主要是对常见易错的地方进行容错处理,避免崩溃,并保存出错时的函数调用栈,以方便快速定位代码,主要是利用的runtime和fishook知识。 ![iOSCrash防护](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/iOSCrash防护.gif) From 1fd2098f399d35b2cdb68f16918e330263d900bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Sat, 8 Aug 2020 13:55:09 +0800 Subject: [PATCH 130/356] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 635e8b20..2e856cf8 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,9 @@ >> 8.5、UIScrollView实现原理 >> 8.6、UITableView的实现原理 -> [结尾](#结尾) +> [高质量技术博客集合](iOS_Tips/DarkMode/WorkIssues/高质量技术博客.md) +> [结尾](#结尾) + ## 1-暗黑模式适配 From 4616a9a95fba08fb43b65172d7dd0ea08a9c8fb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Sat, 8 Aug 2020 13:55:48 +0800 Subject: [PATCH 131/356] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2e856cf8..898a169d 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ >> 8.5、UIScrollView实现原理 >> 8.6、UITableView的实现原理 -> [高质量技术博客集合](iOS_Tips/DarkMode/WorkIssues/高质量技术博客.md) +> [高质量技术博客集合](iOS_Tips/DarkMode/WorkIssues/高质量技术博客.md) > [结尾](#结尾) From 32dd2df433a5d1d4956e9e13092661b9a4d4dbf4 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sat, 8 Aug 2020 17:39:13 +0800 Subject: [PATCH 132/356] =?UTF-8?q?=E5=AD=A6=E4=B9=A0=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 2 + .../WorkIssues/\347\254\224\350\256\260.md" | 77 ++++++++++++------- ...00\346\234\257\345\215\232\345\256\242.md" | 1 + 3 files changed, 54 insertions(+), 26 deletions(-) diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 4ea4e2bd..60b851b2 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -1706,6 +1706,7 @@ FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/DarkMode/General/SLAnimateImageView", + "$(PROJECT_DIR)/DarkMode/WorkIssues/APM/APMMonitor", ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "$(SRCROOT)/DarkMode/General/Tool/PrefixHeader.pch"; @@ -1737,6 +1738,7 @@ FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/DarkMode/General/SLAnimateImageView", + "$(PROJECT_DIR)/DarkMode/WorkIssues/APM/APMMonitor", ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "$(SRCROOT)/DarkMode/General/Tool/PrefixHeader.pch"; diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index f7f32206..0ae669f7 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -1,27 +1,52 @@ - 一、APM/性能监控 - 1. [iOS-Monitor-Platform](https://github.com/aozhimin/iOS-Monitor-Platform) + + ## 一、性能优化 - 二、[性能优化](https://github.com/skyming/iOS-Performance-Optimization) -1. 优化业务流程 -2. 合理的线程分配 -3. 预处理、延时加载、按需加载 -4. 三级缓存 -5. 使用正确的API -6. 启动连续闪退保护 -7. Crash防护 -8. APM监控 - -三、程序员的自我修养 - 编译、链接、装载 -1. [趣探 Mach-O](https://juejin.im/post/5a0c5c5e51882555cc416602) -2. [iOS程序员的自我修养](https://juejin.im/post/5d5273b1f265da03f233c2d6) - -四、数据结构与算法 -1. [LeetcodeTop](https://github.com/afatcoder/LeetcodeTop) - -五、面试题相关 -1. [iOS-InterviewQuestion-collection](https://github.com/liberalisman/iOS-InterviewQuestion-collection) -2. [阿里、字节 一套高效的iOS面试题解答](https://github.com/colourful987/bytedance-alibaba-interview) -3. [2019年iOS面试反思总结](https://juejin.im/post/6844903942644563982) -4. [IOS面试考察(九):性能优化相关问题](https://juejin.im/post/6844904131941892110#heading-50) -5. [Theendisthebegi ](https://www.jianshu.com/u/b836babfef41) -6. [analyze](https://github.com/draveness/analyze) +* 1.0、APM性能监控 + +> CPU占用率、内存/磁盘使用率、卡顿监控定位、Crash防护、线程数量监控、网络监控(TCP 建立连接时间 、DNS 时间、 SSL时间、首包时间、响应时间 、流量)、ViewController启动耗时监测 、load方法耗时、函数耗时...... + +* 1.1、内存优化 + +> 合理的线程分配、使用正确的API、延时加载、按需加载/复用、处理内存警告、自动释放池、 + +* 1.2、卡顿优化 + +> 优化业务流程、 预处理、 三级缓存 + +* 1.3、 安装包瘦身 + +* 1.4、启动时间优化 + +* 1.5、编译时间优化 + +* 1.6、网络优化 + +* 1.7、健壮性/稳定性 + +> 启动连续闪退保护、Crash防护 + +* 1.7、安全性 + +* 资料 +> [iOS-Performance-Optimization](https://github.com/skyming/iOS-Performance-Optimization) +> [DoraemonKit](https://github.com/didi/DoraemonKit/blob/master/README_CN.md) +> [乐少](https://www.jianshu.com/u/9c51a213b02e) + + +## 二、数据结构与算法 +1、 [LeetcodeTop](https://github.com/afatcoder/LeetcodeTop) + +## 三、面试题相关 +1、[iOS-InterviewQuestion-collection](https://github.com/liberalisman/iOS-InterviewQuestion-collection) +2、[阿里、字节 一套高效的iOS面试题解答](https://github.com/colourful987/bytedance-alibaba-interview) +3、[2019年iOS面试反思总结](https://juejin.im/post/6844903942644563982) +4、[IOS面试考察(九):性能优化相关问题](https://juejin.im/post/6844904131941892110#heading-50) +5、[Theendisthebegi ](https://www.jianshu.com/u/b836babfef41) +6、[analyze](https://github.com/draveness/analyze) + +## 四、逆向与安全 +1、 [趣探 Mach-O](https://juejin.im/post/5a0c5c5e51882555cc416602) +2、 [iOS程序员的自我修养 - 编译、链接、装载](https://juejin.im/post/5d5273b1f265da03f233c2d6) + + +## 五、音视频 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 6942c060..8a77fe82 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -35,6 +35,7 @@ * 33、[景铭巴巴](https://www.jianshu.com/u/c3c893a27097) * 34、[punmy](https://punmy.cn/) * 35、[LearnOpengl](https://learnopengl-cn.github.io) +* 36、[everettjf](https://everettjf.github.io/) ## 高质量微信公众号 From 334f4c99e3527ad11519ae49e756e5c8abc0c142 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sun, 9 Aug 2020 16:13:54 +0800 Subject: [PATCH 133/356] =?UTF-8?q?APM=20=20=E4=B9=8Bload=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E8=80=97=E6=97=B6=E7=9B=91=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 6 ++ .../WorkIssues/APM/APMMonitor/SLAPMLoadTime.h | 14 +++ .../WorkIssues/APM/APMMonitor/SLAPMLoadTime.m | 98 +++++++++++++++++++ .../WorkIssues/\347\254\224\350\256\260.md" | 2 + 4 files changed, 120 insertions(+) create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.h create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.m diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 60b851b2..f96721e5 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 7811F7AE24B32A1E000AA044 /* Other c Flags.png in Resources */ = {isa = PBXBuildFile; fileRef = 7811F7AB24B32A1E000AA044 /* Other c Flags.png */; }; 7811F7AF24B32A1E000AA044 /* Order File.png in Resources */ = {isa = PBXBuildFile; fileRef = 7811F7AC24B32A1E000AA044 /* Order File.png */; }; 781D9D0624DD662E00FAE73D /* UIView+SLAsynUpdateUI.m in Sources */ = {isa = PBXBuildFile; fileRef = 781D9D0524DD662E00FAE73D /* UIView+SLAsynUpdateUI.m */; }; + 781DA28B24DFD52500FAE73D /* SLAPMLoadTime.m in Sources */ = {isa = PBXBuildFile; fileRef = 781DA28924DFD52400FAE73D /* SLAPMLoadTime.m */; }; 7822CCF8235B054200E70C29 /* SLPaddingLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 7822CCF7235B054200E70C29 /* SLPaddingLabel.m */; }; 782CFB1D239DDE95001B5528 /* SLSplitScreenViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 782CFB1C239DDE95001B5528 /* SLSplitScreenViewController.m */; }; 782CFB20239DEA05001B5528 /* SLSplitScreenCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 782CFB1F239DEA05001B5528 /* SLSplitScreenCell.m */; }; @@ -215,6 +216,8 @@ 7811F7AC24B32A1E000AA044 /* Order File.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Order File.png"; sourceTree = ""; }; 781D9D0424DD662E00FAE73D /* UIView+SLAsynUpdateUI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIView+SLAsynUpdateUI.h"; sourceTree = ""; }; 781D9D0524DD662E00FAE73D /* UIView+SLAsynUpdateUI.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIView+SLAsynUpdateUI.m"; sourceTree = ""; }; + 781DA28924DFD52400FAE73D /* SLAPMLoadTime.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLAPMLoadTime.m; sourceTree = ""; }; + 781DA28A24DFD52500FAE73D /* SLAPMLoadTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLAPMLoadTime.h; sourceTree = ""; }; 7822CCF6235B054200E70C29 /* SLPaddingLabel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLPaddingLabel.h; sourceTree = ""; }; 7822CCF7235B054200E70C29 /* SLPaddingLabel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLPaddingLabel.m; sourceTree = ""; }; 782CFB1B239DDE95001B5528 /* SLSplitScreenViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLSplitScreenViewController.h; sourceTree = ""; }; @@ -918,6 +921,8 @@ 789AD1C724D7FA5F00CB0B4C /* SLAPMURLProtocol.m */, 789AD1D024D9622B00CB0B4C /* UIViewController+SLAPMVCTime.h */, 789AD1D124D9622B00CB0B4C /* UIViewController+SLAPMVCTime.m */, + 781DA28A24DFD52500FAE73D /* SLAPMLoadTime.h */, + 781DA28924DFD52400FAE73D /* SLAPMLoadTime.m */, 789AD1D324D97F8500CB0B4C /* SLSystemAppInfo.h */, 789AD1D424D97F8500CB0B4C /* SLSystemAppInfo.m */, ); @@ -1415,6 +1420,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 781DA28B24DFD52500FAE73D /* SLAPMLoadTime.m in Sources */, 782CFB1D239DDE95001B5528 /* SLSplitScreenViewController.m in Sources */, 7857977823725C21004CD664 /* SLFaceDetectController.m in Sources */, 7835048524586BAC0071283E /* queue.c in Sources */, diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.h new file mode 100644 index 00000000..d34e3c57 --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.h @@ -0,0 +1,14 @@ +// +// SLAPMLoadTime.h +// DarkMode +// +// Created by wsl on 2020/8/4. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import + +///监测+load方法耗时 引自: https://www.jianshu.com/p/c14987eee107 +@interface SLAPMLoadTime : NSObject + +@end diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.m new file mode 100644 index 00000000..0d6c373e --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.m @@ -0,0 +1,98 @@ +// +// SLAPMLoadTime.m +// DarkMode +// +// Created by wsl on 2020/8/4. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLAPMLoadTime.h" +#import +#import +#import +#include +#include +#include +#include + + +#define TIMESTAMP_NUMBER(interval) [NSNumber numberWithLongLong:interval*1000*1000] + +unsigned int count; +const char **classes; + +static NSMutableArray *_loadInfoArray; + +@implementation SLAPMLoadTime ++ (void)load { + + _loadInfoArray = [[NSMutableArray alloc] init]; + + CFAbsoluteTime time1 =CFAbsoluteTimeGetCurrent(); + + int imageCount = (int)_dyld_image_count(); + + for(int iImg = 0; iImg < imageCount; iImg++) { + + const char* path = _dyld_get_image_name((unsigned)iImg); + NSString *imagePath = [NSString stringWithUTF8String:path]; + + NSBundle* mainBundle = [NSBundle mainBundle]; + NSString* bundlePath = [mainBundle bundlePath]; + + if ([imagePath containsString:bundlePath] && ![imagePath containsString:@".dylib"]) { + classes = objc_copyClassNamesForImage(path, &count); + + for (int i = 0; i < count; i++) { + NSString *className = [NSString stringWithCString:classes[i] encoding:NSUTF8StringEncoding]; + if (![className isEqualToString:@""] && className) { + Class class = object_getClass(NSClassFromString(className)); + + SEL originalSelector = @selector(load); + SEL swizzledSelector = @selector(LDAPM_Load); + + Method originalMethod = class_getClassMethod(class, originalSelector); + Method swizzledMethod = class_getClassMethod([SLAPMLoadTime class], swizzledSelector); + + BOOL hasMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); + + if (!hasMethod) { + BOOL didAddMethod = class_addMethod(class, + swizzledSelector, + method_getImplementation(swizzledMethod), + method_getTypeEncoding(swizzledMethod)); + + if (didAddMethod) { + swizzledMethod = class_getClassMethod(class, swizzledSelector); + + method_exchangeImplementations(originalMethod, swizzledMethod); + } + } + + } + } + } + } + + CFAbsoluteTime time2 =CFAbsoluteTimeGetCurrent(); + + NSLog(@"Hook Time:%f",(time2 - time1) * 1000); +} + ++ (void)LDAPM_Load { + + CFAbsoluteTime start =CFAbsoluteTimeGetCurrent(); + + [self LDAPM_Load]; + + CFAbsoluteTime end =CFAbsoluteTimeGetCurrent(); + // 时间精度 us + NSDictionary *infoDic = @{@"st":TIMESTAMP_NUMBER(start), + @"et":TIMESTAMP_NUMBER(end), + @"name":NSStringFromClass([self class]) + }; + + [_loadInfoArray addObject:infoDic]; +} + +@end diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 0ae669f7..9dae6313 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -17,6 +17,8 @@ * 1.4、启动时间优化 +> 合并动态库、二进制重排、异步延时加载、load 的方法处理 + * 1.5、编译时间优化 * 1.6、网络优化 From 0727b5ba45b4510706168c2e6767fe19ee6e2fc4 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sun, 9 Aug 2020 19:08:59 +0800 Subject: [PATCH 134/356] =?UTF-8?q?APM=20=E4=B9=8B=20=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E8=80=97=E6=97=B6=E7=9B=91=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 6 + .../APM/APMMonitor/QiCallTraceCore.c | 464 ++++++++++++++++++ .../APM/APMMonitor/QiCallTraceCore.h | 36 ++ .../WorkIssues/\347\254\224\350\256\260.md" | 5 +- 4 files changed, 510 insertions(+), 1 deletion(-) create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/QiCallTraceCore.c create mode 100644 iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/QiCallTraceCore.h diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index f96721e5..5d5ddb84 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ 7811F7AF24B32A1E000AA044 /* Order File.png in Resources */ = {isa = PBXBuildFile; fileRef = 7811F7AC24B32A1E000AA044 /* Order File.png */; }; 781D9D0624DD662E00FAE73D /* UIView+SLAsynUpdateUI.m in Sources */ = {isa = PBXBuildFile; fileRef = 781D9D0524DD662E00FAE73D /* UIView+SLAsynUpdateUI.m */; }; 781DA28B24DFD52500FAE73D /* SLAPMLoadTime.m in Sources */ = {isa = PBXBuildFile; fileRef = 781DA28924DFD52400FAE73D /* SLAPMLoadTime.m */; }; + 781DA28E24E00F9E00FAE73D /* QiCallTraceCore.c in Sources */ = {isa = PBXBuildFile; fileRef = 781DA28C24E00F9E00FAE73D /* QiCallTraceCore.c */; }; 7822CCF8235B054200E70C29 /* SLPaddingLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 7822CCF7235B054200E70C29 /* SLPaddingLabel.m */; }; 782CFB1D239DDE95001B5528 /* SLSplitScreenViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 782CFB1C239DDE95001B5528 /* SLSplitScreenViewController.m */; }; 782CFB20239DEA05001B5528 /* SLSplitScreenCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 782CFB1F239DEA05001B5528 /* SLSplitScreenCell.m */; }; @@ -218,6 +219,8 @@ 781D9D0524DD662E00FAE73D /* UIView+SLAsynUpdateUI.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIView+SLAsynUpdateUI.m"; sourceTree = ""; }; 781DA28924DFD52400FAE73D /* SLAPMLoadTime.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLAPMLoadTime.m; sourceTree = ""; }; 781DA28A24DFD52500FAE73D /* SLAPMLoadTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLAPMLoadTime.h; sourceTree = ""; }; + 781DA28C24E00F9E00FAE73D /* QiCallTraceCore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = QiCallTraceCore.c; sourceTree = ""; }; + 781DA28D24E00F9E00FAE73D /* QiCallTraceCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QiCallTraceCore.h; sourceTree = ""; }; 7822CCF6235B054200E70C29 /* SLPaddingLabel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLPaddingLabel.h; sourceTree = ""; }; 7822CCF7235B054200E70C29 /* SLPaddingLabel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLPaddingLabel.m; sourceTree = ""; }; 782CFB1B239DDE95001B5528 /* SLSplitScreenViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLSplitScreenViewController.h; sourceTree = ""; }; @@ -923,6 +926,8 @@ 789AD1D124D9622B00CB0B4C /* UIViewController+SLAPMVCTime.m */, 781DA28A24DFD52500FAE73D /* SLAPMLoadTime.h */, 781DA28924DFD52400FAE73D /* SLAPMLoadTime.m */, + 781DA28C24E00F9E00FAE73D /* QiCallTraceCore.c */, + 781DA28D24E00F9E00FAE73D /* QiCallTraceCore.h */, 789AD1D324D97F8500CB0B4C /* SLSystemAppInfo.h */, 789AD1D424D97F8500CB0B4C /* SLSystemAppInfo.m */, ); @@ -1530,6 +1535,7 @@ 787C7DCC2462ADE5005DF7ED /* NSObject+SLMLeakFinder.m in Sources */, 78E72D792480B36800751373 /* SLScrollViewController.m in Sources */, 782CFB20239DEA05001B5528 /* SLSplitScreenCell.m in Sources */, + 781DA28E24E00F9E00FAE73D /* QiCallTraceCore.c in Sources */, 781D9D0624DD662E00FAE73D /* UIView+SLAsynUpdateUI.m in Sources */, 7830A59E2358520200BC79BA /* SLEditTextView.m in Sources */, 7860D78E2398D34E008C53EC /* SLMixColorTextureVC.m in Sources */, diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/QiCallTraceCore.c b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/QiCallTraceCore.c new file mode 100644 index 00000000..25c2660b --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/QiCallTraceCore.c @@ -0,0 +1,464 @@ +// +// QiCallTraceCore.c +// Qi_ObjcMsgHook +// +// Created by liusiqi on 2019/11/20. +// Copyright © 2019 QiShare. All rights reserved. +// + +#include "QiCallTraceCore.h" + +#ifdef __aarch64__ + +#pragma mark - fishhook +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * A structure representing a particular intended rebinding from a symbol + * name to its replacement + */ +struct rebinding { + const char *name; + void *replacement; + void **replaced; +}; + +/* + * For each rebinding in rebindings, rebinds references to external, indirect + * symbols with the specified name to instead point at replacement for each + * image in the calling process as well as for all future images that are loaded + * by the process. If rebind_functions is called more than once, the symbols to + * rebind are added to the existing list of rebindings, and if a given symbol + * is rebound more than once, the later rebinding will take precedence. + */ +static int fish_rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel); + + +#ifdef __LP64__ +typedef struct mach_header_64 mach_header_t; +typedef struct segment_command_64 segment_command_t; +typedef struct section_64 section_t; +typedef struct nlist_64 nlist_t; +#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT_64 +#else +typedef struct mach_header mach_header_t; +typedef struct segment_command segment_command_t; +typedef struct section section_t; +typedef struct nlist nlist_t; +#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT +#endif + +#ifndef SEG_DATA_CONST +#define SEG_DATA_CONST "__DATA_CONST" +#endif + +struct rebindings_entry { + struct rebinding *rebindings; + size_t rebindings_nel; + struct rebindings_entry *next; +}; + +static struct rebindings_entry *_rebindings_head; + +static int prepend_rebindings(struct rebindings_entry **rebindings_head, + struct rebinding rebindings[], + size_t nel) { + struct rebindings_entry *new_entry = malloc(sizeof(struct rebindings_entry)); + if (!new_entry) { + return -1; + } + new_entry->rebindings = malloc(sizeof(struct rebinding) * nel); + if (!new_entry->rebindings) { + free(new_entry); + return -1; + } + memcpy(new_entry->rebindings, rebindings, sizeof(struct rebinding) * nel); + new_entry->rebindings_nel = nel; + new_entry->next = *rebindings_head; + *rebindings_head = new_entry; + return 0; +} + +static void perform_rebinding_with_section(struct rebindings_entry *rebindings, + section_t *section, + intptr_t slide, + nlist_t *symtab, + char *strtab, + uint32_t *indirect_symtab) { + uint32_t *indirect_symbol_indices = indirect_symtab + section->reserved1; + void **indirect_symbol_bindings = (void **)((uintptr_t)slide + section->addr); + for (uint i = 0; i < section->size / sizeof(void *); i++) { + uint32_t symtab_index = indirect_symbol_indices[i]; + if (symtab_index == INDIRECT_SYMBOL_ABS || symtab_index == INDIRECT_SYMBOL_LOCAL || + symtab_index == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS)) { + continue; + } + uint32_t strtab_offset = symtab[symtab_index].n_un.n_strx; + char *symbol_name = strtab + strtab_offset; + if (strnlen(symbol_name, 2) < 2) { + continue; + } + struct rebindings_entry *cur = rebindings; + while (cur) { + for (uint j = 0; j < cur->rebindings_nel; j++) { + if (strcmp(&symbol_name[1], cur->rebindings[j].name) == 0) { + if (cur->rebindings[j].replaced != NULL && + indirect_symbol_bindings[i] != cur->rebindings[j].replacement) { + *(cur->rebindings[j].replaced) = indirect_symbol_bindings[i]; + } + indirect_symbol_bindings[i] = cur->rebindings[j].replacement; + goto symbol_loop; + } + } + cur = cur->next; + } + symbol_loop:; + } +} + +static void rebind_symbols_for_image(struct rebindings_entry *rebindings, + const struct mach_header *header, + intptr_t slide) { + Dl_info info; + if (dladdr(header, &info) == 0) { + return; + } + + segment_command_t *cur_seg_cmd; + segment_command_t *linkedit_segment = NULL; + struct symtab_command* symtab_cmd = NULL; + struct dysymtab_command* dysymtab_cmd = NULL; + + uintptr_t cur = (uintptr_t)header + sizeof(mach_header_t); + for (uint i = 0; i < header->ncmds; i++, cur += cur_seg_cmd->cmdsize) { + cur_seg_cmd = (segment_command_t *)cur; + if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { + if (strcmp(cur_seg_cmd->segname, SEG_LINKEDIT) == 0) { + linkedit_segment = cur_seg_cmd; + } + } else if (cur_seg_cmd->cmd == LC_SYMTAB) { + symtab_cmd = (struct symtab_command*)cur_seg_cmd; + } else if (cur_seg_cmd->cmd == LC_DYSYMTAB) { + dysymtab_cmd = (struct dysymtab_command*)cur_seg_cmd; + } + } + + if (!symtab_cmd || !dysymtab_cmd || !linkedit_segment || + !dysymtab_cmd->nindirectsyms) { + return; + } + + // Find base symbol/string table addresses + uintptr_t linkedit_base = (uintptr_t)slide + linkedit_segment->vmaddr - linkedit_segment->fileoff; + nlist_t *symtab = (nlist_t *)(linkedit_base + symtab_cmd->symoff); + char *strtab = (char *)(linkedit_base + symtab_cmd->stroff); + + // Get indirect symbol table (array of uint32_t indices into symbol table) + uint32_t *indirect_symtab = (uint32_t *)(linkedit_base + dysymtab_cmd->indirectsymoff); + + cur = (uintptr_t)header + sizeof(mach_header_t); + for (uint i = 0; i < header->ncmds; i++, cur += cur_seg_cmd->cmdsize) { + cur_seg_cmd = (segment_command_t *)cur; + if (cur_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) { + if (strcmp(cur_seg_cmd->segname, SEG_DATA) != 0 && + strcmp(cur_seg_cmd->segname, SEG_DATA_CONST) != 0) { + continue; + } + for (uint j = 0; j < cur_seg_cmd->nsects; j++) { + section_t *sect = + (section_t *)(cur + sizeof(segment_command_t)) + j; + if ((sect->flags & SECTION_TYPE) == S_LAZY_SYMBOL_POINTERS) { + perform_rebinding_with_section(rebindings, sect, slide, symtab, strtab, indirect_symtab); + } + if ((sect->flags & SECTION_TYPE) == S_NON_LAZY_SYMBOL_POINTERS) { + perform_rebinding_with_section(rebindings, sect, slide, symtab, strtab, indirect_symtab); + } + } + } + } +} + +static void _rebind_symbols_for_image(const struct mach_header *header, + intptr_t slide) { + rebind_symbols_for_image(_rebindings_head, header, slide); +} + +static int fish_rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel) { + int retval = prepend_rebindings(&_rebindings_head, rebindings, rebindings_nel); + if (retval < 0) { + return retval; + } + // If this was the first call, register callback for image additions (which is also invoked for + // existing images, otherwise, just run on existing images + //首先是遍历 dyld 里的所有的 image,取出 image header 和 slide。注意第一次调用时主要注册 callback + if (!_rebindings_head->next) { + _dyld_register_func_for_add_image(_rebind_symbols_for_image); + } else { + uint32_t c = _dyld_image_count(); + for (uint32_t i = 0; i < c; i++) { + _rebind_symbols_for_image(_dyld_get_image_header(i), _dyld_get_image_vmaddr_slide(i)); + } + } + return retval; +} + + +#pragma mark - Record + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static bool _call_record_enabled = true; +static uint64_t _min_time_cost = 1000; //us +static int _max_call_depth = 3; +static pthread_key_t _thread_key; +__unused static id (*orig_objc_msgSend)(id, SEL, ...); + +static qiCallRecord *_qiCallRecords; +//static int otp_record_num; +//static int otp_record_alloc; +static int _qiRecordNum; +static int _qiRecordAlloc; + +typedef struct { + id self; //通过 object_getClass 能够得到 Class 再通过 NSStringFromClass 能够得到类名 + Class cls; + SEL cmd; //通过 NSStringFromSelector 方法能够得到方法名 + uint64_t time; //us + uintptr_t lr; // link register +} thread_call_record; + +typedef struct { + thread_call_record *stack; + int allocated_length; + int index; + bool is_main_thread; +} thread_call_stack; + +static inline thread_call_stack * get_thread_call_stack() { + thread_call_stack *cs = (thread_call_stack *)pthread_getspecific(_thread_key); + if (cs == NULL) { + cs = (thread_call_stack *)malloc(sizeof(thread_call_stack)); + cs->stack = (thread_call_record *)calloc(128, sizeof(thread_call_record)); + cs->allocated_length = 64; + cs->index = -1; + cs->is_main_thread = pthread_main_np(); + pthread_setspecific(_thread_key, cs); + } + return cs; +} + +static void release_thread_call_stack(void *ptr) { + thread_call_stack *cs = (thread_call_stack *)ptr; + if (!cs) return; + if (cs->stack) free(cs->stack); + free(cs); +} + +static inline void push_call_record(id _self, Class _cls, SEL _cmd, uintptr_t lr) { + thread_call_stack *cs = get_thread_call_stack(); + if (cs) { + int nextIndex = (++cs->index); + if (nextIndex >= cs->allocated_length) { + cs->allocated_length += 64; + cs->stack = (thread_call_record *)realloc(cs->stack, cs->allocated_length * sizeof(thread_call_record)); + } + thread_call_record *newRecord = &cs->stack[nextIndex]; + newRecord->self = _self; + newRecord->cls = _cls; + newRecord->cmd = _cmd; + newRecord->lr = lr; + if (cs->is_main_thread && _call_record_enabled) { + struct timeval now; + gettimeofday(&now, NULL); + newRecord->time = (now.tv_sec % 100) * 1000000 + now.tv_usec; + } + } +} + +static inline uintptr_t pop_call_record() { + thread_call_stack *cs = get_thread_call_stack(); + int curIndex = cs->index; + int nextIndex = cs->index--; + thread_call_record *pRecord = &cs->stack[nextIndex]; + + if (cs->is_main_thread && _call_record_enabled) { + struct timeval now; + gettimeofday(&now, NULL); + uint64_t time = (now.tv_sec % 100) * 1000000 + now.tv_usec; + if (time < pRecord->time) { + time += 100 * 1000000; + } + uint64_t cost = time - pRecord->time; + if (cost > _min_time_cost && cs->index < _max_call_depth) { + if (!_qiCallRecords) { + _qiRecordAlloc = 1024; + _qiCallRecords = malloc(sizeof(qiCallRecord) * _qiRecordAlloc); + } + _qiRecordNum++; + if (_qiRecordNum >= _qiRecordAlloc) { + _qiRecordAlloc += 1024; + _qiCallRecords = realloc(_qiCallRecords, sizeof(qiCallRecord) * _qiRecordAlloc); + } + qiCallRecord *log = &_qiCallRecords[_qiRecordNum - 1]; + log->cls = pRecord->cls; + log->depth = curIndex; + log->sel = pRecord->cmd; + log->time = cost; + } + } + return pRecord->lr; +} + +void before_objc_msgSend(id self, SEL _cmd, uintptr_t lr) { + push_call_record(self, object_getClass(self), _cmd, lr); +} + +uintptr_t after_objc_msgSend() { + return pop_call_record(); +} + + +//replacement objc_msgSend (arm64) +// https://blog.nelhage.com/2010/10/amd64-and-va_arg/ +// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf +// https://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARM64FunctionCallingConventions.html +#define call(b, value) \ +__asm volatile ("stp x8, x9, [sp, #-16]!\n"); \ +__asm volatile ("mov x12, %0\n" :: "r"(value)); \ +__asm volatile ("ldp x8, x9, [sp], #16\n"); \ +__asm volatile (#b " x12\n"); + +#define save() \ +__asm volatile ( \ +"stp x8, x9, [sp, #-16]!\n" \ +"stp x6, x7, [sp, #-16]!\n" \ +"stp x4, x5, [sp, #-16]!\n" \ +"stp x2, x3, [sp, #-16]!\n" \ +"stp x0, x1, [sp, #-16]!\n"); + +#define load() \ +__asm volatile ( \ +"ldp x0, x1, [sp], #16\n" \ +"ldp x2, x3, [sp], #16\n" \ +"ldp x4, x5, [sp], #16\n" \ +"ldp x6, x7, [sp], #16\n" \ +"ldp x8, x9, [sp], #16\n" ); + +#define link(b, value) \ +__asm volatile ("stp x8, lr, [sp, #-16]!\n"); \ +__asm volatile ("sub sp, sp, #16\n"); \ +call(b, value); \ +__asm volatile ("add sp, sp, #16\n"); \ +__asm volatile ("ldp x8, lr, [sp], #16\n"); + +#define ret() __asm volatile ("ret\n"); + +__attribute__((__naked__)) +static void hook_Objc_msgSend() { + // Save parameters. + save() + + __asm volatile ("mov x2, lr\n"); + __asm volatile ("mov x3, x4\n"); + + // Call our before_objc_msgSend. + call(blr, &before_objc_msgSend) + + // Load parameters. + load() + + // Call through to the original objc_msgSend. + call(blr, orig_objc_msgSend) + + // Save original objc_msgSend return value. + save() + + // Call our after_objc_msgSend. + call(blr, &after_objc_msgSend) + + // restore lr + __asm volatile ("mov lr, x0\n"); + + // Load original objc_msgSend return value. + load() + + // return + ret() +} + + +#pragma mark public + +void qiCallTraceStart() { + _call_record_enabled = true; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + pthread_key_create(&_thread_key, &release_thread_call_stack); + fish_rebind_symbols((struct rebinding[6]){ + {"objc_msgSend", (void *)hook_Objc_msgSend, (void **)&orig_objc_msgSend}, + }, 1); + }); +} + +void qiCallTraceStop() { + _call_record_enabled = false; +} + +void qiCallConfigMinTime(uint64_t us) { + _min_time_cost = us; +} +void qiCallConfigMaxDepth(int depth) { + _max_call_depth = depth; +} + +qiCallRecord *qiGetCallRecords(int *num) { + if (num) { + *num = _qiRecordNum; + } + return _qiCallRecords; +} + +void qiClearCallRecords() { + if (_qiCallRecords) { + free(_qiCallRecords); + _qiCallRecords = NULL; + } + _qiRecordNum = 0; +} + +#else + +void qiCallTraceStart() {} +void qiCallTraceStop() {} +void qiCallConfigMinTime(uint64_t us) { +} +void qiCallConfigMaxDepth(int depth) { +} +qiCallRecord *qiGetCallRecords(int *num) { + if (num) { + *num = 0; + } + return NULL; +} +void qiClearCallRecords() {} + +#endif diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/QiCallTraceCore.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/QiCallTraceCore.h new file mode 100644 index 00000000..cd47140c --- /dev/null +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/QiCallTraceCore.h @@ -0,0 +1,36 @@ +// +// QiCallTraceCore.h +// Qi_ObjcMsgHook +// +// Created by liusiqi on 2019/11/20. +// Copyright © 2019 QiShare. All rights reserved. +// + +#ifndef QiCallTraceCore_h +#define QiCallTraceCore_h + +#include +#include + + +/* + 函数调用耗时监测 来源:https://www.jianshu.com/p/bc1c000afdba + */ + +typedef struct { + __unsafe_unretained Class cls; + SEL sel; + uint64_t time; // us (1/1000 ms) + int depth; +} qiCallRecord; + +extern void qiCallTraceStart(void); +extern void qiCallTraceStop(void); + +extern void qiCallConfigMinTime(uint64_t us); //default 1000 +extern void qiCallConfigMaxDepth(int depth); //default 3 + +extern qiCallRecord *qiGetCallRecords(int *num); +extern void qiClearCallRecords(void); + +#endif /* QiCallTraceCore_h */ diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 9dae6313..7270eec2 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -3,7 +3,7 @@ * 1.0、APM性能监控 -> CPU占用率、内存/磁盘使用率、卡顿监控定位、Crash防护、线程数量监控、网络监控(TCP 建立连接时间 、DNS 时间、 SSL时间、首包时间、响应时间 、流量)、ViewController启动耗时监测 、load方法耗时、函数耗时...... +> CPU占用率、内存/磁盘使用率、卡顿监控定位、Crash防护、线程数量监控、网络监控(TCP 建立连接时间 、DNS 时间、 SSL时间、首包时间、响应时间 、流量)、ViewController启动耗时监测 、load方法耗时、方法耗时监控...... * 1.1、内存优化 @@ -33,6 +33,7 @@ > [iOS-Performance-Optimization](https://github.com/skyming/iOS-Performance-Optimization) > [DoraemonKit](https://github.com/didi/DoraemonKit/blob/master/README_CN.md) > [乐少](https://www.jianshu.com/u/9c51a213b02e) +> [iOS 性能监控(三)—— 方法耗时监控](https://www.jianshu.com/p/bc1c000afdba) ## 二、数据结构与算法 @@ -52,3 +53,5 @@ ## 五、音视频 + +1、[(强烈推荐)移动端音视频从零到上手](https://juejin.im/post/6844903889007820813) From 6b71f85603996c10d490164c59ec4be68a9e74dd Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 10 Aug 2020 00:01:55 +0800 Subject: [PATCH 135/356] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheManager.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheManager.m b/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheManager.m index 8d8c3a5c..91262fd5 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheManager.m +++ b/iOS_Tips/DarkMode/WKWebView/WebCache/SLWebCacheManager.m @@ -163,7 +163,7 @@ - (BOOL)writeCacheData:(NSCachedURLResponse *)cachedURLResponse withRequest:(NSU NSDate *date = [NSDate date]; NSDictionary *info = @{@"time" : [NSString stringWithFormat:@"%f",[date timeIntervalSince1970]], @"MIMEType" : cachedURLResponse.response.MIMEType, - @"textEncodingName" : cachedURLResponse.response.textEncodingName}; + @"textEncodingName" : cachedURLResponse.response.textEncodingName == nil ? @"": cachedURLResponse.response.textEncodingName}; //写入磁盘 BOOL result1 = [info writeToFile:[self filePathFromRequest:request isInfo:YES] atomically:YES]; From 51b19956c745e069423c0aa5931216493c32c7d4 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 10 Aug 2020 15:45:59 +0800 Subject: [PATCH 136/356] =?UTF-8?q?=E5=8D=9A=E5=AE=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 8a77fe82..799e04c1 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -36,7 +36,8 @@ * 34、[punmy](https://punmy.cn/) * 35、[LearnOpengl](https://learnopengl-cn.github.io) * 36、[everettjf](https://everettjf.github.io/) - +* 37、[HybridPageKit](https://dequan1331.github.io/index.html) +* 38、[纳兰若水](https://www.xuyanlan.com/archives/) ## 高质量微信公众号 From 88f7ea8a366642aaf0bbbc80b551a25ce9c37830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Mon, 10 Aug 2020 17:37:20 +0800 Subject: [PATCH 137/356] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 898a169d..2d77e323 100644 --- a/README.md +++ b/README.md @@ -127,7 +127,7 @@ #### 6.7-[二进制重排优化启动速度](https://juejin.im/post/5ea79839f265da7bba509590) #### 6.8-[iOS APM应用性能监控管理(doing)]() -> CPU占用率、内存/磁盘使用率、卡顿监控定位、Crash防护、线程数量监控、网络监控(TCP 建立连接时间 、DNS 时间、 SSL时间、首包时间、响应时间 、流量)、ViewController启动耗时监测 ...... +> CPU占用率、内存/磁盘使用率、卡顿监控定位、Crash防护、线程数量监控、网络监控(TCP 建立连接时间 、DNS 时间、 SSL时间、首包时间、响应时间 、流量)、ViewController启动耗时监测 、load方法的耗时、方法执行耗时...... ## 7-iOSCrash防护 From 8c9d9721a7d1c83c303f2f81ac9b4511d27b3ca7 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 10 Aug 2020 18:20:33 +0800 Subject: [PATCH 138/356] =?UTF-8?q?=E5=8D=9A=E5=AE=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...1\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 799e04c1..2de5e079 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -38,6 +38,7 @@ * 36、[everettjf](https://everettjf.github.io/) * 37、[HybridPageKit](https://dequan1331.github.io/index.html) * 38、[纳兰若水](https://www.xuyanlan.com/archives/) +* 39、[知识小集](https://juejin.im/user/1327865776308782) ## 高质量微信公众号 From ae5cef6388d19de375438c08f3e65186e0280488 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 11 Aug 2020 19:43:56 +0800 Subject: [PATCH 139/356] =?UTF-8?q?=E5=8D=9A=E5=AE=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 8 +++++--- ...17\346\212\200\346\234\257\345\215\232\345\256\242.md" | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 7270eec2..f3c0e202 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -7,7 +7,7 @@ * 1.1、内存优化 -> 合理的线程分配、使用正确的API、延时加载、按需加载/复用、处理内存警告、自动释放池、 +> 合理的线程分配、使用正确的API、延时加载、按需加载/复用、处理内存警告、自动释放池@autoreleasepool、图片降采样/分片加载、NSCache、避免循环引用导致的内存泄漏 * 1.2、卡顿优化 @@ -25,15 +25,17 @@ * 1.7、健壮性/稳定性 -> 启动连续闪退保护、Crash防护 +> 启动连续闪退保护、Crash防护、Crash分析 * 1.7、安全性 -* 资料 +> 资料 > [iOS-Performance-Optimization](https://github.com/skyming/iOS-Performance-Optimization) > [DoraemonKit](https://github.com/didi/DoraemonKit/blob/master/README_CN.md) > [乐少](https://www.jianshu.com/u/9c51a213b02e) > [iOS 性能监控(三)—— 方法耗时监控](https://www.jianshu.com/p/bc1c000afdba) +> [iOS crash 日志堆栈解析](https://juejin.im/post/6844903598011187213) +> [iOS Memory 内存详解 (长文)](https://juejin.im/post/6844903902169710600) ## 二、数据结构与算法 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 2de5e079..67657910 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -39,6 +39,8 @@ * 37、[HybridPageKit](https://dequan1331.github.io/index.html) * 38、[纳兰若水](https://www.xuyanlan.com/archives/) * 39、[知识小集](https://juejin.im/user/1327865776308782) +* 40、[Cyandev](https://juejin.im/user/3298190611199415) +* 41、[RickeyBoy](https://juejin.im/user/2928754706626136) ## 高质量微信公众号 From 6c97fddcaa4fac8cddd8d86ff4c0f06318f0fc47 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 12 Aug 2020 18:44:07 +0800 Subject: [PATCH 140/356] =?UTF-8?q?=E5=8D=9A=E5=AE=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 7 +++++-- ...217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index f3c0e202..960fa763 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -7,11 +7,11 @@ * 1.1、内存优化 -> 合理的线程分配、使用正确的API、延时加载、按需加载/复用、处理内存警告、自动释放池@autoreleasepool、图片降采样/分片加载、NSCache、避免循环引用导致的内存泄漏 +> 合理的线程分配、使用正确的API、延时加载、按需加载/复用、处理内存警告、自动释放池@autoreleasepool、图片降采样/分片加载、NSCache、避免循环引用导致的内存泄漏 * 1.2、卡顿优化 -> 优化业务流程、 预处理、 三级缓存 +> 优化业务流程、 预处理、 三级缓存、空间换时间、避免圆角/阴影/光栅化/透明颜色造成的离屏渲染、 * 1.3、 安装包瘦身 @@ -35,7 +35,10 @@ > [乐少](https://www.jianshu.com/u/9c51a213b02e) > [iOS 性能监控(三)—— 方法耗时监控](https://www.jianshu.com/p/bc1c000afdba) > [iOS crash 日志堆栈解析](https://juejin.im/post/6844903598011187213) +> [iOS崩溃crash大解析](https://www.jianshu.com/p/1b804426d212) > [iOS Memory 内存详解 (长文)](https://juejin.im/post/6844903902169710600) +> [iOS 性能优化调试](https://www.jianshu.com/c/fcb00b489a85) +> [iOS Memory Deep Dive](https://www.jianshu.com/p/dad9f27e412e) ## 二、数据结构与算法 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 67657910..cf3cee4f 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -41,6 +41,7 @@ * 39、[知识小集](https://juejin.im/user/1327865776308782) * 40、[Cyandev](https://juejin.im/user/3298190611199415) * 41、[RickeyBoy](https://juejin.im/user/2928754706626136) +* 42、[落影loyinglin](https://github.com/loyinglin) ## 高质量微信公众号 From cfea3aaf663d22c430683576e8d60ffc655756be Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 12 Aug 2020 20:30:55 +0800 Subject: [PATCH 141/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 5 +++++ 1 file changed, 5 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 960fa763..a3e744ea 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -60,3 +60,8 @@ ## 五、音视频 1、[(强烈推荐)移动端音视频从零到上手](https://juejin.im/post/6844903889007820813) + + +## 六、Shell脚本 + +* 1、[Shell脚本编程30分钟入门](https://github.com/qinjx/30min_guides/blob/master/shell.md) From 286b8f3a5b0c4b65b71e92652d879a92b37ec479 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 13 Aug 2020 17:40:55 +0800 Subject: [PATCH 142/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 2 + .../DarkMode/General/Tool/PrefixHeader.pch | 134 +----------------- .../WorkIssues/\347\254\224\350\256\260.md" | 5 +- 3 files changed, 8 insertions(+), 133 deletions(-) diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 5d5ddb84..64689438 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -499,6 +499,7 @@ 78EF8B6324188767008D0CD7 /* SLAlertView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAlertView.m; sourceTree = ""; }; 78F42021237915730093497C /* SLGPUImageController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLGPUImageController.h; sourceTree = ""; }; 78F42022237915730093497C /* SLGPUImageController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLGPUImageController.m; sourceTree = ""; }; + 78F4E41224E5404A000B2ADE /* SLToolMacro.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLToolMacro.h; sourceTree = ""; }; 78F54914233383D800910215 /* SLBlurView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLBlurView.h; sourceTree = ""; }; 78F54915233383D800910215 /* SLBlurView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLBlurView.m; sourceTree = ""; }; 78FA0F9B235407E6003E456B /* SLDrawView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLDrawView.h; sourceTree = ""; }; @@ -810,6 +811,7 @@ isa = PBXGroup; children = ( 78AA10F42371A7B50044A6F8 /* PrefixHeader.pch */, + 78F4E41224E5404A000B2ADE /* SLToolMacro.h */, 78777CE4238FF65C006FA671 /* SLDelayPerform.h */, 78777CE5238FF65C006FA671 /* SLDelayPerform.m */, 783504622452C20B0071283E /* SLMethod.h */, diff --git a/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch b/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch index 8c623156..b2851d91 100644 --- a/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch +++ b/iOS_Tips/DarkMode/General/Tool/PrefixHeader.pch @@ -17,137 +17,7 @@ #ifdef __OBJC__ // 只被object-c文件所引用 -// 这个定义全工程都可以调用,不用重复引入 - -///我的联系方式 -#define SL_JianShuUrl @"https://www.jianshu.com/u/e15d1f644bea" -#define SL_GithubUrl @"https://github.com/wsl2ls/iOS_Tips.git" -#define SL_WeChat @"iOS2679114653" -#define SL_QQGroup @"835303405" -#define SL_WeiBo @"https://weibo.com/5732733120/profile?rightmod=1&wvr=6&mod=personinfo&is_all=1" -#define SL_CSDN @"https://blog.csdn.net/wsl2ls" -#define SL_JueJin @"https://juejin.im/user/5c00d97b6fb9a049fb436288" -#define SL_Blog @"https://wsl2ls.github.io" -//【腾讯文档】2020_慕课网/极客/腾讯课堂等课程资源:https://docs.qq.com/doc/DS1lhWkhPc2xEamx5 - -//---------------------- About UI/Device ---------------------------- -#define iPhone4 ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(640, 960), [[UIScreen mainScreen] currentMode].size) : NO) -#define iPhone5 ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(640, 1136), [[UIScreen mainScreen] currentMode].size) : NO) -#define iPhone6 ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(750, 1334), [[UIScreen mainScreen] currentMode].size) : NO) -#define iPhone6Plus ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1242, 2208), [[UIScreen mainScreen] currentMode].size) : NO) -#define iPhone6PlusScale ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2001), [[UIScreen mainScreen] currentMode].size) : NO) -#define iPhoneX ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO) -#define iPhoneXR ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(828, 1792), [[UIScreen mainScreen] currentMode].size) : NO) -#define iPhoneXM ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1242, 2688), [[UIScreen mainScreen] currentMode].size) : NO) - -#define SL_SafeAreaEnable ((iPhoneX || iPhoneXR || iPhoneXM) ? YES : NO) - -#define SL_TopSafeAreaHeight (SL_SafeAreaEnable ? 44.f : 20.f) -#define SL_TopNavigationBarHeight (SL_SafeAreaEnable ? 88.f : 64.f) -#define SL_BottomTabbarHeight (SL_SafeAreaEnable ? (49.f + 34.f) : (49.f)) -#define SL_BottomSafeAreaHeight (SL_SafeAreaEnable ? (34.f) : (0.f)) - -/// 屏幕宽高 -#define SL_kScreenWidth [UIScreen mainScreen].bounds.size.width -#define SL_kScreenHeight [UIScreen mainScreen].bounds.size.height - -/** 判断是否为iPhone */ -#define isiPhone (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) -/** 判断是否是iPad */ -#define isiPad (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) -/** 判断是否为iPod */ -#define isiPod ([[[UIDevice currentDevice] model] isEqualToString:@"iPod touch"]) - -//Get the OS version. 判断操作系统版本 -#define SL_IOSVERSION [[[UIDevice currentDevice] systemVersion] floatValue] -#define SL_CurrentSystemVersion ([[UIDevice currentDevice] systemVersion]) -#define SL_CurrentLanguage ([[NSLocale preferredLanguages] objectAtIndex:0]) - -//judge the simulator or hardware device 判断是真机还是模拟器 -#if TARGET_OS_IPHONE -//iPhone Device -#endif -#if TARGET_IPHONE_SIMULATOR -//iPhone Simulator -#endif - - -//---------------------- About Helper 辅助方法 ---------------------------- -/// 弱引用对象 -#define SL_WeakSelf __weak typeof(self) weakSelf = self; - -///主线程操作 -#define SL_DISPATCH_ON_MAIN_THREAD(mainQueueBlock) dispatch_async(dispatch_get_main_queue(),mainQueueBlock); -#define SL_GCDWithGlobal(block) dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block) -#define sl_GCDWithMain(block) dispatch_async(dispatch_get_main_queue(),block) - -///NSUserDefaults 存储 -#define SL_UserDefaultSetObjectForKey(__VALUE__,__KEY__) \ -{\ -[[NSUserDefaults standardUserDefaults] setObject:__VALUE__ forKey:__KEY__];\ -[[NSUserDefaults standardUserDefaults] synchronize];\ -} -///NSUserDefaults 获得存储的对象 -#define SL_UserDefaultObjectForKey(__KEY__) [[NSUserDefaults standardUserDefaults] objectForKey:__KEY__] -///NSUserDefaults 删除对象 -#define SL_UserDefaultRemoveObjectForKey(__KEY__) \ -{\ -[[NSUserDefaults standardUserDefaults] removeObjectForKey:__KEY__];\ -[[NSUserDefaults standardUserDefaults] synchronize];\ -} - -/** 快速查询一段代码的执行时间 */ -/** 用法 - SL_StartTime - do your work here - SL_EndDuration - */ -#define SL_StartTime NSDate *startTime = [NSDate date] -#define SL_EndDuration -[startTime timeIntervalSinceNow] - -// STRING容错机制 -#define SL_IS_NULL(x) (!x || [x isKindOfClass:[NSNull class]]) -#define SL_IS_EMPTY_STRING(x) (SL_IS_NULL(x) || [x isEqual:@""] || [x isEqual:@"(null)"]) -#define SL_DEFUSE_EMPTY_STRING(x) (!SL_IS_EMPTY_STRING(x) ? x : @"") - - -//沙河目录 -///获取沙盒主目录路径 -#define SL_HomeDir NSHomeDirectory(); -/// 获取Documents目录路径 -#define SL_DocumentDir [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] -/// 获取Library的目录路径 -#define SL_LibraryDir [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject] -/// 获取Caches目录路径 -#define SL_CachesDir [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject] -/// 获取tmp目录路径 -#define SL_TmpDir NSTemporaryDirectory() - -//---------------------- About Color 颜色 ---------------------------- -/// 随机颜色 -#define SL_UIColorFromRandomColor [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:1.0] -/// rgb颜色 -#define SL_UIColorFromRGB(r,g,b,a) [UIColor colorWithRed:(r)/255.0f green:(g)/255.0f blue:(b)/255.0f alpha:(a)] -/// 16进制 颜色 -#define SL_UIColorFromHex(rgbValue, a) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:(a)] - -//---------------------- About Log 打印日志 ---------------------------- -/// 打印 -#ifdef DEBUG -# define NSLog(fmt, ...) NSLog((fmt), ##__VA_ARGS__); -# define SL_Log(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); -#define SL_NSLog(...) printf("%f %s %ld :%s\n",[[NSDate date]timeIntervalSince1970],strrchr(__FILE__,'/'),[[NSNumber numberWithInt:__LINE__] integerValue],[[NSString stringWithFormat:__VA_ARGS__]UTF8String]); -#else -# define NSLog(fmt, ...) -# define SL_Log(...) -# define SL_NSLog(...) -#endif - -//---------------------- About Shader 着色器 ---------------------------- -//#x 将参数x字符串化 -#define STRINGIZE(x) #x -#define STRINGIZE2(x) STRINGIZE(x) -#define Shader_String(text) @ STRINGIZE2(text) +#import "SLToolMacro.h" #import "UIView+SLFrame.h" @@ -157,8 +27,8 @@ #import "SLMethod.h" #import "SLViewController.h" -#endif +#endif #endif /* PrefixHeader_pch */ diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index a3e744ea..c191fdfb 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -11,10 +11,12 @@ * 1.2、卡顿优化 -> 优化业务流程、 预处理、 三级缓存、空间换时间、避免圆角/阴影/光栅化/透明颜色造成的离屏渲染、 +> 优化业务流程、 预处理、 缓存/空间换时间、避免圆角/阴影/光栅化/透明颜色造成的离屏渲染、异步绘制/合并图层 * 1.3、 安装包瘦身 +> + * 1.4、启动时间优化 > 合并动态库、二进制重排、异步延时加载、load 的方法处理 @@ -39,6 +41,7 @@ > [iOS Memory 内存详解 (长文)](https://juejin.im/post/6844903902169710600) > [iOS 性能优化调试](https://www.jianshu.com/c/fcb00b489a85) > [iOS Memory Deep Dive](https://www.jianshu.com/p/dad9f27e412e) +> [iOS性能优化系列篇之“列表流畅度优化”](https://juejin.im/post/6844903656769208334) ## 二、数据结构与算法 From 5b0328bba0068d7040ca7e29b7fc7be4604bffbc Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 13 Aug 2020 17:41:05 +0800 Subject: [PATCH 143/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/General/Tool/SLToolMacro.h | 149 +++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 iOS_Tips/DarkMode/General/Tool/SLToolMacro.h diff --git a/iOS_Tips/DarkMode/General/Tool/SLToolMacro.h b/iOS_Tips/DarkMode/General/Tool/SLToolMacro.h new file mode 100644 index 00000000..aea11776 --- /dev/null +++ b/iOS_Tips/DarkMode/General/Tool/SLToolMacro.h @@ -0,0 +1,149 @@ +// +// SLToolMacro.h +// DarkMode +// +// Created by wsl on 2020/8/13. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#ifndef SLToolMacro_h +#define SLToolMacro_h + +#pragma mark - Call Me +///我的联系方式 +#define SL_JianShuUrl @"https://www.jianshu.com/u/e15d1f644bea" +#define SL_GithubUrl @"https://github.com/wsl2ls/iOS_Tips.git" +#define SL_WeChat @"iOS2679114653" +#define SL_QQGroup @"835303405" +#define SL_WeiBo @"https://weibo.com/5732733120/profile?rightmod=1&wvr=6&mod=personinfo&is_all=1" +#define SL_CSDN @"https://blog.csdn.net/wsl2ls" +#define SL_JueJin @"https://juejin.im/user/5c00d97b6fb9a049fb436288" +#define SL_Blog @"https://wsl2ls.github.io" +//【腾讯文档】2020_慕课网/极客/腾讯课堂等课程资源:https://docs.qq.com/doc/DS1lhWkhPc2xEamx5 + +#pragma mark - About UI/Device +//---------------------- About UI/Device ---------------------------- +#define iPhone4 ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(640, 960), [[UIScreen mainScreen] currentMode].size) : NO) +#define iPhone5 ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(640, 1136), [[UIScreen mainScreen] currentMode].size) : NO) +#define iPhone6 ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(750, 1334), [[UIScreen mainScreen] currentMode].size) : NO) +#define iPhone6Plus ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1242, 2208), [[UIScreen mainScreen] currentMode].size) : NO) +#define iPhone6PlusScale ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2001), [[UIScreen mainScreen] currentMode].size) : NO) +#define iPhoneX ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO) +#define iPhoneXR ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(828, 1792), [[UIScreen mainScreen] currentMode].size) : NO) +#define iPhoneXM ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1242, 2688), [[UIScreen mainScreen] currentMode].size) : NO) + +#define SL_SafeAreaEnable ((iPhoneX || iPhoneXR || iPhoneXM) ? YES : NO) + +#define SL_TopSafeAreaHeight (SL_SafeAreaEnable ? 44.f : 20.f) +#define SL_TopNavigationBarHeight (SL_SafeAreaEnable ? 88.f : 64.f) +#define SL_BottomTabbarHeight (SL_SafeAreaEnable ? (49.f + 34.f) : (49.f)) +#define SL_BottomSafeAreaHeight (SL_SafeAreaEnable ? (34.f) : (0.f)) + +/// 屏幕宽高 +#define SL_kScreenWidth [UIScreen mainScreen].bounds.size.width +#define SL_kScreenHeight [UIScreen mainScreen].bounds.size.height + +/** 判断是否为iPhone */ +#define isiPhone (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) +/** 判断是否是iPad */ +#define isiPad (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) +/** 判断是否为iPod */ +#define isiPod ([[[UIDevice currentDevice] model] isEqualToString:@"iPod touch"]) + +//Get the OS version. 判断操作系统版本 +#define SL_IOSVERSION [[[UIDevice currentDevice] systemVersion] floatValue] +#define SL_CurrentSystemVersion ([[UIDevice currentDevice] systemVersion]) +#define SL_CurrentLanguage ([[NSLocale preferredLanguages] objectAtIndex:0]) + +//judge the simulator or hardware device 判断是真机还是模拟器 +#if TARGET_OS_IPHONE +//iPhone Device +#endif +#if TARGET_IPHONE_SIMULATOR +//iPhone Simulator +#endif + +#pragma mark - About Helper 辅助方法 +//---------------------- About Helper 辅助方法 ---------------------------- +/// 弱引用对象 +#define SL_WeakSelf __weak typeof(self) weakSelf = self; + +///主线程操作 +#define SL_DISPATCH_ON_MAIN_THREAD(mainQueueBlock) dispatch_async(dispatch_get_main_queue(),mainQueueBlock); +#define SL_GCDWithGlobal(block) dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block) +#define sl_GCDWithMain(block) dispatch_async(dispatch_get_main_queue(),block) + +///NSUserDefaults 存储 +#define SL_UserDefaultSetObjectForKey(__VALUE__,__KEY__) \ +{\ +[[NSUserDefaults standardUserDefaults] setObject:__VALUE__ forKey:__KEY__];\ +[[NSUserDefaults standardUserDefaults] synchronize];\ +} +///NSUserDefaults 获得存储的对象 +#define SL_UserDefaultObjectForKey(__KEY__) [[NSUserDefaults standardUserDefaults] objectForKey:__KEY__] +///NSUserDefaults 删除对象 +#define SL_UserDefaultRemoveObjectForKey(__KEY__) \ +{\ +[[NSUserDefaults standardUserDefaults] removeObjectForKey:__KEY__];\ +[[NSUserDefaults standardUserDefaults] synchronize];\ +} + +/** 快速查询一段代码的执行时间 */ +/** 用法 + SL_StartTime + do your work here + SL_EndDuration + */ +#define SL_StartTime NSDate *startTime = [NSDate date] +#define SL_EndDuration -[startTime timeIntervalSinceNow] + +// STRING容错机制 +#define SL_IS_NULL(x) (!x || [x isKindOfClass:[NSNull class]]) +#define SL_IS_EMPTY_STRING(x) (SL_IS_NULL(x) || [x isEqual:@""] || [x isEqual:@"(null)"]) +#define SL_DEFUSE_EMPTY_STRING(x) (!SL_IS_EMPTY_STRING(x) ? x : @"") + + +//沙河目录 +///获取沙盒主目录路径 +#define SL_HomeDir NSHomeDirectory(); +/// 获取Documents目录路径 +#define SL_DocumentDir [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] +/// 获取Library的目录路径 +#define SL_LibraryDir [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject] +/// 获取Caches目录路径 +#define SL_CachesDir [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject] +/// 获取tmp目录路径 +#define SL_TmpDir NSTemporaryDirectory() + +#pragma mark - About Color 颜色 +//---------------------- About Color 颜色 ---------------------------- +/// 随机颜色 +#define SL_UIColorFromRandomColor [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:1.0] +/// rgb颜色 +#define SL_UIColorFromRGB(r,g,b,a) [UIColor colorWithRed:(r)/255.0f green:(g)/255.0f blue:(b)/255.0f alpha:(a)] +/// 16进制 颜色 +#define SL_UIColorFromHex(rgbValue, a) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:(a)] + +#pragma mark - About Log 打印日志 +//---------------------- About Log 打印日志 ---------------------------- +/// 打印 +#ifdef DEBUG +# define NSLog(fmt, ...) NSLog((fmt), ##__VA_ARGS__); +# define SL_Log(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); +#define SL_NSLog(...) printf("%f %s %ld :%s\n",[[NSDate date]timeIntervalSince1970],strrchr(__FILE__,'/'),[[NSNumber numberWithInt:__LINE__] integerValue],[[NSString stringWithFormat:__VA_ARGS__]UTF8String]); +#else +# define NSLog(fmt, ...) +# define SL_Log(...) +# define SL_NSLog(...) +#endif + +//---------------------- About Shader 着色器 ---------------------------- +//#x 将参数x字符串化 +#define STRINGIZE(x) #x +#define STRINGIZE2(x) STRINGIZE(x) +#define Shader_String(text) @ STRINGIZE2(text) + + + + +#endif /* SLToolMacro_h */ From 4c6af7aa7d0baf478227b5284ce1e8abcfacda67 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 13 Aug 2020 19:14:45 +0800 Subject: [PATCH 144/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 6 ++++++ 1 file changed, 6 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index c191fdfb..5312fbfe 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -68,3 +68,9 @@ ## 六、Shell脚本 * 1、[Shell脚本编程30分钟入门](https://github.com/qinjx/30min_guides/blob/master/shell.md) + + + +## 其它 + +* 1、[CocoaPods 都做了什么?](https://www.jianshu.com/p/84936d9344ff) From 35f8bbbcff776e6e156a0b7e761bc2e8c143852e Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 14 Aug 2020 20:15:02 +0800 Subject: [PATCH 145/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/.DS_Store | Bin 10244 -> 10244 bytes .../WorkIssues/\347\254\224\350\256\260.md" | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS_Tips/.DS_Store b/iOS_Tips/.DS_Store index 2673fac1a1a3f5cd6d9f279b0dd94795ad22cafb..007448fdc99fb4db63cd7855127d4372871a98d9 100644 GIT binary patch delta 100 zcmZn(XbIS0CBdZ6Ir)INhDdI{i%U{Yei8!%1IMSpw;BtI4mpA(CNGfSK^3?o!N(Xd q`L%==x4B8Oi4On|H6num delta 100 zcmZn(XbIS0CBekpJ^6sRhDdI{i%U{Yei8!%14sJGZ9yh6ha5o?lNU(vpbFfP;A1qH q{93|_nWfx#@*4>qfr1Rf;N<+=0-#<729^yBlMSTgHaAH&@c{s}&meaI diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 5312fbfe..af2db2e3 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -11,7 +11,7 @@ * 1.2、卡顿优化 -> 优化业务流程、 预处理、 缓存/空间换时间、避免圆角/阴影/光栅化/透明颜色造成的离屏渲染、异步绘制/合并图层 +> 优化业务流程、 预处理、 缓存/空间换时间、避免圆角/阴影/光栅化/透明颜色造成的离屏渲染、异步解码绘制、合并图层、 * 1.3、 安装包瘦身 From 3e112c67f4aec06ef23c5ed3e555483a143f387b Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 17 Aug 2020 19:10:14 +0800 Subject: [PATCH 146/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 4 ++-- ...07\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index af2db2e3..27e1f539 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -11,11 +11,11 @@ * 1.2、卡顿优化 -> 优化业务流程、 预处理、 缓存/空间换时间、避免圆角/阴影/光栅化/透明颜色造成的离屏渲染、异步解码绘制、合并图层、 +> 优化业务流程、 预处理、 缓存/空间换时间、避免圆角/阴影/光栅化/透明造成的离屏渲染、异步解码绘制、合并图层、图像字节对象 * 1.3、 安装包瘦身 -> +> 去掉无用资源和压缩资源、编译选项优化、可执行文件瘦身 * 1.4、启动时间优化 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index cf3cee4f..8f72bda2 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -42,6 +42,7 @@ * 40、[Cyandev](https://juejin.im/user/3298190611199415) * 41、[RickeyBoy](https://juejin.im/user/2928754706626136) * 42、[落影loyinglin](https://github.com/loyinglin) +* 43、[阿毛的蛋疼地](https://xiangwangfeng.com/) ## 高质量微信公众号 From 3a2e3c8b7f4fee188b1a111ddd9c829fc2cccdf4 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 18 Aug 2020 16:09:47 +0800 Subject: [PATCH 147/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 27e1f539..9603a99c 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -42,7 +42,7 @@ > [iOS 性能优化调试](https://www.jianshu.com/c/fcb00b489a85) > [iOS Memory Deep Dive](https://www.jianshu.com/p/dad9f27e412e) > [iOS性能优化系列篇之“列表流畅度优化”](https://juejin.im/post/6844903656769208334) - +> [基于clang插件的一种iOS包大小瘦身方案](https://mp.weixin.qq.com/s?__biz=MzUxMzcxMzE5Ng==&mid=2247488360&idx=1&sn=94fba30a87d0f9bc0b9ff94d3fed3386&source=41#wechat_redirect) ## 二、数据结构与算法 1、 [LeetcodeTop](https://github.com/afatcoder/LeetcodeTop) From b8cb0a5818ed9ecbebcb8194ace92adf4419b008 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 18 Aug 2020 16:30:48 +0800 Subject: [PATCH 148/356] =?UTF-8?q?=E5=8D=9A=E5=AE=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...1\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 8f72bda2..c2fce2c5 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -43,6 +43,7 @@ * 41、[RickeyBoy](https://juejin.im/user/2928754706626136) * 42、[落影loyinglin](https://github.com/loyinglin) * 43、[阿毛的蛋疼地](https://xiangwangfeng.com/) +* 44、[与佳期](gonghonglou.com) ## 高质量微信公众号 From 5d0b8317ada0f39c0bb8eb078526da69daa1b204 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 18 Aug 2020 19:54:28 +0800 Subject: [PATCH 149/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\347\254\224\350\256\260.md" | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 9603a99c..ffdd0db8 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -45,24 +45,24 @@ > [基于clang插件的一种iOS包大小瘦身方案](https://mp.weixin.qq.com/s?__biz=MzUxMzcxMzE5Ng==&mid=2247488360&idx=1&sn=94fba30a87d0f9bc0b9ff94d3fed3386&source=41#wechat_redirect) ## 二、数据结构与算法 -1、 [LeetcodeTop](https://github.com/afatcoder/LeetcodeTop) +* 1、 [LeetcodeTop](https://github.com/afatcoder/LeetcodeTop) ## 三、面试题相关 -1、[iOS-InterviewQuestion-collection](https://github.com/liberalisman/iOS-InterviewQuestion-collection) -2、[阿里、字节 一套高效的iOS面试题解答](https://github.com/colourful987/bytedance-alibaba-interview) -3、[2019年iOS面试反思总结](https://juejin.im/post/6844903942644563982) -4、[IOS面试考察(九):性能优化相关问题](https://juejin.im/post/6844904131941892110#heading-50) -5、[Theendisthebegi ](https://www.jianshu.com/u/b836babfef41) -6、[analyze](https://github.com/draveness/analyze) +* 1、[iOS-InterviewQuestion-collection](https://github.com/liberalisman/iOS-InterviewQuestion-collection) +* 2、[阿里、字节 一套高效的iOS面试题解答](https://github.com/colourful987/bytedance-alibaba-interview) +* 3、[2019年iOS面试反思总结](https://juejin.im/post/6844903942644563982) +* 4、[IOS面试考察(九):性能优化相关问题](https://juejin.im/post/6844904131941892110#heading-50) +* 5、[Theendisthebegi ](https://www.jianshu.com/u/b836babfef41) +* 6、[analyze](https://github.com/draveness/analyze) ## 四、逆向与安全 -1、 [趣探 Mach-O](https://juejin.im/post/5a0c5c5e51882555cc416602) -2、 [iOS程序员的自我修养 - 编译、链接、装载](https://juejin.im/post/5d5273b1f265da03f233c2d6) +* 1、 [趣探 Mach-O](https://juejin.im/post/5a0c5c5e51882555cc416602) +* 2、 [iOS程序员的自我修养 - 编译、链接、装载](https://juejin.im/post/5d5273b1f265da03f233c2d6) ## 五、音视频 -1、[(强烈推荐)移动端音视频从零到上手](https://juejin.im/post/6844903889007820813) +* 1、[(强烈推荐)移动端音视频从零到上手](https://juejin.im/post/6844903889007820813) ## 六、Shell脚本 @@ -71,6 +71,8 @@ +## 七、网络 + ## 其它 * 1、[CocoaPods 都做了什么?](https://www.jianshu.com/p/84936d9344ff) From 564ecceb5fc18af796b0a559df5a5e17398a7ab2 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 19 Aug 2020 09:24:37 +0800 Subject: [PATCH 150/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 2 ++ 1 file changed, 2 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index ffdd0db8..e1ba89a1 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -73,6 +73,8 @@ ## 七、网络 +* 1、[TCP序列号和确认号详解](https://blog.csdn.net/fujibao/article/details/80857180) + ## 其它 * 1、[CocoaPods 都做了什么?](https://www.jianshu.com/p/84936d9344ff) From b3feb0e412b86e79c03d5a1043b02369fc300f0a Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 19 Aug 2020 15:52:27 +0800 Subject: [PATCH 151/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/.DS_Store | Bin 10244 -> 10244 bytes iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 10 +++++++++- .../WorkIssues/\347\254\224\350\256\260.md" | 3 ++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/iOS_Tips/.DS_Store b/iOS_Tips/.DS_Store index 007448fdc99fb4db63cd7855127d4372871a98d9..ca771eb506401f4ca3bae678af430abd16b41d85 100644 GIT binary patch delta 36 scmZn(XbG6$&nU4mU^hRb#N 合并动态库、二进制重排、异步延时加载、load 的方法处理 +> 合并减少动态库、二进制重排、异步延时加载、load 的方法处理、清理无用类 * 1.5、编译时间优化 @@ -43,6 +43,7 @@ > [iOS Memory Deep Dive](https://www.jianshu.com/p/dad9f27e412e) > [iOS性能优化系列篇之“列表流畅度优化”](https://juejin.im/post/6844903656769208334) > [基于clang插件的一种iOS包大小瘦身方案](https://mp.weixin.qq.com/s?__biz=MzUxMzcxMzE5Ng==&mid=2247488360&idx=1&sn=94fba30a87d0f9bc0b9ff94d3fed3386&source=41#wechat_redirect) +> [iOS 启动速度优化和安装包优化简单总结](https://juejin.im/post/6844903821387235341) ## 二、数据结构与算法 * 1、 [LeetcodeTop](https://github.com/afatcoder/LeetcodeTop) From 0df8a010847e74fb14e99e820f3fc414a993a1b2 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 19 Aug 2020 16:06:18 +0800 Subject: [PATCH 152/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 32c1d1d7..e9c5b41f 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -42,7 +42,7 @@ > [iOS 性能优化调试](https://www.jianshu.com/c/fcb00b489a85) > [iOS Memory Deep Dive](https://www.jianshu.com/p/dad9f27e412e) > [iOS性能优化系列篇之“列表流畅度优化”](https://juejin.im/post/6844903656769208334) -> [基于clang插件的一种iOS包大小瘦身方案](https://mp.weixin.qq.com/s?__biz=MzUxMzcxMzE5Ng==&mid=2247488360&idx=1&sn=94fba30a87d0f9bc0b9ff94d3fed3386&source=41#wechat_redirect) +> [iOS瘦身之道](https://juejin.im/post/6844903845340921869) > [iOS 启动速度优化和安装包优化简单总结](https://juejin.im/post/6844903821387235341) ## 二、数据结构与算法 From 3704d66088ad62c616bfebe9f1a534ff634f0114 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 19 Aug 2020 17:21:08 +0800 Subject: [PATCH 153/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 5 +++-- ...7\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index e9c5b41f..85c43644 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -11,11 +11,11 @@ * 1.2、卡顿优化 -> 优化业务流程、 预处理、 缓存/空间换时间、避免圆角/阴影/光栅化/透明造成的离屏渲染、异步解码绘制、合并图层、图像字节对象 +> 优化业务流程、 预处理、 缓存/空间换时间、避免圆角/阴影/光栅化/透明造成的离屏渲染、异步解码绘制、合并图层、图像字节对齐 * 1.3、 安装包瘦身 -> 去掉无用资源和压缩资源、编译选项优化、可执行文件瘦身 +> 去掉无用资源、压缩资源、矢量图、编译选项优化、可执行文件瘦身 * 1.4、启动时间优化 @@ -43,6 +43,7 @@ > [iOS Memory Deep Dive](https://www.jianshu.com/p/dad9f27e412e) > [iOS性能优化系列篇之“列表流畅度优化”](https://juejin.im/post/6844903656769208334) > [iOS瘦身之道](https://juejin.im/post/6844903845340921869) +> [如何使用 Clang Plugin 找到项目中的无用代码](https://blog.gocy.tech/2017/09/12/DetectingUselessCodeWithClang-p1/) > [iOS 启动速度优化和安装包优化简单总结](https://juejin.im/post/6844903821387235341) ## 二、数据结构与算法 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index c2fce2c5..b330dc61 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -44,6 +44,8 @@ * 42、[落影loyinglin](https://github.com/loyinglin) * 43、[阿毛的蛋疼地](https://xiangwangfeng.com/) * 44、[与佳期](gonghonglou.com) +* 45、[RoyCao](https://juejin.im/user/4019470241649550) +* 46、[gocy](https://blog.gocy.tech/) ## 高质量微信公众号 From 2f69dd6f482e8b495dd55d940b048f070869984e Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 19 Aug 2020 17:45:05 +0800 Subject: [PATCH 154/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 85c43644..ec5effbd 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -43,6 +43,7 @@ > [iOS Memory Deep Dive](https://www.jianshu.com/p/dad9f27e412e) > [iOS性能优化系列篇之“列表流畅度优化”](https://juejin.im/post/6844903656769208334) > [iOS瘦身之道](https://juejin.im/post/6844903845340921869) +> [iOS应用瘦身总结](https://juejin.im/post/6844903849732341774) > [如何使用 Clang Plugin 找到项目中的无用代码](https://blog.gocy.tech/2017/09/12/DetectingUselessCodeWithClang-p1/) > [iOS 启动速度优化和安装包优化简单总结](https://juejin.im/post/6844903821387235341) From c837a4fa89c4c9f0aeee20c816f1c85e69a435be Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 20 Aug 2020 18:32:06 +0800 Subject: [PATCH 155/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 14 ++++++ .../WorkIssues/SLWorkIssuesViewController.m | 11 +++-- .../SLUnusedResourceViewController.h" | 18 ++++++++ .../SLUnusedResourceViewController.m" | 46 +++++++++++++++++++ .../WorkIssues/\347\254\224\350\256\260.md" | 28 +++++------ 5 files changed, 100 insertions(+), 17 deletions(-) create mode 100644 "iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.h" create mode 100644 "iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 04d15709..a227319b 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -97,6 +97,7 @@ 7869C72324A8B6D200527546 /* SLPictureTransitionAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 7869C72124A8B6D200527546 /* SLPictureTransitionAnimation.m */; }; 78777CE0238FEA48006FA671 /* SLOpenGLController.m in Sources */ = {isa = PBXBuildFile; fileRef = 78777CDF238FEA48006FA671 /* SLOpenGLController.m */; }; 78777CE6238FF65C006FA671 /* SLDelayPerform.m in Sources */ = {isa = PBXBuildFile; fileRef = 78777CE5238FF65C006FA671 /* SLDelayPerform.m */; }; + 78799EA224EE7EEC00DA8C7A /* SLUnusedResourceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 78799EA124EE7EEC00DA8C7A /* SLUnusedResourceViewController.m */; }; 787C7DBE245D74E4005DF7ED /* NSMutableArray+SLCrashProtector.m in Sources */ = {isa = PBXBuildFile; fileRef = 787C7DB2245D74E3005DF7ED /* NSMutableArray+SLCrashProtector.m */; }; 787C7DBF245D74E4005DF7ED /* NSMutableDictionary+SLCrashProtector.m in Sources */ = {isa = PBXBuildFile; fileRef = 787C7DB3245D74E3005DF7ED /* NSMutableDictionary+SLCrashProtector.m */; }; 787C7DC0245D74E4005DF7ED /* NSDictionary+SLCrashProtector.m in Sources */ = {isa = PBXBuildFile; fileRef = 787C7DB5245D74E3005DF7ED /* NSDictionary+SLCrashProtector.m */; }; @@ -338,6 +339,8 @@ 78777CDF238FEA48006FA671 /* SLOpenGLController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLOpenGLController.m; sourceTree = ""; }; 78777CE4238FF65C006FA671 /* SLDelayPerform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLDelayPerform.h; sourceTree = ""; }; 78777CE5238FF65C006FA671 /* SLDelayPerform.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLDelayPerform.m; sourceTree = ""; }; + 78799EA024EE7EEC00DA8C7A /* SLUnusedResourceViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLUnusedResourceViewController.h; sourceTree = ""; }; + 78799EA124EE7EEC00DA8C7A /* SLUnusedResourceViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLUnusedResourceViewController.m; sourceTree = ""; }; 787C7DB2245D74E3005DF7ED /* NSMutableArray+SLCrashProtector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableArray+SLCrashProtector.m"; sourceTree = ""; }; 787C7DB3245D74E3005DF7ED /* NSMutableDictionary+SLCrashProtector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableDictionary+SLCrashProtector.m"; sourceTree = ""; }; 787C7DB4245D74E3005DF7ED /* NSString+SLCrashProtector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+SLCrashProtector.h"; sourceTree = ""; }; @@ -869,6 +872,15 @@ path = "设计模式"; sourceTree = ""; }; + 78799E9F24EE7E7F00DA8C7A /* 查找项目无用资源 */ = { + isa = PBXGroup; + children = ( + 78799EA024EE7EEC00DA8C7A /* SLUnusedResourceViewController.h */, + 78799EA124EE7EEC00DA8C7A /* SLUnusedResourceViewController.m */, + ); + path = "查找项目无用资源"; + sourceTree = ""; + }; 78842455248F92D400C2E505 /* AVFoundation */ = { isa = PBXGroup; children = ( @@ -899,6 +911,7 @@ 784C4C6D24C5B4F500D5C199 /* 笔记.md */, 7884247D2492102900C2E505 /* SLWorkIssuesViewController.h */, 7884247E2492102900C2E505 /* SLWorkIssuesViewController.m */, + 78799E9F24EE7E7F00DA8C7A /* 查找项目无用资源 */, 784C4BDE24BC409600D5C199 /* APM */, 7811F76C24B2C70D000AA044 /* 二进制重排 */, 78EF8B5C24162B07008D0CD7 /* UIMenuController */, @@ -1518,6 +1531,7 @@ 7869C72324A8B6D200527546 /* SLPictureTransitionAnimation.m in Sources */, 78E179372351A40D0007E4BB /* SLShotFocusView.m in Sources */, 787C7DC8245D77D9005DF7ED /* SLZombieCatcher.m in Sources */, + 78799EA224EE7EEC00DA8C7A /* SLUnusedResourceViewController.m in Sources */, 78A4BD45236C5DF20021AE32 /* SLEditVideoController.m in Sources */, 78B10485232F57C30051579F /* SceneDelegate.m in Sources */, 783FB45C2394A4E10039AEFD /* SLShaderLanguageViewController.m in Sources */, diff --git a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m index a5effb68..f0a822bc 100644 --- a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m @@ -11,6 +11,7 @@ #import "SLWebViewController.h" #import "SLBinaryResetViewController.h" #import "SLAPMViewController.h" +#import "SLUnusedResourceViewController.h" @interface SLWorkIssuesViewController () @property (nonatomic, strong) NSMutableArray *titlesArray; @@ -51,7 +52,8 @@ - (void)getData { @"iOS 传感器集锦", @"iOS 自定义转场动画", @"二进制重排优化启动时间", - @"iOS APM应用性能监控管理(doing)"]]; + @"iOS APM应用性能监控管理(doing)", + @"ipa瘦身之查找无用图片资源"]]; [self.urlArray addObjectsFromArray:@[@"", @"https://juejin.im/post/5c0e1e73f265da616413d828", @"https://juejin.im/post/5c0e1df95188250d2722a3bc", @@ -59,7 +61,8 @@ - (void)getData { @"https://juejin.im/post/5c088a1051882517165dd15d", @"https://juejin.im/post/5c088ba36fb9a049fb43737b", @"二进制重排", - @"APM"]]; + @"APM", + @"ipa瘦身"]]; [self.classArray addObjectsFromArray:@[[SLMenuViewController class], [SLWebViewController class], [SLWebViewController class], @@ -67,7 +70,8 @@ - (void)getData { [SLWebViewController class], [SLWebViewController class], [SLBinaryResetViewController class], - [SLAPMViewController class]]]; + [SLAPMViewController class], + [SLUnusedResourceViewController class]]]; [self.tableView reloadData]; } @@ -105,6 +109,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath [tableView deselectRowAtIndexPath:indexPath animated:NO]; UIViewController *nextVc = [[self.classArray[indexPath.row] alloc] init]; NSString *urlString = self.urlArray[indexPath.row]; + nextVc.navigationItem.title = self.titlesArray[indexPath.row]; switch (indexPath.row) { default: if (urlString.length > 0 && [urlString hasPrefix:@"http"]) { diff --git "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.h" "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.h" new file mode 100644 index 00000000..36c94e88 --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.h" @@ -0,0 +1,18 @@ +// +// SLUnusedResourceViewController.h +// DarkMode +// +// Created by wsl on 2020/8/20. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +///查找项目无用资源 +@interface SLUnusedResourceViewController : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" new file mode 100644 index 00000000..76d76c9a --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" @@ -0,0 +1,46 @@ +// +// SLUnusedResourceViewController.m +// DarkMode +// +// Created by wsl on 2020/8/20. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLUnusedResourceViewController.h" + +@interface SLUnusedResourceViewController () + +@end + +@implementation SLUnusedResourceViewController + +#pragma mark - Override +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor whiteColor]; + + +} + +#pragma mark - UI + +#pragma mark - Data + +#pragma mark - Getter + +#pragma mark - HelpMethods + +#pragma mark - EventsHandle + + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index ec5effbd..b7f35103 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -31,20 +31,20 @@ * 1.7、安全性 -> 资料 -> [iOS-Performance-Optimization](https://github.com/skyming/iOS-Performance-Optimization) -> [DoraemonKit](https://github.com/didi/DoraemonKit/blob/master/README_CN.md) -> [乐少](https://www.jianshu.com/u/9c51a213b02e) -> [iOS 性能监控(三)—— 方法耗时监控](https://www.jianshu.com/p/bc1c000afdba) -> [iOS crash 日志堆栈解析](https://juejin.im/post/6844903598011187213) -> [iOS崩溃crash大解析](https://www.jianshu.com/p/1b804426d212) -> [iOS Memory 内存详解 (长文)](https://juejin.im/post/6844903902169710600) -> [iOS 性能优化调试](https://www.jianshu.com/c/fcb00b489a85) -> [iOS Memory Deep Dive](https://www.jianshu.com/p/dad9f27e412e) -> [iOS性能优化系列篇之“列表流畅度优化”](https://juejin.im/post/6844903656769208334) -> [iOS瘦身之道](https://juejin.im/post/6844903845340921869) -> [iOS应用瘦身总结](https://juejin.im/post/6844903849732341774) -> [如何使用 Clang Plugin 找到项目中的无用代码](https://blog.gocy.tech/2017/09/12/DetectingUselessCodeWithClang-p1/) +> 资料 +> [iOS-Performance-Optimization](https://github.com/skyming/iOS-Performance-Optimization) +> [DoraemonKit](https://github.com/didi/DoraemonKit/blob/master/README_CN.md) +> [乐少](https://www.jianshu.com/u/9c51a213b02e) +> [iOS 性能监控(三)—— 方法耗时监控](https://www.jianshu.com/p/bc1c000afdba) +> [iOS crash 日志堆栈解析](https://juejin.im/post/6844903598011187213) +> [iOS崩溃crash大解析](https://www.jianshu.com/p/1b804426d212) +> [iOS Memory 内存详解 (长文)](https://juejin.im/post/6844903902169710600) +> [iOS 性能优化调试](https://www.jianshu.com/c/fcb00b489a85) +> [iOS Memory Deep Dive](https://www.jianshu.com/p/dad9f27e412e) +> [iOS性能优化系列篇之“列表流畅度优化”](https://juejin.im/post/6844903656769208334) +> [iOS瘦身之道](https://juejin.im/post/6844903845340921869) +> [iOS应用瘦身总结](https://juejin.im/post/6844903849732341774) +> [如何使用 Clang Plugin 找到项目中的无用代码](https://blog.gocy.tech/2017/09/12/DetectingUselessCodeWithClang-p1/) > [iOS 启动速度优化和安装包优化简单总结](https://juejin.im/post/6844903821387235341) ## 二、数据结构与算法 From 2f721b13abd3f5d6171df0d87a8d007157c29082 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 20 Aug 2020 19:01:26 +0800 Subject: [PATCH 156/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SLUnusedResourceViewController.m" | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" index 76d76c9a..efe0bf0c 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" @@ -8,6 +8,10 @@ #import "SLUnusedResourceViewController.h" +/* 资料: + https://www.jianshu.com/p/cef2f6becbe6 + https://github.com/tinymind/LSUnusedResources +*/ @interface SLUnusedResourceViewController () @end @@ -19,6 +23,7 @@ - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; + [self test]; } @@ -30,6 +35,13 @@ - (void)viewDidLoad { #pragma mark - HelpMethods +- (void)test { + + + + +} + #pragma mark - EventsHandle From 3cef18578c83fabcedb09f5a7031eec219fd8821 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 21 Aug 2020 18:54:21 +0800 Subject: [PATCH 157/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/.DS_Store | Bin 10244 -> 10244 bytes iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 6 ++ .../SLResourceInfo.h" | 28 +++++++ .../SLResourceInfo.m" | 13 ++++ .../SLUnusedResourceViewController.m" | 70 +++++++++++++----- 5 files changed, 100 insertions(+), 17 deletions(-) create mode 100644 "iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLResourceInfo.h" create mode 100644 "iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLResourceInfo.m" diff --git a/iOS_Tips/.DS_Store b/iOS_Tips/.DS_Store index ca771eb506401f4ca3bae678af430abd16b41d85..a974884ba5ff36efe8aeac7d0c23d2fed1031529 100644 GIT binary patch delta 54 zcmZn(XbIS0CBbBTY4QPa4S|9T!{Frn+yVv=U`k+^yg@=|@&XAyrklM$rX>@*z~^Gh0U)e GB>4fiSP)bI diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index a227319b..f3dfd9f8 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -98,6 +98,7 @@ 78777CE0238FEA48006FA671 /* SLOpenGLController.m in Sources */ = {isa = PBXBuildFile; fileRef = 78777CDF238FEA48006FA671 /* SLOpenGLController.m */; }; 78777CE6238FF65C006FA671 /* SLDelayPerform.m in Sources */ = {isa = PBXBuildFile; fileRef = 78777CE5238FF65C006FA671 /* SLDelayPerform.m */; }; 78799EA224EE7EEC00DA8C7A /* SLUnusedResourceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 78799EA124EE7EEC00DA8C7A /* SLUnusedResourceViewController.m */; }; + 78799EAB24EFC60C00DA8C7A /* SLResourceInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 78799EAA24EFC60C00DA8C7A /* SLResourceInfo.m */; }; 787C7DBE245D74E4005DF7ED /* NSMutableArray+SLCrashProtector.m in Sources */ = {isa = PBXBuildFile; fileRef = 787C7DB2245D74E3005DF7ED /* NSMutableArray+SLCrashProtector.m */; }; 787C7DBF245D74E4005DF7ED /* NSMutableDictionary+SLCrashProtector.m in Sources */ = {isa = PBXBuildFile; fileRef = 787C7DB3245D74E3005DF7ED /* NSMutableDictionary+SLCrashProtector.m */; }; 787C7DC0245D74E4005DF7ED /* NSDictionary+SLCrashProtector.m in Sources */ = {isa = PBXBuildFile; fileRef = 787C7DB5245D74E3005DF7ED /* NSDictionary+SLCrashProtector.m */; }; @@ -341,6 +342,8 @@ 78777CE5238FF65C006FA671 /* SLDelayPerform.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLDelayPerform.m; sourceTree = ""; }; 78799EA024EE7EEC00DA8C7A /* SLUnusedResourceViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLUnusedResourceViewController.h; sourceTree = ""; }; 78799EA124EE7EEC00DA8C7A /* SLUnusedResourceViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLUnusedResourceViewController.m; sourceTree = ""; }; + 78799EA924EFC60C00DA8C7A /* SLResourceInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLResourceInfo.h; sourceTree = ""; }; + 78799EAA24EFC60C00DA8C7A /* SLResourceInfo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLResourceInfo.m; sourceTree = ""; }; 787C7DB2245D74E3005DF7ED /* NSMutableArray+SLCrashProtector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableArray+SLCrashProtector.m"; sourceTree = ""; }; 787C7DB3245D74E3005DF7ED /* NSMutableDictionary+SLCrashProtector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableDictionary+SLCrashProtector.m"; sourceTree = ""; }; 787C7DB4245D74E3005DF7ED /* NSString+SLCrashProtector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+SLCrashProtector.h"; sourceTree = ""; }; @@ -877,6 +880,8 @@ children = ( 78799EA024EE7EEC00DA8C7A /* SLUnusedResourceViewController.h */, 78799EA124EE7EEC00DA8C7A /* SLUnusedResourceViewController.m */, + 78799EA924EFC60C00DA8C7A /* SLResourceInfo.h */, + 78799EAA24EFC60C00DA8C7A /* SLResourceInfo.m */, ); path = "查找项目无用资源"; sourceTree = ""; @@ -1556,6 +1561,7 @@ 787C7DD22462C5F3005DF7ED /* UIViewController+SLMLeakFinder.m in Sources */, 788ADB382441F48F00302CD9 /* SLCrashViewController.m in Sources */, 78DAA1162360256200A60F64 /* SLEditSelectedBox.m in Sources */, + 78799EAB24EFC60C00DA8C7A /* SLResourceInfo.m in Sources */, 787C7DCC2462ADE5005DF7ED /* NSObject+SLMLeakFinder.m in Sources */, 78E72D792480B36800751373 /* SLScrollViewController.m in Sources */, 782CFB20239DEA05001B5528 /* SLSplitScreenCell.m in Sources */, diff --git "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLResourceInfo.h" "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLResourceInfo.h" new file mode 100644 index 00000000..a241dc59 --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLResourceInfo.h" @@ -0,0 +1,28 @@ +// +// SLResourceInfo.h +// DarkMode +// +// Created by wsl on 2020/8/21. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface SLResourceInfo : NSObject + +///文件路径 +@property (nonatomic, copy) NSString *fileName; +///文件路径 +@property (nonatomic, copy) NSString *filePath; +///文件大小 +@property (nonatomic, assign) CGFloat fileSize; +/// 是否为文件夹 +@property (nonatomic, assign) BOOL isFolder; +/// 文件类型 +@property (nonatomic, copy) NSString *fileType; + +@end + +NS_ASSUME_NONNULL_END diff --git "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLResourceInfo.m" "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLResourceInfo.m" new file mode 100644 index 00000000..4aa0107c --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLResourceInfo.m" @@ -0,0 +1,13 @@ +// +// SLResourceInfo.m +// DarkMode +// +// Created by wsl on 2020/8/21. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLResourceInfo.h" + +@implementation SLResourceInfo + +@end diff --git "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" index efe0bf0c..9e9e9b26 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" @@ -7,11 +7,13 @@ // #import "SLUnusedResourceViewController.h" +#import "SLResourceInfo.h" /* 资料: - https://www.jianshu.com/p/cef2f6becbe6 - https://github.com/tinymind/LSUnusedResources -*/ + https://www.jianshu.com/p/cef2f6becbe6 + https://github.com/tinymind/LSUnusedResources + https://www.jianshu.com/p/b25b05ef170d + */ @interface SLUnusedResourceViewController () @end @@ -22,8 +24,8 @@ @implementation SLUnusedResourceViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; - - [self test]; + + [self searchUnderFilePath:@"/Users/wsl/GitHub/iOS_Tips/iOS_Tips/DarkMode" fileTypes:@"jpeg|jpg|png|gif|imageset"]; } @@ -35,24 +37,58 @@ - (void)viewDidLoad { #pragma mark - HelpMethods -- (void)test { - - - +/// 在FilePath路径下搜索所有suffixs类型的文件 +/// @param searchPath 搜索路径 +/// @param suffixs 文件后缀/格式 多种格式用|隔开即可 例如@"jpeg|jpg|png|gif|imageset" +- (void)searchUnderFilePath:(NSString *)searchPath fileTypes:(NSString *)suffixs{ + NSArray *filesArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:searchPath error:nil] ; + NSEnumerator *filesEnumerator = [filesArray objectEnumerator]; + filesArray = nil; + NSMutableArray *resourceInfos = [NSMutableArray array]; + //相对于searchPath的子路径 + NSString *subPath; + while (subPath = [filesEnumerator nextObject]) { + @autoreleasepool { + //匹配对象 + NSString *fileName = subPath.lastPathComponent; + //匹配规则 + NSString *regularExpStr = [@"[a-zA-Z0-9_-]*\\." stringByAppendingFormat:@"%@", suffixs]; + // NSString *regularExpStr = @"([a-zA-Z0-9_-]*)\\.m"; + NSRegularExpression *regularExp = [[NSRegularExpression alloc] initWithPattern:regularExpStr options:NSRegularExpressionCaseInsensitive error:nil]; + NSArray *resultArr = [regularExp matchesInString:fileName options:NSMatchingReportProgress range:NSMakeRange(0, fileName.length)]; + if(resultArr.count == 0) continue; + //取出匹配出来的字符串 + NSString *subStr = [fileName substringWithRange:resultArr.firstObject.range]; + NSLog(@"%@",subStr); + + //全路径 + NSString *fullPath = [searchPath stringByAppendingPathComponent:subPath]; + //文件属性信息 + NSDictionary *fileDic = [[NSFileManager defaultManager] attributesOfItemAtPath:fullPath error:nil]; + + SLResourceInfo *info = [[SLResourceInfo alloc] init]; + info.filePath = fullPath; + info.fileSize = [fileDic fileSize]; + info.isFolder = [[fileDic fileType] isEqualToString:@"NSFileTypeDirectory"] ? YES : NO; + info.fileName = fileName; + [resourceInfos addObject:info]; + } + } } + #pragma mark - EventsHandle /* -#pragma mark - Navigation - -// In a storyboard-based application, you will often want to do a little preparation before navigation -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - // Get the new view controller using [segue destinationViewController]. - // Pass the selected object to the new view controller. -} -*/ + #pragma mark - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. + } + */ @end From eb5997297601e092ce5851d26b67729a371a4e20 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 21 Aug 2020 19:12:53 +0800 Subject: [PATCH 158/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 8 ++++++++ .../SLUnusedResourceViewController.m" | 5 +++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index f3dfd9f8..de72fd63 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -878,6 +878,7 @@ 78799E9F24EE7E7F00DA8C7A /* 查找项目无用资源 */ = { isa = PBXGroup; children = ( + 78799EAC24EFE1B400DA8C7A /* png */, 78799EA024EE7EEC00DA8C7A /* SLUnusedResourceViewController.h */, 78799EA124EE7EEC00DA8C7A /* SLUnusedResourceViewController.m */, 78799EA924EFC60C00DA8C7A /* SLResourceInfo.h */, @@ -886,6 +887,13 @@ path = "查找项目无用资源"; sourceTree = ""; }; + 78799EAC24EFE1B400DA8C7A /* png */ = { + isa = PBXGroup; + children = ( + ); + path = png; + sourceTree = ""; + }; 78842455248F92D400C2E505 /* AVFoundation */ = { isa = PBXGroup; children = ( diff --git "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" index 9e9e9b26..013ca843 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" @@ -12,7 +12,7 @@ /* 资料: https://www.jianshu.com/p/cef2f6becbe6 https://github.com/tinymind/LSUnusedResources - https://www.jianshu.com/p/b25b05ef170d + http://www.regexlab.com/zh/regref.htm */ @interface SLUnusedResourceViewController () @@ -51,6 +51,7 @@ - (void)searchUnderFilePath:(NSString *)searchPath fileTypes:(NSString *)suffixs @autoreleasepool { //匹配对象 NSString *fileName = subPath.lastPathComponent; + // fileName = subPath; //匹配规则 NSString *regularExpStr = [@"[a-zA-Z0-9_-]*\\." stringByAppendingFormat:@"%@", suffixs]; // NSString *regularExpStr = @"([a-zA-Z0-9_-]*)\\.m"; @@ -59,7 +60,7 @@ - (void)searchUnderFilePath:(NSString *)searchPath fileTypes:(NSString *)suffixs if(resultArr.count == 0) continue; //取出匹配出来的字符串 NSString *subStr = [fileName substringWithRange:resultArr.firstObject.range]; - NSLog(@"%@",subStr); + NSLog(@"%@",fileName); //全路径 NSString *fullPath = [searchPath stringByAppendingPathComponent:subPath]; From 4c54a4c0541a9c61a68cd0175e2806c50af5e034 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 21 Aug 2020 19:21:49 +0800 Subject: [PATCH 159/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SLUnusedResourceViewController.m" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" index 013ca843..3ec135d8 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" @@ -12,7 +12,7 @@ /* 资料: https://www.jianshu.com/p/cef2f6becbe6 https://github.com/tinymind/LSUnusedResources - http://www.regexlab.com/zh/regref.htm + https://www.runoob.com/regexp/regexp-tutorial.html */ @interface SLUnusedResourceViewController () From 18894be2d174f0191c6540a95c761fa5302b2aa9 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 21 Aug 2020 19:25:08 +0800 Subject: [PATCH 160/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SLUnusedResourceViewController.m" | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" index 3ec135d8..e0efd38a 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" @@ -12,7 +12,8 @@ /* 资料: https://www.jianshu.com/p/cef2f6becbe6 https://github.com/tinymind/LSUnusedResources - https://www.runoob.com/regexp/regexp-tutorial.html + 正则表达式入门:https://www.runoob.com/regexp/regexp-tutorial.html + 正则表达式在线工具: https://tool.oschina.net/regex/ */ @interface SLUnusedResourceViewController () From 218ff5b548bbf8bc06d96d39037045fdbd5b0b07 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 21 Aug 2020 19:27:03 +0800 Subject: [PATCH 161/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SLUnusedResourceViewController.m" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" index e0efd38a..9b608e8e 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" @@ -26,7 +26,7 @@ - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; - [self searchUnderFilePath:@"/Users/wsl/GitHub/iOS_Tips/iOS_Tips/DarkMode" fileTypes:@"jpeg|jpg|png|gif|imageset"]; + [self searchAllUnderFilePath:@"/Users/wsl/GitHub/iOS_Tips/iOS_Tips/DarkMode" fileTypes:@"jpeg|jpg|png|gif|imageset"]; } @@ -41,7 +41,7 @@ - (void)viewDidLoad { /// 在FilePath路径下搜索所有suffixs类型的文件 /// @param searchPath 搜索路径 /// @param suffixs 文件后缀/格式 多种格式用|隔开即可 例如@"jpeg|jpg|png|gif|imageset" -- (void)searchUnderFilePath:(NSString *)searchPath fileTypes:(NSString *)suffixs{ +- (void)searchAllUnderFilePath:(NSString *)searchPath fileTypes:(NSString *)suffixs{ NSArray *filesArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:searchPath error:nil] ; NSEnumerator *filesEnumerator = [filesArray objectEnumerator]; filesArray = nil; From b8fa52faaa29770a456625935cfb30bf96e01e69 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sat, 22 Aug 2020 14:34:28 +0800 Subject: [PATCH 162/356] =?UTF-8?q?=E6=AD=A3=E5=88=99=E8=A1=A8=E8=BE=BE?= =?UTF-8?q?=E5=BC=8F=E5=8C=B9=E9=85=8D=E5=9B=BE=E7=89=87=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m | 2 +- .../SLUnusedResourceViewController.m" | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m index f0a822bc..bfe1b12d 100644 --- a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m @@ -53,7 +53,7 @@ - (void)getData { @"iOS 自定义转场动画", @"二进制重排优化启动时间", @"iOS APM应用性能监控管理(doing)", - @"ipa瘦身之查找无用图片资源"]]; + @"ipa瘦身之查找无用图片资源(doing)"]]; [self.urlArray addObjectsFromArray:@[@"", @"https://juejin.im/post/5c0e1e73f265da616413d828", @"https://juejin.im/post/5c0e1df95188250d2722a3bc", diff --git "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" index 9b608e8e..70162b82 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" @@ -12,7 +12,7 @@ /* 资料: https://www.jianshu.com/p/cef2f6becbe6 https://github.com/tinymind/LSUnusedResources - 正则表达式入门:https://www.runoob.com/regexp/regexp-tutorial.html + 正则表达式入门:http://www.regexlab.com/zh/regref.htm 正则表达式在线工具: https://tool.oschina.net/regex/ */ @interface SLUnusedResourceViewController () @@ -54,14 +54,14 @@ - (void)searchAllUnderFilePath:(NSString *)searchPath fileTypes:(NSString *)suff NSString *fileName = subPath.lastPathComponent; // fileName = subPath; //匹配规则 - NSString *regularExpStr = [@"[a-zA-Z0-9_-]*\\." stringByAppendingFormat:@"%@", suffixs]; + NSString *regularExpStr = [NSString stringWithFormat:@"[a-zA-Z0-9_-]*(@[23]x)?\\.(%@)",suffixs]; // NSString *regularExpStr = @"([a-zA-Z0-9_-]*)\\.m"; NSRegularExpression *regularExp = [[NSRegularExpression alloc] initWithPattern:regularExpStr options:NSRegularExpressionCaseInsensitive error:nil]; NSArray *resultArr = [regularExp matchesInString:fileName options:NSMatchingReportProgress range:NSMakeRange(0, fileName.length)]; if(resultArr.count == 0) continue; //取出匹配出来的字符串 - NSString *subStr = [fileName substringWithRange:resultArr.firstObject.range]; - NSLog(@"%@",fileName); +// NSString *subStr = [fileName substringWithRange:resultArr.firstObject.range]; +// NSLog(@"%@",subStr); //全路径 NSString *fullPath = [searchPath stringByAppendingPathComponent:subPath]; From 4445332788bad0618d5439d42641f230fe10aacc Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sat, 22 Aug 2020 18:56:53 +0800 Subject: [PATCH 163/356] =?UTF-8?q?iPA=E7=98=A6=E8=BA=AB=E4=B9=8B=E6=9F=A5?= =?UTF-8?q?=E6=89=BE=E6=97=A0=E7=94=A8=E8=B5=84=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 12 +- .../SmallVideo/View/SLMosaicView.m | 4 +- .../WorkIssues/SLWorkIssuesViewController.m | 2 +- .../SLUnusedResourceViewController.h" | 4 +- .../SLUnusedResourceViewController.m" | 131 +++++++++++++++--- .../unused.png" | Bin 0 -> 82125 bytes 6 files changed, 119 insertions(+), 34 deletions(-) create mode 100644 "iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/unused.png" diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index de72fd63..c533e717 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -99,6 +99,7 @@ 78777CE6238FF65C006FA671 /* SLDelayPerform.m in Sources */ = {isa = PBXBuildFile; fileRef = 78777CE5238FF65C006FA671 /* SLDelayPerform.m */; }; 78799EA224EE7EEC00DA8C7A /* SLUnusedResourceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 78799EA124EE7EEC00DA8C7A /* SLUnusedResourceViewController.m */; }; 78799EAB24EFC60C00DA8C7A /* SLResourceInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 78799EAA24EFC60C00DA8C7A /* SLResourceInfo.m */; }; + 78799EB224F1027300DA8C7A /* unused.png in Resources */ = {isa = PBXBuildFile; fileRef = 78799EB124F1027300DA8C7A /* unused.png */; }; 787C7DBE245D74E4005DF7ED /* NSMutableArray+SLCrashProtector.m in Sources */ = {isa = PBXBuildFile; fileRef = 787C7DB2245D74E3005DF7ED /* NSMutableArray+SLCrashProtector.m */; }; 787C7DBF245D74E4005DF7ED /* NSMutableDictionary+SLCrashProtector.m in Sources */ = {isa = PBXBuildFile; fileRef = 787C7DB3245D74E3005DF7ED /* NSMutableDictionary+SLCrashProtector.m */; }; 787C7DC0245D74E4005DF7ED /* NSDictionary+SLCrashProtector.m in Sources */ = {isa = PBXBuildFile; fileRef = 787C7DB5245D74E3005DF7ED /* NSDictionary+SLCrashProtector.m */; }; @@ -344,6 +345,7 @@ 78799EA124EE7EEC00DA8C7A /* SLUnusedResourceViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLUnusedResourceViewController.m; sourceTree = ""; }; 78799EA924EFC60C00DA8C7A /* SLResourceInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLResourceInfo.h; sourceTree = ""; }; 78799EAA24EFC60C00DA8C7A /* SLResourceInfo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLResourceInfo.m; sourceTree = ""; }; + 78799EB124F1027300DA8C7A /* unused.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = unused.png; sourceTree = ""; }; 787C7DB2245D74E3005DF7ED /* NSMutableArray+SLCrashProtector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableArray+SLCrashProtector.m"; sourceTree = ""; }; 787C7DB3245D74E3005DF7ED /* NSMutableDictionary+SLCrashProtector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableDictionary+SLCrashProtector.m"; sourceTree = ""; }; 787C7DB4245D74E3005DF7ED /* NSString+SLCrashProtector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+SLCrashProtector.h"; sourceTree = ""; }; @@ -878,7 +880,7 @@ 78799E9F24EE7E7F00DA8C7A /* 查找项目无用资源 */ = { isa = PBXGroup; children = ( - 78799EAC24EFE1B400DA8C7A /* png */, + 78799EB124F1027300DA8C7A /* unused.png */, 78799EA024EE7EEC00DA8C7A /* SLUnusedResourceViewController.h */, 78799EA124EE7EEC00DA8C7A /* SLUnusedResourceViewController.m */, 78799EA924EFC60C00DA8C7A /* SLResourceInfo.h */, @@ -887,13 +889,6 @@ path = "查找项目无用资源"; sourceTree = ""; }; - 78799EAC24EFE1B400DA8C7A /* png */ = { - isa = PBXGroup; - children = ( - ); - path = png; - sourceTree = ""; - }; 78842455248F92D400C2E505 /* AVFoundation */ = { isa = PBXGroup; children = ( @@ -1377,6 +1372,7 @@ 782CFB6D239E69F3001B5528 /* Scale.fsh in Resources */, 782CFB71239E69FA001B5528 /* Shake.vsh in Resources */, 78B1048B232F57C30051579F /* Main.storyboard in Resources */, + 78799EB224F1027300DA8C7A /* unused.png in Resources */, 782CFB27239DFD89001B5528 /* SplitScreen_1.fsh in Resources */, 783FB4612394A76B0039AEFD /* shaderf.fsh in Resources */, 7811F7AD24B32A1E000AA044 /* Write Link Map File.png in Resources */, diff --git a/iOS_Tips/DarkMode/AVFoundation/SmallVideo/View/SLMosaicView.m b/iOS_Tips/DarkMode/AVFoundation/SmallVideo/View/SLMosaicView.m index 41287848..770323ca 100644 --- a/iOS_Tips/DarkMode/AVFoundation/SmallVideo/View/SLMosaicView.m +++ b/iOS_Tips/DarkMode/AVFoundation/SmallVideo/View/SLMosaicView.m @@ -207,7 +207,7 @@ - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { } else if (self.mosaicType == SLMosaicTypePaintbrush) { SLMosaicPointElement *blur = [ SLMosaicPointElement new]; blur.rect = CGRectMake(point.x-self.paintSize.width/2, point.y-self.paintSize.height/2, self.paintSize.width, self.paintSize.height); - blur.imageName = @"EditMosaicBrush.png"; + blur.imageName = @"EditMosaicBrush"; blur.color = self.brushColor ? self.brushColor(blur.rect.origin) : nil; SLMosaicLineLayer *layer = [SLMosaicLineLayer layer]; layer.frame = self.bounds; @@ -257,7 +257,7 @@ - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { //2、创建LFSplashBlur SLMosaicPointElement *blur = [SLMosaicPointElement new]; - blur.imageName = @"EditMosaicBrush.png"; + blur.imageName = @"EditMosaicBrush"; blur.color = self.brushColor ? self.brushColor(point) : nil; /** 新增随机位置 */ int x = self.paintSize.width + MIN(1, (int)(self.paintSize.width*0.4)); diff --git a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m index bfe1b12d..7526bc10 100644 --- a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m @@ -53,7 +53,7 @@ - (void)getData { @"iOS 自定义转场动画", @"二进制重排优化启动时间", @"iOS APM应用性能监控管理(doing)", - @"ipa瘦身之查找无用图片资源(doing)"]]; + @"ipa瘦身之查找无用资源"]]; [self.urlArray addObjectsFromArray:@[@"", @"https://juejin.im/post/5c0e1e73f265da616413d828", @"https://juejin.im/post/5c0e1df95188250d2722a3bc", diff --git "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.h" "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.h" index 36c94e88..612155cd 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.h" +++ "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.h" @@ -10,8 +10,8 @@ NS_ASSUME_NONNULL_BEGIN -///查找项目无用资源 -@interface SLUnusedResourceViewController : UIViewController +///查找项目无用的图片、类等文件资源, 此示例主要针对于此项目中的图片资源,其他类型资源实现原理相同 +@interface SLUnusedResourceViewController : UITableViewController @end diff --git "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" index 70162b82..f43971de 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" @@ -16,7 +16,7 @@ 正则表达式在线工具: https://tool.oschina.net/regex/ */ @interface SLUnusedResourceViewController () - +@property (nonatomic, strong) NSMutableArray *dataSource; @end @implementation SLUnusedResourceViewController @@ -25,23 +25,105 @@ @implementation SLUnusedResourceViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; - - [self searchAllUnderFilePath:@"/Users/wsl/GitHub/iOS_Tips/iOS_Tips/DarkMode" fileTypes:@"jpeg|jpg|png|gif|imageset"]; - + [self setupUI]; + [self getUnusedResourceData]; } #pragma mark - UI +- (void)setupUI { + self.navigationController.navigationBar.translucent = YES; + self.tableView.estimatedRowHeight = 1; + self.navigationItem.title = @"正在查找无用图片..."; +} #pragma mark - Data +///获取没有用的图片信息 +- (void)getUnusedResourceData { + + //文件目录路径 + NSString *folderPath = @"/Users/wsl/GitHub/iOS_Tips/iOS_Tips/DarkMode"; + + NSString *imgTypes = @"jpeg|jpg|png|gif|imageset"; + NSString *imgExpression = [NSString stringWithFormat:@"([a-zA-Z0-9_-]*)(@[23]x)?\\.(%@)",imgTypes]; + NSMutableArray *imgResources = [self searchAllUnderFolderPath:folderPath fileTypes:imgTypes regularExpression:imgExpression]; + + NSString *fileTypes = @"h|m$|swift|xib|storyboard"; + NSString *fileExpression = [NSString stringWithFormat:@"([a-zA-Z0-9_-]*)(\\.)(%@)",fileTypes]; + NSMutableArray *files = [self searchAllUnderFolderPath:folderPath fileTypes:fileTypes regularExpression:fileExpression]; + + NSMutableArray *unusedImgs = [NSMutableArray array]; + dispatch_async(dispatch_get_global_queue(0, 0), ^{ + for (SLResourceInfo *imgInfo in imgResources) { + //其他文件中是否使用了该图片 + BOOL isUsed = NO; + for (SLResourceInfo *fileInfo in files) { + //文件内容 + NSString *content = [NSString stringWithContentsOfFile:fileInfo.filePath encoding:NSUTF8StringEncoding error:nil]; + if (content == nil) continue; + + /* + 文件类型、语法、用法等不同,匹配规则就不同,依项目情况而定 + @"@\"%@\"" 例 @"wsl" + @"@\"(%@)(\.(jpeg|jpg|png|gif))?\"" 例 @"wsl.png" + @"imageNamed:@\"(.+)\""; + @"(imageNamed|contentOfFile):@\"(.*)\"" + + @"image name=\"(.+?)\"" xib格式(.xib .storyboard) + (stickers_%d) + */ + //去掉.png等后缀 + NSString *imgName = [imgInfo.fileName stringByReplacingOccurrencesOfString:imgInfo.fileType withString:@""]; + NSRange range = [imgName rangeOfString:@"@"]; + if (range.length) { + //去掉 @2x @3x + imgName = [imgName stringByReplacingOccurrencesOfString:[imgName substringFromIndex:range.location] withString:@""]; + } + //匹配规则 + // NSString *regularExpStr = [NSString stringWithFormat:@"@\"(%@)\"",imgName]; + NSString *regularExpStr = [NSString stringWithFormat:@"@\"(%@)\"",imgName]; + NSRegularExpression *regularExp = [[NSRegularExpression alloc] initWithPattern:regularExpStr options:NSRegularExpressionCaseInsensitive error:nil]; + NSArray *resultArr = [regularExp matchesInString:content options:NSMatchingReportProgress range:NSMakeRange(0, content.length)]; + if(resultArr.count > 0){ + // 取出匹配出来的字符串 + NSString *subStr = [content substringWithRange:resultArr.firstObject.range]; + // NSLog(@"%@",subStr); + isUsed = YES; + break; + } + } + //没有使用过,加入无用待处理数组 + if (!isUsed) [unusedImgs addObject:imgInfo]; + } + + for (SLResourceInfo *unusedImg in unusedImgs) { + // NSLog(@"⚠️ 没用 %@", unusedImg.fileName); + } + + self.dataSource = unusedImgs; + SL_DISPATCH_ON_MAIN_THREAD(^{ + self.navigationItem.title = @"ipa瘦身之查找无用资源"; + [self.tableView reloadData]; + }); + + }); + +} #pragma mark - Getter +- (NSMutableArray *)dataSource { + if (!_dataSource) { + _dataSource = [NSMutableArray array]; + } + return _dataSource;; +} #pragma mark - HelpMethods -/// 在FilePath路径下搜索所有suffixs类型的文件 +/// 在searchPath路径下搜索所有suffixs类型的文件 /// @param searchPath 搜索路径 /// @param suffixs 文件后缀/格式 多种格式用|隔开即可 例如@"jpeg|jpg|png|gif|imageset" -- (void)searchAllUnderFilePath:(NSString *)searchPath fileTypes:(NSString *)suffixs{ +/// @param expression 正则表达式/匹配规则 +- (NSMutableArray *)searchAllUnderFolderPath:(NSString *)searchPath fileTypes:(NSString *)suffixs regularExpression:(NSString *)expression { NSArray *filesArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:searchPath error:nil] ; NSEnumerator *filesEnumerator = [filesArray objectEnumerator]; filesArray = nil; @@ -52,16 +134,15 @@ - (void)searchAllUnderFilePath:(NSString *)searchPath fileTypes:(NSString *)suff @autoreleasepool { //匹配对象 NSString *fileName = subPath.lastPathComponent; - // fileName = subPath; + //匹配规则 - NSString *regularExpStr = [NSString stringWithFormat:@"[a-zA-Z0-9_-]*(@[23]x)?\\.(%@)",suffixs]; - // NSString *regularExpStr = @"([a-zA-Z0-9_-]*)\\.m"; + NSString *regularExpStr = expression; NSRegularExpression *regularExp = [[NSRegularExpression alloc] initWithPattern:regularExpStr options:NSRegularExpressionCaseInsensitive error:nil]; NSArray *resultArr = [regularExp matchesInString:fileName options:NSMatchingReportProgress range:NSMakeRange(0, fileName.length)]; if(resultArr.count == 0) continue; //取出匹配出来的字符串 -// NSString *subStr = [fileName substringWithRange:resultArr.firstObject.range]; -// NSLog(@"%@",subStr); + // NSString *subStr = [fileName substringWithRange:resultArr.firstObject.range]; + // NSLog(@"%@",subStr); //全路径 NSString *fullPath = [searchPath stringByAppendingPathComponent:subPath]; @@ -73,24 +154,32 @@ - (void)searchAllUnderFilePath:(NSString *)searchPath fileTypes:(NSString *)suff info.fileSize = [fileDic fileSize]; info.isFolder = [[fileDic fileType] isEqualToString:@"NSFileTypeDirectory"] ? YES : NO; info.fileName = fileName; + info.fileType = [fileName substringFromIndex:[fileName rangeOfString:@"."].location]; [resourceInfos addObject:info]; } } - + return resourceInfos; } #pragma mark - EventsHandle -/* - #pragma mark - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - // Get the new view controller using [segue destinationViewController]. - // Pass the selected object to the new view controller. - } - */ +#pragma mark - UITableViewDelegate, UITableViewDataSource +- (NSInteger)tableView:(nonnull UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return self.dataSource.count; +} +- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath { + UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cellID"]; + if(!cell) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"cellID"]; + } + SLResourceInfo *info = self.dataSource[indexPath.row]; + cell.imageView.image = [UIImage imageWithContentsOfFile:info.filePath]; + cell.textLabel.text = info.fileName; + return cell; +} +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { +} @end diff --git "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/unused.png" "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/unused.png" new file mode 100644 index 0000000000000000000000000000000000000000..6bbf7c217030470be77af73c285421ec606a6a6a GIT binary patch literal 82125 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 z⁢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 Date: Sat, 22 Aug 2020 19:06:42 +0800 Subject: [PATCH 164/356] Update README.md --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2d77e323..bf5734a7 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,8 @@ >> 6.5、iOS 传感器集锦 >> 6.6、iOS 自定义转场动画 >> 6.7、二进制重排优化启动速度 ->> 6.8、iOS APM应用性能监控管理(doing) +>> 6.8、iOS APM应用性能监控管理(doing) +>> 6.9、ipa瘦身之扫描无用资源 > 7、[iOS Crash防护](#7-iOSCrash防护) > 8、[WKWebView相关](#8-WKWebView相关) @@ -129,6 +130,10 @@ > CPU占用率、内存/磁盘使用率、卡顿监控定位、Crash防护、线程数量监控、网络监控(TCP 建立连接时间 、DNS 时间、 SSL时间、首包时间、响应时间 、流量)、ViewController启动耗时监测 、load方法的耗时、方法执行耗时...... +#### 6.9、ipa瘦身之扫描无用资源 + +> 扫描项目中无用的图片、类等文件资源, 此示例主要针对于此项目中的图片资源,其他类型资源实现原理相同。 + ## 7-iOSCrash防护 > Crash防护内容涉及 NSArray/NSMutableArray、NSDictionary/NSMutableDictionary、NSString/NSMutableString、Unrecognized Selector、KVO、KVC 、异步线程刷新UI、野指针定位、内存泄漏/循环引用;主要是对常见易错的地方进行容错处理,避免崩溃,并保存出错时的函数调用栈,以方便快速定位代码,主要是利用的runtime和fishook知识。 From 22c657c9c51f61802b0f978746c2d171192625b6 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sat, 22 Aug 2020 19:08:55 +0800 Subject: [PATCH 165/356] =?UTF-8?q?IPA=E7=98=A6=E8=BA=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m | 2 +- .../SLUnusedResourceViewController.h" | 2 +- .../SLUnusedResourceViewController.m" | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m index 7526bc10..06c91aa7 100644 --- a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m @@ -53,7 +53,7 @@ - (void)getData { @"iOS 自定义转场动画", @"二进制重排优化启动时间", @"iOS APM应用性能监控管理(doing)", - @"ipa瘦身之查找无用资源"]]; + @"ipa瘦身之扫描无用资源"]]; [self.urlArray addObjectsFromArray:@[@"", @"https://juejin.im/post/5c0e1e73f265da616413d828", @"https://juejin.im/post/5c0e1df95188250d2722a3bc", diff --git "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.h" "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.h" index 612155cd..b51c88bf 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.h" +++ "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.h" @@ -10,7 +10,7 @@ NS_ASSUME_NONNULL_BEGIN -///查找项目无用的图片、类等文件资源, 此示例主要针对于此项目中的图片资源,其他类型资源实现原理相同 +///扫描项目无用的图片、类等文件资源, 此示例主要针对于此项目中的图片资源,其他类型资源实现原理相同 @interface SLUnusedResourceViewController : UITableViewController @end diff --git "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" index f43971de..72c9f577 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" @@ -33,7 +33,7 @@ - (void)viewDidLoad { - (void)setupUI { self.navigationController.navigationBar.translucent = YES; self.tableView.estimatedRowHeight = 1; - self.navigationItem.title = @"正在查找无用图片..."; + self.navigationItem.title = @"正在扫描无用图片..."; } #pragma mark - Data @@ -101,7 +101,7 @@ - (void)getUnusedResourceData { self.dataSource = unusedImgs; SL_DISPATCH_ON_MAIN_THREAD(^{ - self.navigationItem.title = @"ipa瘦身之查找无用资源"; + self.navigationItem.title = @"ipa瘦身之扫描无用资源"; [self.tableView reloadData]; }); From 8eb5e56ac7751cc8093d1cb4715e02b17ccee0c8 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 25 Aug 2020 19:42:06 +0800 Subject: [PATCH 166/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index b7f35103..7b6f2ccb 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -15,7 +15,7 @@ * 1.3、 安装包瘦身 -> 去掉无用资源、压缩资源、矢量图、编译选项优化、可执行文件瘦身 +> 去掉无用/重复资源、压缩资源、矢量图/图片格式、编译选项优化、可执行文件瘦身、如果不支持32位以及 iOS8 就去掉 armv7 、xcassets管理常用的、较小的图图片、大图放在 Bundle 内管理、静态库瘦身 * 1.4、启动时间优化 @@ -46,6 +46,7 @@ > [iOS应用瘦身总结](https://juejin.im/post/6844903849732341774) > [如何使用 Clang Plugin 找到项目中的无用代码](https://blog.gocy.tech/2017/09/12/DetectingUselessCodeWithClang-p1/) > [iOS 启动速度优化和安装包优化简单总结](https://juejin.im/post/6844903821387235341) +> [iOS代码瘦身实践:删除无用的类](https://juejin.im/post/6844903921169727496) ## 二、数据结构与算法 * 1、 [LeetcodeTop](https://github.com/afatcoder/LeetcodeTop) @@ -81,3 +82,5 @@ ## 其它 * 1、[CocoaPods 都做了什么?](https://www.jianshu.com/p/84936d9344ff) +* 2、[2. 整体把握 CocoaPods 核心组件](https://mp.weixin.qq.com/s/eyjrhPgPFdidPWO7t2SDcA) +* 3、[1. 版本管理工具及 Ruby 工具链环境](https://mp.weixin.qq.com/s/s2yJEb2P0_Kk-rIpYBi_9A) From a3bb4cbd4a2e4f62a930922641fff7f24b2c34ab Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 25 Aug 2020 19:45:24 +0800 Subject: [PATCH 167/356] =?UTF-8?q?IPA=E7=98=A6=E8=BA=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SLUnusedResourceViewController.m" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" index 72c9f577..339fc0ee 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/\346\237\245\346\211\276\351\241\271\347\233\256\346\227\240\347\224\250\350\265\204\346\272\220/SLUnusedResourceViewController.m" @@ -47,7 +47,7 @@ - (void)getUnusedResourceData { NSString *imgExpression = [NSString stringWithFormat:@"([a-zA-Z0-9_-]*)(@[23]x)?\\.(%@)",imgTypes]; NSMutableArray *imgResources = [self searchAllUnderFolderPath:folderPath fileTypes:imgTypes regularExpression:imgExpression]; - NSString *fileTypes = @"h|m$|swift|xib|storyboard"; + NSString *fileTypes = @"h|m$|swift|xib|storyboard|plist"; NSString *fileExpression = [NSString stringWithFormat:@"([a-zA-Z0-9_-]*)(\\.)(%@)",fileTypes]; NSMutableArray *files = [self searchAllUnderFolderPath:folderPath fileTypes:fileTypes regularExpression:fileExpression]; From cbd3ff3fdef17b392d59fd9df796e75af610ce78 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 26 Aug 2020 11:29:04 +0800 Subject: [PATCH 168/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/General/.DS_Store | Bin 6148 -> 6148 bytes .../WorkIssues/\347\254\224\350\256\260.md" | 1 + ...00\346\234\257\345\215\232\345\256\242.md" | 1 + 3 files changed, 2 insertions(+) diff --git a/iOS_Tips/DarkMode/General/.DS_Store b/iOS_Tips/DarkMode/General/.DS_Store index 205abbf8b4720e0c22e3de1e473872aaa4832937..51725728d312ba6abed7a18d28a52f059e8f3efc 100644 GIT binary patch delta 60 zcmV-C0K@-;FoZCWV*&HCF$1RolQ0wnlMezE0rQh20;vfWdwVb}ATu&Klh^_u0>HtO S`2rsS!m}9z?gX<12>%aN^%MmF delta 62 zcmV-E0Kxx+FoZCWV*&NEF$1RolQ0wnlMezE0rit40;vladwVlDF)Sc4IX08l0v`gx U!;|*{9|6R(7X$7Dvj+(M4|oU^djJ3c diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 7b6f2ccb..e6b6551c 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -50,6 +50,7 @@ ## 二、数据结构与算法 * 1、 [LeetcodeTop](https://github.com/afatcoder/LeetcodeTop) +* 2、[小浩算法](https://www.geekxh.com) ## 三、面试题相关 * 1、[iOS-InterviewQuestion-collection](https://github.com/liberalisman/iOS-InterviewQuestion-collection) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index b330dc61..281c0dcc 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -52,3 +52,4 @@ * 1、[一瓜技术](公众号:tech_gua) * 2、[奔跑的程序猿iOSer](公众号:iOS2679114653) * 3、[知识小集](公众号:zsxjtip) +* 4、[小浩算法](公众号:xuesuanfa) From 5429a71353b9355fe214c656095bff894695e44c Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 26 Aug 2020 19:21:57 +0800 Subject: [PATCH 169/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index e6b6551c..24989e1c 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -45,7 +45,8 @@ > [iOS瘦身之道](https://juejin.im/post/6844903845340921869) > [iOS应用瘦身总结](https://juejin.im/post/6844903849732341774) > [如何使用 Clang Plugin 找到项目中的无用代码](https://blog.gocy.tech/2017/09/12/DetectingUselessCodeWithClang-p1/) -> [iOS 启动速度优化和安装包优化简单总结](https://juejin.im/post/6844903821387235341) +> [基于clang插件的一种iOS包大小瘦身方案](https://mp.weixin.qq.com/s?__biz=MzUxMzcxMzE5Ng==&mid=2247488360&idx=1&sn=94fba30a87d0f9bc0b9ff94d3fed3386&source=41#wechat_redirect) +> [iOS 启动速度优化和安装包优化简单总结](https://juejin.im/post/6844903821387235341) > [iOS代码瘦身实践:删除无用的类](https://juejin.im/post/6844903921169727496) ## 二、数据结构与算法 From b0ea95523582826fc60d4daa9c75aa95266d315d Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 27 Aug 2020 10:28:29 +0800 Subject: [PATCH 170/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 24989e1c..48f64f2e 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -38,6 +38,7 @@ > [iOS 性能监控(三)—— 方法耗时监控](https://www.jianshu.com/p/bc1c000afdba) > [iOS crash 日志堆栈解析](https://juejin.im/post/6844903598011187213) > [iOS崩溃crash大解析](https://www.jianshu.com/p/1b804426d212) +> [iOS实录14:浅谈iOS Crash(一)](https://www.jianshu.com/p/3261493e6d9e) > [iOS Memory 内存详解 (长文)](https://juejin.im/post/6844903902169710600) > [iOS 性能优化调试](https://www.jianshu.com/c/fcb00b489a85) > [iOS Memory Deep Dive](https://www.jianshu.com/p/dad9f27e412e) From 0f22437b3a04fd8030c184b2e235ffdffc2e391b Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 27 Aug 2020 11:10:05 +0800 Subject: [PATCH 171/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + ...1\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 2 files changed, 2 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 48f64f2e..6ebe07b2 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -33,6 +33,7 @@ > 资料 > [iOS-Performance-Optimization](https://github.com/skyming/iOS-Performance-Optimization) +> [深入剖析 iOS 性能优化](https://ming1016.github.io/2017/06/20/deeply-ios-performance-optimization/#more) > [DoraemonKit](https://github.com/didi/DoraemonKit/blob/master/README_CN.md) > [乐少](https://www.jianshu.com/u/9c51a213b02e) > [iOS 性能监控(三)—— 方法耗时监控](https://www.jianshu.com/p/bc1c000afdba) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 281c0dcc..6af7058e 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -46,6 +46,7 @@ * 44、[与佳期](gonghonglou.com) * 45、[RoyCao](https://juejin.im/user/4019470241649550) * 46、[gocy](https://blog.gocy.tech/) +* 47、[戴铭的博客](https://ming1016.github.io) ## 高质量微信公众号 From 77d482517991f1bd135d98138ae1d2d8d10e946f Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 27 Aug 2020 11:33:54 +0800 Subject: [PATCH 172/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 4 ++-- ...07\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 6ebe07b2..3e5d5097 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -19,7 +19,7 @@ * 1.4、启动时间优化 -> 合并减少动态库、二进制重排、异步延时加载、load 的方法处理、清理无用类 +> 合并减少动态库、二进制重排、异步延时加载、load 的方法处理、清理无用类、 * 1.5、编译时间优化 @@ -33,7 +33,7 @@ > 资料 > [iOS-Performance-Optimization](https://github.com/skyming/iOS-Performance-Optimization) -> [深入剖析 iOS 性能优化](https://ming1016.github.io/2017/06/20/deeply-ios-performance-optimization/#more) +> [深入剖析 iOS 性能优化-戴明](https://ming1016.github.io/2017/06/20/deeply-ios-performance-optimization/#more) > [DoraemonKit](https://github.com/didi/DoraemonKit/blob/master/README_CN.md) > [乐少](https://www.jianshu.com/u/9c51a213b02e) > [iOS 性能监控(三)—— 方法耗时监控](https://www.jianshu.com/p/bc1c000afdba) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 6af7058e..8558ecd5 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -47,6 +47,7 @@ * 45、[RoyCao](https://juejin.im/user/4019470241649550) * 46、[gocy](https://blog.gocy.tech/) * 47、[戴铭的博客](https://ming1016.github.io) +* 48、[iDog的精神时光屋](https://bigporo.github.io) ## 高质量微信公众号 From 4d8d63244d1e47a1f658b2fa93834655364c507a Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 27 Aug 2020 15:24:11 +0800 Subject: [PATCH 173/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 8558ecd5..03652813 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -47,7 +47,8 @@ * 45、[RoyCao](https://juejin.im/user/4019470241649550) * 46、[gocy](https://blog.gocy.tech/) * 47、[戴铭的博客](https://ming1016.github.io) -* 48、[iDog的精神时光屋](https://bigporo.github.io) +* 48、[iDog的精神时光屋](https://bigporo.github.io) +* 49、[Draveness](https://draveness.me/) ## 高质量微信公众号 From acaac0b39d8b555f0053ede5b3680121278f3a38 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 27 Aug 2020 19:21:20 +0800 Subject: [PATCH 174/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 3e5d5097..d90abd4b 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -19,7 +19,7 @@ * 1.4、启动时间优化 -> 合并减少动态库、二进制重排、异步延时加载、load 的方法处理、清理无用类、 +> 合并减少动态库和类、二进制重排/减少缺页中断、load 的方法处理和耗时监听、异步延时加载、业务流程优化、rootViewController的加载 * 1.5、编译时间优化 @@ -49,7 +49,11 @@ > [如何使用 Clang Plugin 找到项目中的无用代码](https://blog.gocy.tech/2017/09/12/DetectingUselessCodeWithClang-p1/) > [基于clang插件的一种iOS包大小瘦身方案](https://mp.weixin.qq.com/s?__biz=MzUxMzcxMzE5Ng==&mid=2247488360&idx=1&sn=94fba30a87d0f9bc0b9ff94d3fed3386&source=41#wechat_redirect) > [iOS 启动速度优化和安装包优化简单总结](https://juejin.im/post/6844903821387235341) -> [iOS代码瘦身实践:删除无用的类](https://juejin.im/post/6844903921169727496) +> [iOS代码瘦身实践:删除无用的类](https://juejin.im/post/6844903921169727496) +> [优化 App 的启动时间](http://yulingtianxia.com/blog/2016/10/30/Optimizing-App-Startup-Time/) +> [iOS App 启动性能优化](https://mp.weixin.qq.com/s/Kf3EbDIUuf0aWVT-UCEmbA) + + ## 二、数据结构与算法 * 1、 [LeetcodeTop](https://github.com/afatcoder/LeetcodeTop) From a3dd450dc6b0b057ec5a551b89af1c834638eec6 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 27 Aug 2020 19:33:28 +0800 Subject: [PATCH 175/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\347\254\224\350\256\260.md" | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index d90abd4b..bb243e11 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -51,15 +51,18 @@ > [iOS 启动速度优化和安装包优化简单总结](https://juejin.im/post/6844903821387235341) > [iOS代码瘦身实践:删除无用的类](https://juejin.im/post/6844903921169727496) > [优化 App 的启动时间](http://yulingtianxia.com/blog/2016/10/30/Optimizing-App-Startup-Time/) -> [iOS App 启动性能优化](https://mp.weixin.qq.com/s/Kf3EbDIUuf0aWVT-UCEmbA) +> [iOS App 启动性能优化](https://mp.weixin.qq.com/s/Kf3EbDIUuf0aWVT-UCEmbA) +> [iOS一次立竿见影的启动时间优化](https://juejin.im/post/6844903525172903944) ## 二、数据结构与算法 + * 1、 [LeetcodeTop](https://github.com/afatcoder/LeetcodeTop) * 2、[小浩算法](https://www.geekxh.com) ## 三、面试题相关 + * 1、[iOS-InterviewQuestion-collection](https://github.com/liberalisman/iOS-InterviewQuestion-collection) * 2、[阿里、字节 一套高效的iOS面试题解答](https://github.com/colourful987/bytedance-alibaba-interview) * 3、[2019年iOS面试反思总结](https://juejin.im/post/6844903942644563982) @@ -68,6 +71,7 @@ * 6、[analyze](https://github.com/draveness/analyze) ## 四、逆向与安全 + * 1、 [趣探 Mach-O](https://juejin.im/post/5a0c5c5e51882555cc416602) * 2、 [iOS程序员的自我修养 - 编译、链接、装载](https://juejin.im/post/5d5273b1f265da03f233c2d6) @@ -87,8 +91,11 @@ * 1、[TCP序列号和确认号详解](https://blog.csdn.net/fujibao/article/details/80857180) + ## 其它 -* 1、[CocoaPods 都做了什么?](https://www.jianshu.com/p/84936d9344ff) -* 2、[2. 整体把握 CocoaPods 核心组件](https://mp.weixin.qq.com/s/eyjrhPgPFdidPWO7t2SDcA) -* 3、[1. 版本管理工具及 Ruby 工具链环境](https://mp.weixin.qq.com/s/s2yJEb2P0_Kk-rIpYBi_9A) +* 1、[CocoaPods 都做了什么?](https://www.jianshu.com/p/84936d9344ff) +* 2、[1. 版本管理工具及 Ruby 工具链环境](https://mp.weixin.qq.com/s/s2yJEb2P0_Kk-rIpYBi_9A) +* 3、[2. 整体把握 CocoaPods 核心组件](https://mp.weixin.qq.com/s/eyjrhPgPFdidPWO7t2SDcA) +* 4、[OCLint 实现 Code Review - 给你的代码提提质量](https://juejin.im/post/6844903853775650830) +* 5、[(译)开源软件架构之 LLVM(The Architecture of Open Source Applications LLVM)](https://juejin.im/post/6844904034134917134) From a7f839ea419d4b89295d40a3380b13b96f97d5f3 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 28 Aug 2020 16:35:45 +0800 Subject: [PATCH 176/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index bb243e11..a9949086 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -81,13 +81,17 @@ * 1、[(强烈推荐)移动端音视频从零到上手](https://juejin.im/post/6844903889007820813) -## 六、Shell脚本 + +## 六、跨平台/热更新/JSBridge + + +## 七、Shell脚本 * 1、[Shell脚本编程30分钟入门](https://github.com/qinjx/30min_guides/blob/master/shell.md) -## 七、网络 +## 八、网络 * 1、[TCP序列号和确认号详解](https://blog.csdn.net/fujibao/article/details/80857180) From af640022d76919a8750e8979a8e29d116d59af1b Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 28 Aug 2020 16:58:12 +0800 Subject: [PATCH 177/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index a9949086..27a32cbc 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -82,7 +82,9 @@ -## 六、跨平台/热更新/JSBridge +## 六、跨平台/热更新 + +* 1、DSBridge /JSBridge /JSPatch/ ## 七、Shell脚本 From 0abb2ea7412eea69d4fcc9e0a607ac41a230123f Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 28 Aug 2020 17:39:08 +0800 Subject: [PATCH 178/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m index 7f1659dd..500bc02e 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.m @@ -53,7 +53,7 @@ - (void)setMachHandler { ///创建异常端口 kern_return_t kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &server_port); assert(kr == KERN_SUCCESS); - NSLog(@"create a port: %d", server_port); + NSLog(@"创建异常消息监听端口: %d", server_port); ///申请set_exception_ports 的权限 kr = mach_port_insert_right(mach_task_self(), server_port, server_port, MACH_MSG_TYPE_MAKE_SEND); From 5244afb6eab381d778c60d2ccb8584c9bcca9f4e Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 28 Aug 2020 18:52:23 +0800 Subject: [PATCH 179/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...1\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 03652813..c16c8abc 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -49,6 +49,7 @@ * 47、[戴铭的博客](https://ming1016.github.io) * 48、[iDog的精神时光屋](https://bigporo.github.io) * 49、[Draveness](https://draveness.me/) +* 50、[NewPan](https://juejin.im/user/2506542239987454) ## 高质量微信公众号 From 6c4cd77cff16531dcde9f723574edfac31d7eeb2 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 28 Aug 2020 19:32:22 +0800 Subject: [PATCH 180/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + ...1\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 2 files changed, 2 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 27a32cbc..3543742d 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -53,6 +53,7 @@ > [优化 App 的启动时间](http://yulingtianxia.com/blog/2016/10/30/Optimizing-App-Startup-Time/) > [iOS App 启动性能优化](https://mp.weixin.qq.com/s/Kf3EbDIUuf0aWVT-UCEmbA) > [iOS一次立竿见影的启动时间优化](https://juejin.im/post/6844903525172903944) +> [iOS Dynamic Framework 对App启动时间影响实测](https://www.jianshu.com/p/3263009e9228) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index c16c8abc..0eccdb97 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -50,6 +50,7 @@ * 48、[iDog的精神时光屋](https://bigporo.github.io) * 49、[Draveness](https://draveness.me/) * 50、[NewPan](https://juejin.im/user/2506542239987454) +* 51、[没故事的卓同学 ](https://juejin.im/user/1926000099460664) ## 高质量微信公众号 From a59346596260df62ff019510e64338f77dc06aac Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 31 Aug 2020 09:43:56 +0800 Subject: [PATCH 181/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 3 +-- ...207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 3543742d..fdc22cc5 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -80,8 +80,7 @@ ## 五、音视频 * 1、[(强烈推荐)移动端音视频从零到上手](https://juejin.im/post/6844903889007820813) - - +* 2、[移动开发者的必知音视频基础知识](https://juejin.im/post/6844904039503626247) ## 六、跨平台/热更新 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 0eccdb97..4fdb4e0f 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -58,3 +58,4 @@ * 2、[奔跑的程序猿iOSer](公众号:iOS2679114653) * 3、[知识小集](公众号:zsxjtip) * 4、[小浩算法](公众号:xuesuanfa) +* 5、[素燕](公众号:gh_a97f4df5b7b9) From fb0b0da9615cceeb065969a79ea9ec1d9e780e2a Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 31 Aug 2020 19:27:41 +0800 Subject: [PATCH 182/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index fdc22cc5..7b8f7881 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -11,7 +11,7 @@ * 1.2、卡顿优化 -> 优化业务流程、 预处理、 缓存/空间换时间、避免圆角/阴影/光栅化/透明造成的离屏渲染、异步解码绘制、合并图层、图像字节对齐 +> 优化业务流程、 预处理、 缓存/空间换时间、避免圆角/阴影/光栅化/透明造成的离屏渲染、异步解码/异步绘制、合并图层、图像字节对齐 * 1.3、 安装包瘦身 @@ -23,13 +23,15 @@ * 1.5、编译时间优化 +> + * 1.6、网络优化 * 1.7、健壮性/稳定性 > 启动连续闪退保护、Crash防护、Crash分析 -* 1.7、安全性 +* 1.8、安全性 > 资料 > [iOS-Performance-Optimization](https://github.com/skyming/iOS-Performance-Optimization) From 1b0d9387837999bce60329190b70c9d57801d39a Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 31 Aug 2020 19:32:36 +0800 Subject: [PATCH 183/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 7b8f7881..47ac19fd 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -56,7 +56,7 @@ > [iOS App 启动性能优化](https://mp.weixin.qq.com/s/Kf3EbDIUuf0aWVT-UCEmbA) > [iOS一次立竿见影的启动时间优化](https://juejin.im/post/6844903525172903944) > [iOS Dynamic Framework 对App启动时间影响实测](https://www.jianshu.com/p/3263009e9228) - +> [iOS优化篇之App启动时间优化](https://juejin.im/post/6861917375382929415) ## 二、数据结构与算法 From 2c730b26f9440105f13f531bf29bd5fc8723c089 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 1 Sep 2020 09:02:00 +0800 Subject: [PATCH 184/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 4 +++- ...07\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 47ac19fd..1eb37529 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -77,7 +77,7 @@ * 1、 [趣探 Mach-O](https://juejin.im/post/5a0c5c5e51882555cc416602) * 2、 [iOS程序员的自我修养 - 编译、链接、装载](https://juejin.im/post/5d5273b1f265da03f233c2d6) - +* 3、[[iOS翻译]编译器](https://juejin.im/post/6854573220612931592) ## 五、音视频 @@ -87,6 +87,7 @@ ## 六、跨平台/热更新 * 1、DSBridge /JSBridge /JSPatch/ +* 2、[写给自己看系列之WebViewJavascriptBridge源码分析](https://juejin.im/post/6844904097192247303) ## 七、Shell脚本 @@ -107,3 +108,4 @@ * 3、[2. 整体把握 CocoaPods 核心组件](https://mp.weixin.qq.com/s/eyjrhPgPFdidPWO7t2SDcA) * 4、[OCLint 实现 Code Review - 给你的代码提提质量](https://juejin.im/post/6844903853775650830) * 5、[(译)开源软件架构之 LLVM(The Architecture of Open Source Applications LLVM)](https://juejin.im/post/6844904034134917134) +* 6、[你真的会用 CocoaPods 吗?](https://juejin.im/post/6844903506734759949) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 4fdb4e0f..2081bdbb 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -51,6 +51,7 @@ * 49、[Draveness](https://draveness.me/) * 50、[NewPan](https://juejin.im/user/2506542239987454) * 51、[没故事的卓同学 ](https://juejin.im/user/1926000099460664) +* 52、[薛定諤](https://juejin.im/user/325111170210045) ## 高质量微信公众号 From 5923ed90ebdf2f6647736b6218ba6d172471897a Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 1 Sep 2020 09:54:59 +0800 Subject: [PATCH 185/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 6 +++++- ...\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 1eb37529..f5da927b 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -57,7 +57,7 @@ > [iOS一次立竿见影的启动时间优化](https://juejin.im/post/6844903525172903944) > [iOS Dynamic Framework 对App启动时间影响实测](https://www.jianshu.com/p/3263009e9228) > [iOS优化篇之App启动时间优化](https://juejin.im/post/6861917375382929415) - +> [iOS如何提高10倍以上编译速度](https://juejin.im/post/6844904169124397070) ## 二、数据结构与算法 @@ -101,6 +101,10 @@ * 1、[TCP序列号和确认号详解](https://blog.csdn.net/fujibao/article/details/80857180) +## 九、效率 + +* 1、[iOS教你如何像RN一样实时编译](https://juejin.im/post/6850037272415813645) + ## 其它 * 1、[CocoaPods 都做了什么?](https://www.jianshu.com/p/84936d9344ff) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 2081bdbb..74f87cea 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -52,6 +52,7 @@ * 50、[NewPan](https://juejin.im/user/2506542239987454) * 51、[没故事的卓同学 ](https://juejin.im/user/1926000099460664) * 52、[薛定諤](https://juejin.im/user/325111170210045) +* 53、[Mr_Coder](https://juejin.im/user/3544481220795998) ## 高质量微信公众号 From 299bfc73282fb11bc571f9f329bf2bbaa4ef4975 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 1 Sep 2020 20:20:25 +0800 Subject: [PATCH 186/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index f5da927b..906a89ef 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -43,7 +43,7 @@ > [iOS崩溃crash大解析](https://www.jianshu.com/p/1b804426d212) > [iOS实录14:浅谈iOS Crash(一)](https://www.jianshu.com/p/3261493e6d9e) > [iOS Memory 内存详解 (长文)](https://juejin.im/post/6844903902169710600) -> [iOS 性能优化调试](https://www.jianshu.com/c/fcb00b489a85) +> [iOS 性能优化调试专题](https://www.jianshu.com/c/fcb00b489a85) > [iOS Memory Deep Dive](https://www.jianshu.com/p/dad9f27e412e) > [iOS性能优化系列篇之“列表流畅度优化”](https://juejin.im/post/6844903656769208334) > [iOS瘦身之道](https://juejin.im/post/6844903845340921869) From a97ed919dc5f46dafc0654632a7bf53f0a7d4f6f Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 1 Sep 2020 20:24:43 +0800 Subject: [PATCH 187/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 2 ++ 1 file changed, 2 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 906a89ef..06011980 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -104,6 +104,8 @@ ## 九、效率 * 1、[iOS教你如何像RN一样实时编译](https://juejin.im/post/6850037272415813645) +* 2、[iOS开发老司机的神兵利器-效率工具](https://juejin.im/post/6844904205640007687) +* 3、[Xcode配置文件xcconfig](https://juejin.im/post/6844903766282469390) ## 其它 From 33dc3260df0c3f8505c5bc68b5f2d8b269760a6f Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 1 Sep 2020 20:26:56 +0800 Subject: [PATCH 188/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 5 +++++ 1 file changed, 5 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 06011980..29b16f21 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -107,6 +107,11 @@ * 2、[iOS开发老司机的神兵利器-效率工具](https://juejin.im/post/6844904205640007687) * 3、[Xcode配置文件xcconfig](https://juejin.im/post/6844903766282469390) + +## 十、架构/设计模式 + + + ## 其它 * 1、[CocoaPods 都做了什么?](https://www.jianshu.com/p/84936d9344ff) From f024abe7c44ef9d76c9c41e1030e03e32f1f2c02 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 1 Sep 2020 20:30:43 +0800 Subject: [PATCH 189/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 29b16f21..31b1069e 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -27,13 +27,17 @@ * 1.6、网络优化 +> + * 1.7、健壮性/稳定性 > 启动连续闪退保护、Crash防护、Crash分析 * 1.8、安全性 -> 资料 +> 代码混淆 + +> * 资料 > [iOS-Performance-Optimization](https://github.com/skyming/iOS-Performance-Optimization) > [深入剖析 iOS 性能优化-戴明](https://ming1016.github.io/2017/06/20/deeply-ios-performance-optimization/#more) > [DoraemonKit](https://github.com/didi/DoraemonKit/blob/master/README_CN.md) From 831901bb28d6a3eebe70015b1148f01b3cd4bc67 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 1 Sep 2020 20:49:05 +0800 Subject: [PATCH 190/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 6 ++++-- ...\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 31b1069e..93a31756 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -82,6 +82,7 @@ * 1、 [趣探 Mach-O](https://juejin.im/post/5a0c5c5e51882555cc416602) * 2、 [iOS程序员的自我修养 - 编译、链接、装载](https://juejin.im/post/5d5273b1f265da03f233c2d6) * 3、[[iOS翻译]编译器](https://juejin.im/post/6854573220612931592) +* 4、[Injection:iOS热重载背后的黑魔法](https://mp.weixin.qq.com/s/hFnHdOP6pmIwzZck-zXE8g) ## 五、音视频 @@ -108,8 +109,9 @@ ## 九、效率 * 1、[iOS教你如何像RN一样实时编译](https://juejin.im/post/6850037272415813645) -* 2、[iOS开发老司机的神兵利器-效率工具](https://juejin.im/post/6844904205640007687) -* 3、[Xcode配置文件xcconfig](https://juejin.im/post/6844903766282469390) +* 2、[Injection:iOS热重载背后的黑魔法](https://mp.weixin.qq.com/s/hFnHdOP6pmIwzZck-zXE8g) +* 3、[iOS开发老司机的神兵利器-效率工具](https://juejin.im/post/6844904205640007687) +* 4、[Xcode配置文件xcconfig](https://juejin.im/post/6844903766282469390) ## 十、架构/设计模式 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 74f87cea..3a550051 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -61,3 +61,4 @@ * 3、[知识小集](公众号:zsxjtip) * 4、[小浩算法](公众号:xuesuanfa) * 5、[素燕](公众号:gh_a97f4df5b7b9) +* 6、[iOSTips](公众号:iostips) From b9b95eee9fab38d3faacaa241c19aba7bf753372 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 1 Sep 2020 21:30:05 +0800 Subject: [PATCH 191/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/Crash/SLCrashViewController.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m index ae3a0214..8df2f28e 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m @@ -117,6 +117,11 @@ - (void)crashHandlerDidOutputCrashError:(SLCrashError *)crashError { [fileHandle closeFile]; } + //调试模式时,强制抛出异常,提醒开发者代码有问题 + #if DEBUG + @throw crashError.exception; + #endif + } #pragma mark - Container Crash From 5993a7b33dabd448f09c9b704793e80e4dfe3ed7 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 2 Sep 2020 11:23:55 +0800 Subject: [PATCH 192/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 2 ++ ...\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 2 files changed, 3 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 93a31756..32080bbe 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -62,6 +62,7 @@ > [iOS Dynamic Framework 对App启动时间影响实测](https://www.jianshu.com/p/3263009e9228) > [iOS优化篇之App启动时间优化](https://juejin.im/post/6861917375382929415) > [iOS如何提高10倍以上编译速度](https://juejin.im/post/6844904169124397070) +> [为什么 Debug Information Format 改为 DWARF 可以提高编译速度?](https://zhuanlan.zhihu.com/p/112764192) ## 二、数据结构与算法 @@ -76,6 +77,7 @@ * 4、[IOS面试考察(九):性能优化相关问题](https://juejin.im/post/6844904131941892110#heading-50) * 5、[Theendisthebegi ](https://www.jianshu.com/u/b836babfef41) * 6、[analyze](https://github.com/draveness/analyze) +* 7、[iOS 方案之本之使用汇编可以 Hook objc_msgSend](https://zhuanlan.zhihu.com/c_1221108308322443264) ## 四、逆向与安全 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 3a550051..07583e61 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -53,6 +53,7 @@ * 51、[没故事的卓同学 ](https://juejin.im/user/1926000099460664) * 52、[薛定諤](https://juejin.im/user/325111170210045) * 53、[Mr_Coder](https://juejin.im/user/3544481220795998) +* 54、[冬瓜逛逼乎](https://www.zhihu.com/people/desgard-duan) ## 高质量微信公众号 From 3fd30fee576125865e516f46fd3c5462cea8c2f4 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 2 Sep 2020 18:12:37 +0800 Subject: [PATCH 193/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + ...07\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 4 ++++ 2 files changed, 5 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 32080bbe..a18bb40e 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -78,6 +78,7 @@ * 5、[Theendisthebegi ](https://www.jianshu.com/u/b836babfef41) * 6、[analyze](https://github.com/draveness/analyze) * 7、[iOS 方案之本之使用汇编可以 Hook objc_msgSend](https://zhuanlan.zhihu.com/c_1221108308322443264) +* 8、[iOS Rendering 渲染全解析(长文干货)](https://juejin.im/post/6844904162765832206) ## 四、逆向与安全 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 07583e61..862659ec 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -63,3 +63,7 @@ * 4、[小浩算法](公众号:xuesuanfa) * 5、[素燕](公众号:gh_a97f4df5b7b9) * 6、[iOSTips](公众号:iostips) +* 7、[字节流动](公众号:google_developer) +* 8、[有赞coder](公众号:youzan_coder) +* 9、[58技术](公众号:architects_58) +* 10、[音视频开发进阶](公众号:glumes_blog) From f5a1daf79c1377781bc1966c9f3c7c57a37db079 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 2 Sep 2020 20:05:38 +0800 Subject: [PATCH 194/356] =?UTF-8?q?=E5=A4=9A=E4=B8=AAUIScrollView=E5=B5=8C?= =?UTF-8?q?=E5=A5=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 14 +++++++ .../WorkIssues/SLWorkIssuesViewController.m | 26 +++++++------ .../SLScrollviewNesteVC.h" | 18 +++++++++ .../SLScrollviewNesteVC.m" | 39 +++++++++++++++++++ 4 files changed, 86 insertions(+), 11 deletions(-) create mode 100644 "iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.h" create mode 100644 "iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index c533e717..3fac94a3 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -127,6 +127,7 @@ 788ACD622390BFD400737EC2 /* SLLoadImageVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 788ACD612390BFD400737EC2 /* SLLoadImageVC.m */; }; 788ACD652390EA3A00737EC2 /* SLCubeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 788ACD642390EA3A00737EC2 /* SLCubeViewController.m */; }; 788ADB382441F48F00302CD9 /* SLCrashViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 788ADB362441F48F00302CD9 /* SLCrashViewController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 78908DC324FFBE5D004164C2 /* SLScrollviewNesteVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 78908DC224FFBE5D004164C2 /* SLScrollviewNesteVC.m */; }; 789AD16324C99DCA00CB0B4C /* SLAPMThreadCount.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD16224C99DCA00CB0B4C /* SLAPMThreadCount.m */; }; 789AD1C824D7FA5F00CB0B4C /* SLAPMURLProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD1C724D7FA5F00CB0B4C /* SLAPMURLProtocol.m */; }; 789AD1CF24D9024300CB0B4C /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD1CD24D9024300CB0B4C /* Reachability.m */; }; @@ -400,6 +401,8 @@ 788ACD642390EA3A00737EC2 /* SLCubeViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLCubeViewController.m; sourceTree = ""; }; 788ADB352441F48F00302CD9 /* SLCrashViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLCrashViewController.h; sourceTree = ""; }; 788ADB362441F48F00302CD9 /* SLCrashViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLCrashViewController.m; sourceTree = ""; }; + 78908DC124FFBE5D004164C2 /* SLScrollviewNesteVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLScrollviewNesteVC.h; sourceTree = ""; }; + 78908DC224FFBE5D004164C2 /* SLScrollviewNesteVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLScrollviewNesteVC.m; sourceTree = ""; }; 789AD16124C99DCA00CB0B4C /* SLAPMThreadCount.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMThreadCount.h; sourceTree = ""; }; 789AD16224C99DCA00CB0B4C /* SLAPMThreadCount.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMThreadCount.m; sourceTree = ""; }; 789AD1C624D7FA5F00CB0B4C /* SLAPMURLProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMURLProtocol.h; sourceTree = ""; }; @@ -919,6 +922,7 @@ 784C4C6D24C5B4F500D5C199 /* 笔记.md */, 7884247D2492102900C2E505 /* SLWorkIssuesViewController.h */, 7884247E2492102900C2E505 /* SLWorkIssuesViewController.m */, + 78908DC024FFBD83004164C2 /* ScrollView嵌套 */, 78799E9F24EE7E7F00DA8C7A /* 查找项目无用资源 */, 784C4BDE24BC409600D5C199 /* APM */, 7811F76C24B2C70D000AA044 /* 二进制重排 */, @@ -937,6 +941,15 @@ path = Crash; sourceTree = ""; }; + 78908DC024FFBD83004164C2 /* ScrollView嵌套 */ = { + isa = PBXGroup; + children = ( + 78908DC124FFBE5D004164C2 /* SLScrollviewNesteVC.h */, + 78908DC224FFBE5D004164C2 /* SLScrollviewNesteVC.m */, + ); + path = "ScrollView嵌套"; + sourceTree = ""; + }; 789AD1C524D43A3700CB0B4C /* APMMonitor */ = { isa = PBXGroup; children = ( @@ -1487,6 +1500,7 @@ 78B10482232F57C30051579F /* AppDelegate.m in Sources */, 78E72D7C24810E2D00751373 /* SLDynamicItem.m in Sources */, 78777CE0238FEA48006FA671 /* SLOpenGLController.m in Sources */, + 78908DC324FFBE5D004164C2 /* SLScrollviewNesteVC.m in Sources */, 7851CB362331CC87002295B5 /* SLDarkModeViewController.m in Sources */, 78D30965239688EF00DC373A /* GLESMath.c in Sources */, 7811F76F24B2C791000AA044 /* SLBinaryResetViewController.m in Sources */, diff --git a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m index 06c91aa7..36910a88 100644 --- a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m @@ -12,6 +12,7 @@ #import "SLBinaryResetViewController.h" #import "SLAPMViewController.h" #import "SLUnusedResourceViewController.h" +#import "SLScrollviewNesteVC.h" @interface SLWorkIssuesViewController () @property (nonatomic, strong) NSMutableArray *titlesArray; @@ -53,16 +54,18 @@ - (void)getData { @"iOS 自定义转场动画", @"二进制重排优化启动时间", @"iOS APM应用性能监控管理(doing)", - @"ipa瘦身之扫描无用资源"]]; + @"ipa瘦身之扫描无用资源", + @"多个UIScrollView嵌套"]]; [self.urlArray addObjectsFromArray:@[@"", - @"https://juejin.im/post/5c0e1e73f265da616413d828", - @"https://juejin.im/post/5c0e1df95188250d2722a3bc", - @"https://juejin.im/post/5c088b45f265da610e7fe156", - @"https://juejin.im/post/5c088a1051882517165dd15d", - @"https://juejin.im/post/5c088ba36fb9a049fb43737b", - @"二进制重排", - @"APM", - @"ipa瘦身"]]; + @"https://juejin.im/post/5c0e1e73f265da616413d828", + @"https://juejin.im/post/5c0e1df95188250d2722a3bc", + @"https://juejin.im/post/5c088b45f265da610e7fe156", + @"https://juejin.im/post/5c088a1051882517165dd15d", + @"https://juejin.im/post/5c088ba36fb9a049fb43737b", + @"二进制重排", + @"APM", + @"ipa瘦身", + @"UIScrollView嵌套"]]; [self.classArray addObjectsFromArray:@[[SLMenuViewController class], [SLWebViewController class], [SLWebViewController class], @@ -71,7 +74,8 @@ - (void)getData { [SLWebViewController class], [SLBinaryResetViewController class], [SLAPMViewController class], - [SLUnusedResourceViewController class]]]; + [SLUnusedResourceViewController class], + [SLScrollviewNesteVC class]]]; [self.tableView reloadData]; } @@ -117,6 +121,6 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath } [self.navigationController pushViewController:nextVc animated:YES]; break; - } } +} @end diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.h" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.h" new file mode 100644 index 00000000..80431081 --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.h" @@ -0,0 +1,18 @@ +// +// SLScrollviewNesteVC.h +// DarkMode +// +// Created by wsl on 2020/9/2. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +///多个ScrollView/TableView/CollectionView嵌套 +@interface SLScrollviewNesteVC : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" new file mode 100644 index 00000000..d2520615 --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" @@ -0,0 +1,39 @@ +// +// SLScrollviewNesteVC.m +// DarkMode +// +// Created by wsl on 2020/9/2. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLScrollviewNesteVC.h" + +@interface SLScrollviewNesteVC () + +@end + +@implementation SLScrollviewNesteVC + +#pragma mark - Override +- (void)viewDidLoad { + [super viewDidLoad]; + [self setupUI]; +} + +#pragma mark - UI +- (void)setupUI { + self.view.backgroundColor = [UIColor whiteColor]; +} + +#pragma mark - Data + +#pragma mark - Getter + +#pragma mark - HelpMethods + +#pragma mark - EventsHandle + + + + +@end From f36bb371e9ee4e3a41b14c1bf4dba1c2afda7028 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 2 Sep 2020 21:06:02 +0800 Subject: [PATCH 195/356] =?UTF-8?q?UIScrollView=E5=B5=8C=E5=A5=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Crash/SLCrashProtector/SLCrashHandler.h | 2 +- .../DarkMode/Crash/SLCrashViewController.h | 2 +- .../WorkIssues/SLWorkIssuesViewController.m | 2 +- .../SLScrollviewNesteVC.m" | 106 +++++++++++++++++- 4 files changed, 107 insertions(+), 5 deletions(-) diff --git a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h index 55e5c6ad..e346238d 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h +++ b/iOS_Tips/DarkMode/Crash/SLCrashProtector/SLCrashHandler.h @@ -60,7 +60,7 @@ typedef NS_ENUM(NSInteger, SLCrashErrorType) { - (void)crashHandlerDidOutputCrashError:(SLCrashError *)crashError; @end -/// 崩溃处理程序 +/// 崩溃处理程序 注意:部分防护功能还不完善,比如野指针和内存泄漏/循环引用 @interface SLCrashHandler : NSObject ///异常捕获回调 提供给外界实现自定义处理 ,日志上报等(注意线程安全) diff --git a/iOS_Tips/DarkMode/Crash/SLCrashViewController.h b/iOS_Tips/DarkMode/Crash/SLCrashViewController.h index 90149940..37f2d938 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashViewController.h +++ b/iOS_Tips/DarkMode/Crash/SLCrashViewController.h @@ -10,7 +10,7 @@ NS_ASSUME_NONNULL_BEGIN -//iOS Crash防护 +//iOS Crash防护 注意:部分防护功能还不完善,比如野指针和内存泄漏/循环引用 @interface SLCrashViewController : SLViewController @end diff --git a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m index 36910a88..8cda68f6 100644 --- a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m @@ -55,7 +55,7 @@ - (void)getData { @"二进制重排优化启动时间", @"iOS APM应用性能监控管理(doing)", @"ipa瘦身之扫描无用资源", - @"多个UIScrollView嵌套"]]; + @"多个UIScrollView嵌套(doing)"]]; [self.urlArray addObjectsFromArray:@[@"", @"https://juejin.im/post/5c0e1e73f265da616413d828", @"https://juejin.im/post/5c0e1df95188250d2722a3bc", diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" index d2520615..9cb646ce 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" @@ -8,7 +8,15 @@ #import "SLScrollviewNesteVC.h" -@interface SLScrollviewNesteVC () +@interface SLScrollviewNesteVC () + +@property (nonatomic, strong) UIScrollView *mainScrollView; + +@property (nonatomic, strong) UIView *containerView; +@property (nonatomic, strong) UITableView *tableView1; +@property (nonatomic, strong) UITableView *tableView2; + +@property (nonatomic, strong) NSMutableArray *dataSource; @end @@ -23,17 +31,111 @@ - (void)viewDidLoad { #pragma mark - UI - (void)setupUI { self.view.backgroundColor = [UIColor whiteColor]; + [self.view addSubview:self.mainScrollView]; + [self.mainScrollView addSubview:self.containerView]; + self.containerView.frame = CGRectMake(0, 300, SL_kScreenWidth, SL_kScreenHeight-SL_TopNavigationBarHeight); + + // [self.containerView addSubview:self.tableView1]; + // [self.containerView addSubview:self.tableView2]; + + } #pragma mark - Data #pragma mark - Getter +- (UIScrollView *)mainScrollView { + if (!_mainScrollView) { + _mainScrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; + _mainScrollView.backgroundColor = [UIColor orangeColor]; + if (@available(iOS 11.0, *)) { + _mainScrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } else { + // Fallback on earlier versions + } + } + return _mainScrollView; +} +- (UIView *)containerView { + if (!_containerView) { + _containerView = [[UIView alloc] init]; + _containerView.backgroundColor = [UIColor redColor]; + } + return _containerView; +} +- (UITableView *)tableView1 { + if (!_tableView1) { + _tableView1 = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, SL_kScreenWidth, SL_kScreenHeight) style:UITableViewStyleGrouped]; + _tableView1.delegate = self; + _tableView1.dataSource = self; + _tableView1.estimatedRowHeight = 0; + if (@available(iOS 11.0, *)) { + _tableView1.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } else { + // Fallback on earlier versions + } + [_tableView1 registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cellId"]; + } + return _tableView1; +} +- (UITableView *)tableView2 { + if (!_tableView2) { + _tableView2 = [[UITableView alloc] initWithFrame:CGRectMake(SL_kScreenWidth, 0, SL_kScreenWidth, SL_kScreenHeight) style:UITableViewStyleGrouped]; + _tableView2.delegate = self; + _tableView2.dataSource = self; + _tableView2.estimatedRowHeight = 0; + if (@available(iOS 11.0, *)) { + _tableView2.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } else { + // Fallback on earlier versions + } + [_tableView2 registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cellId"]; + } + return _tableView2; +} +- (NSMutableArray *)dataSource { + if (_dataSource == nil) { + _dataSource = [NSMutableArray array]; + } + return _dataSource; +} -#pragma mark - HelpMethods +#pragma mark - Data #pragma mark - EventsHandle +#pragma mark - HelpMethods +#pragma mark - UITableViewDelegate,UITableViewDataSource +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return 20; +} +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + return 100; +} +- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { + return 0.1; +} +- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { + return nil; +} +- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { + return 0.1; +} +- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { + return nil; +} +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cellId" forIndexPath:indexPath]; + cell.textLabel.text = tableView == self.tableView1 ? @"tableView1" : @"tableView2"; + return cell; +} +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [tableView deselectRowAtIndexPath:indexPath animated:YES]; +} @end From 97033a879548892d5a40a82a9ddc45131e0932fe Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 2 Sep 2020 21:13:28 +0800 Subject: [PATCH 196/356] =?UTF-8?q?=E5=A4=9A=E4=B8=AAScrollView/TableView/?= =?UTF-8?q?CollectionView=E5=B5=8C=E5=A5=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SLScrollviewNesteVC.m" | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" index 9cb646ce..5a4fc1ea 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" @@ -8,6 +8,9 @@ #import "SLScrollviewNesteVC.h" +///mainScrollView头部高度 +static CGFloat mainScrollViewHeadHeight = 300; + @interface SLScrollviewNesteVC () @property (nonatomic, strong) UIScrollView *mainScrollView; @@ -33,10 +36,14 @@ - (void)setupUI { self.view.backgroundColor = [UIColor whiteColor]; [self.view addSubview:self.mainScrollView]; [self.mainScrollView addSubview:self.containerView]; - self.containerView.frame = CGRectMake(0, 300, SL_kScreenWidth, SL_kScreenHeight-SL_TopNavigationBarHeight); + self.containerView.frame = CGRectMake(0, mainScrollViewHeadHeight, SL_kScreenWidth, SL_kScreenHeight-SL_TopNavigationBarHeight); + self.mainScrollView.contentSize = CGSizeMake(SL_kScreenWidth, self.containerView.sl_y+self.containerView.sl_height); + + - // [self.containerView addSubview:self.tableView1]; - // [self.containerView addSubview:self.tableView2]; +// self.containerView.contentSize = CGSizeMake(SL_kScreenWidth*2, self.containerView.sl_y+self.containerView.sl_height); +// [self.containerView addSubview:self.tableView1]; +// [self.containerView addSubview:self.tableView2]; } From 1096edefc152a99372f352850ad379f83692057b Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 3 Sep 2020 14:50:53 +0800 Subject: [PATCH 197/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 2 ++ 1 file changed, 2 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index a18bb40e..d5da26a2 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -79,6 +79,8 @@ * 6、[analyze](https://github.com/draveness/analyze) * 7、[iOS 方案之本之使用汇编可以 Hook objc_msgSend](https://zhuanlan.zhihu.com/c_1221108308322443264) * 8、[iOS Rendering 渲染全解析(长文干货)](https://juejin.im/post/6844904162765832206) +* 9、[iOS | 面试知识整理 - OC基础 (二)](https://juejin.im/post/6844903945052110856) +* 10、[各种精选面试题](https://github.com/iOShuyang/Book-Recommended-Interview) ## 四、逆向与安全 From c4518c958c233f63a2ecce3bf99d3c8946310e29 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 3 Sep 2020 19:15:08 +0800 Subject: [PATCH 198/356] =?UTF-8?q?UIScrollView=E5=B5=8C=E5=A5=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 6 + .../SLMenuView.h" | 24 ++++ .../SLMenuView.m" | 118 ++++++++++++++++ .../SLScrollviewNesteVC.m" | 132 +++++++++++++----- 4 files changed, 242 insertions(+), 38 deletions(-) create mode 100644 "iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLMenuView.h" create mode 100644 "iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLMenuView.m" diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 3fac94a3..36e52f97 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -128,6 +128,7 @@ 788ACD652390EA3A00737EC2 /* SLCubeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 788ACD642390EA3A00737EC2 /* SLCubeViewController.m */; }; 788ADB382441F48F00302CD9 /* SLCrashViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 788ADB362441F48F00302CD9 /* SLCrashViewController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 78908DC324FFBE5D004164C2 /* SLScrollviewNesteVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 78908DC224FFBE5D004164C2 /* SLScrollviewNesteVC.m */; }; + 78908DCD2500F099004164C2 /* SLMenuView.m in Sources */ = {isa = PBXBuildFile; fileRef = 78908DCC2500F099004164C2 /* SLMenuView.m */; }; 789AD16324C99DCA00CB0B4C /* SLAPMThreadCount.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD16224C99DCA00CB0B4C /* SLAPMThreadCount.m */; }; 789AD1C824D7FA5F00CB0B4C /* SLAPMURLProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD1C724D7FA5F00CB0B4C /* SLAPMURLProtocol.m */; }; 789AD1CF24D9024300CB0B4C /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD1CD24D9024300CB0B4C /* Reachability.m */; }; @@ -403,6 +404,8 @@ 788ADB362441F48F00302CD9 /* SLCrashViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLCrashViewController.m; sourceTree = ""; }; 78908DC124FFBE5D004164C2 /* SLScrollviewNesteVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLScrollviewNesteVC.h; sourceTree = ""; }; 78908DC224FFBE5D004164C2 /* SLScrollviewNesteVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLScrollviewNesteVC.m; sourceTree = ""; }; + 78908DCB2500F099004164C2 /* SLMenuView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLMenuView.h; sourceTree = ""; }; + 78908DCC2500F099004164C2 /* SLMenuView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLMenuView.m; sourceTree = ""; }; 789AD16124C99DCA00CB0B4C /* SLAPMThreadCount.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMThreadCount.h; sourceTree = ""; }; 789AD16224C99DCA00CB0B4C /* SLAPMThreadCount.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMThreadCount.m; sourceTree = ""; }; 789AD1C624D7FA5F00CB0B4C /* SLAPMURLProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMURLProtocol.h; sourceTree = ""; }; @@ -946,6 +949,8 @@ children = ( 78908DC124FFBE5D004164C2 /* SLScrollviewNesteVC.h */, 78908DC224FFBE5D004164C2 /* SLScrollviewNesteVC.m */, + 78908DCB2500F099004164C2 /* SLMenuView.h */, + 78908DCC2500F099004164C2 /* SLMenuView.m */, ); path = "ScrollView嵌套"; sourceTree = ""; @@ -1558,6 +1563,7 @@ 78A4BD45236C5DF20021AE32 /* SLEditVideoController.m in Sources */, 78B10485232F57C30051579F /* SceneDelegate.m in Sources */, 783FB45C2394A4E10039AEFD /* SLShaderLanguageViewController.m in Sources */, + 78908DCD2500F099004164C2 /* SLMenuView.m in Sources */, 788424822492159F00C2E505 /* SLNavigationController.m in Sources */, 7835048424586BAC0071283E /* fishhook.c in Sources */, 787C7E42246557A5005DF7ED /* SLZombieFinder.m in Sources */, diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLMenuView.h" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLMenuView.h" new file mode 100644 index 00000000..d2e55310 --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLMenuView.h" @@ -0,0 +1,24 @@ +// +// SLMenuView.h +// DarkMode +// +// Created by wsl on 2020/9/3. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class SLMenuView; +@protocol SLMenuViewDelegate +- (void)menuView:(SLMenuView *)menuView didSelectItemAtIndex:(NSInteger)index; +@end + +@interface SLMenuView : UIView +@property (nonatomic, weak) iddelegate; +@property (nonatomic, strong) NSArray *titles; +@property (nonatomic, assign) NSInteger currentPage; +@end + +NS_ASSUME_NONNULL_END diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLMenuView.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLMenuView.m" new file mode 100644 index 00000000..a03f7cab --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLMenuView.m" @@ -0,0 +1,118 @@ +// +// SLMenuView.m +// DarkMode +// +// Created by wsl on 2020/9/3. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLMenuView.h" + + +@interface SLMenuViewCell : UICollectionViewCell +@property (nonatomic, strong) UILabel *titleLabel; +@end +@implementation SLMenuViewCell +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self setupUI]; + } + return self; +} +- (void)setupUI { + [self.contentView addSubview:self.titleLabel]; + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self.contentView); + }]; +} +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.textAlignment = NSTextAlignmentCenter; + } + return _titleLabel; +} +@end + +@interface SLMenuView () +@property (nonatomic, strong) UICollectionView *collectionView; +@end +@implementation SLMenuView + +#pragma mark - Override +- (void)didMoveToSuperview { + if (self.superview) { + [self addSubview:self.collectionView]; + self.collectionView.frame = self.bounds; + } +} +- (void)didMoveToWindow { + if (self.superview) { + [self addSubview:self.collectionView]; + self.collectionView.frame = self.bounds; + } +} + +#pragma mark - Getter +- (UICollectionView *)collectionView { + if (_collectionView == nil) { + UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; + layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; + _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; + _collectionView.backgroundColor = [UIColor clearColor]; + _collectionView.delegate = self; + _collectionView.dataSource = self; + _collectionView.showsHorizontalScrollIndicator = NO; + [_collectionView registerClass:[SLMenuViewCell class] forCellWithReuseIdentifier:@"ItemId"]; + } + return _collectionView; +} + +#pragma mark - Setter +- (void)setCurrentPage:(NSInteger)currentPage { + _currentPage = currentPage; + [self.collectionView reloadData]; +} + +#pragma mark - UICollectionViewDelegate, UICollectionViewDataSource +- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { + return 1; +} +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + return self.titles.count; +} +- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + SLMenuViewCell * item = [collectionView dequeueReusableCellWithReuseIdentifier:@"ItemId" forIndexPath:indexPath]; + item.titleLabel.text = self.titles[indexPath.row]; + if (indexPath.row == self.currentPage) { + item.titleLabel.font = [UIFont boldSystemFontOfSize:18]; + item.titleLabel.textColor = [UIColor redColor]; + }else { + item.titleLabel.font = [UIFont systemFontOfSize:15]; + item.titleLabel.textColor = [UIColor blackColor]; + } + return item; +} +- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { + [collectionView deselectItemAtIndexPath:indexPath animated:NO]; + [self.delegate menuView:self didSelectItemAtIndex:indexPath.row]; +} + +#pragma mark - UICollectionViewDelegateFlowLayout +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { + return CGSizeMake(self.bounds.size.width/self.titles.count, self.bounds.size.height); +} +//列间距 +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { + return 0; +} +//行间距 +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { + return 0; +} +- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { + return UIEdgeInsetsMake(0, 0, 0, 0); +} + +@end diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" index 5a4fc1ea..60fab8c0 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" @@ -7,17 +7,21 @@ // #import "SLScrollviewNesteVC.h" +#import "SLMenuView.h" ///mainScrollView头部高度 -static CGFloat mainScrollViewHeadHeight = 300; +static CGFloat mainScrollViewHeadHeight = 250; +///选项卡高度 +static CGFloat tabHeight = 50; -@interface SLScrollviewNesteVC () +@interface SLScrollviewNesteVC () @property (nonatomic, strong) UIScrollView *mainScrollView; +@property (nonatomic, strong) UIImageView *headView; @property (nonatomic, strong) UIView *containerView; -@property (nonatomic, strong) UITableView *tableView1; -@property (nonatomic, strong) UITableView *tableView2; +@property (nonatomic, strong) SLMenuView *menuView; +@property (nonatomic, strong) UIScrollView *tabScrollView; @property (nonatomic, strong) NSMutableArray *dataSource; @@ -28,24 +32,53 @@ @implementation SLScrollviewNesteVC #pragma mark - Override - (void)viewDidLoad { [super viewDidLoad]; + self.view.backgroundColor = [UIColor whiteColor]; + [self setupUI]; } +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + self.navigationController.navigationBar.hidden = YES; +} +- (void)viewDidDisappear:(BOOL)animated { + [super viewDidDisappear:animated]; + self.navigationController.navigationBar.hidden = NO; +} #pragma mark - UI - (void)setupUI { - self.view.backgroundColor = [UIColor whiteColor]; + [self.view addSubview:self.mainScrollView]; - [self.mainScrollView addSubview:self.containerView]; - self.containerView.frame = CGRectMake(0, mainScrollViewHeadHeight, SL_kScreenWidth, SL_kScreenHeight-SL_TopNavigationBarHeight); - self.mainScrollView.contentSize = CGSizeMake(SL_kScreenWidth, self.containerView.sl_y+self.containerView.sl_height); + [self.mainScrollView addSubview:self.headView]; + self.headView.frame = CGRectMake(0, 0, self.mainScrollView.sl_width, mainScrollViewHeadHeight); + self.containerView.frame = CGRectMake(0, mainScrollViewHeadHeight, SL_kScreenWidth, SL_kScreenHeight-SL_TopNavigationBarHeight); + [self.mainScrollView addSubview:self.containerView]; + self.mainScrollView.contentSize = CGSizeMake(SL_kScreenWidth, mainScrollViewHeadHeight+self.containerView.sl_height); -// self.containerView.contentSize = CGSizeMake(SL_kScreenWidth*2, self.containerView.sl_y+self.containerView.sl_height); -// [self.containerView addSubview:self.tableView1]; -// [self.containerView addSubview:self.tableView2]; + [self.containerView addSubview:self.menuView]; + [self.menuView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.top.mas_equalTo(0); + make.height.mas_equalTo(tabHeight); + }]; + self.menuView.titles = @[@"你好",@"我好",@"大家好"]; + self.menuView.currentPage = 0; + [self.containerView addSubview:self.tabScrollView]; + [self.tabScrollView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.bottom.mas_equalTo(self.containerView); + make.top.mas_equalTo(tabHeight); + }]; + [self.containerView layoutIfNeeded]; + self.tabScrollView.contentSize = CGSizeMake(SL_kScreenWidth*self.menuView.titles.count,self.tabScrollView.frame.size.height); + for (int i = 0; i < self.menuView.titles.count; i++) { + UITableView *tableView = [self tableView]; + tableView.tag = i; + tableView.frame = CGRectMake(i*self.tabScrollView.sl_width, 0, self.tabScrollView.sl_width, self.tabScrollView.sl_height); + [self.tabScrollView addSubview:tableView]; + } } #pragma mark - Data @@ -54,15 +87,22 @@ - (void)setupUI { - (UIScrollView *)mainScrollView { if (!_mainScrollView) { _mainScrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; - _mainScrollView.backgroundColor = [UIColor orangeColor]; + _mainScrollView.delegate = self; if (@available(iOS 11.0, *)) { _mainScrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; } else { - // Fallback on earlier versions } } return _mainScrollView; } +- (UIImageView *)headView { + if (!_headView) { + _headView = [[UIImageView alloc] init]; + _headView.image = [UIImage imageNamed:@"wsl"]; + _headView.contentMode = UIViewContentModeScaleAspectFit; + } + return _headView; +} - (UIView *)containerView { if (!_containerView) { _containerView = [[UIView alloc] init]; @@ -70,35 +110,39 @@ - (UIView *)containerView { } return _containerView; } -- (UITableView *)tableView1 { - if (!_tableView1) { - _tableView1 = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, SL_kScreenWidth, SL_kScreenHeight) style:UITableViewStyleGrouped]; - _tableView1.delegate = self; - _tableView1.dataSource = self; - _tableView1.estimatedRowHeight = 0; - if (@available(iOS 11.0, *)) { - _tableView1.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; - } else { - // Fallback on earlier versions - } - [_tableView1 registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cellId"]; +- (SLMenuView *)menuView { + if (!_menuView) { + _menuView = [[SLMenuView alloc] init]; + _menuView.backgroundColor = [UIColor orangeColor]; + _menuView.delegate = self; } - return _tableView1; -} -- (UITableView *)tableView2 { - if (!_tableView2) { - _tableView2 = [[UITableView alloc] initWithFrame:CGRectMake(SL_kScreenWidth, 0, SL_kScreenWidth, SL_kScreenHeight) style:UITableViewStyleGrouped]; - _tableView2.delegate = self; - _tableView2.dataSource = self; - _tableView2.estimatedRowHeight = 0; + return _menuView; +} +- (UIScrollView *)tabScrollView { + if (!_tabScrollView) { + _tabScrollView = [[UIScrollView alloc] init]; + _tabScrollView.backgroundColor = [UIColor blueColor]; + _tabScrollView.pagingEnabled = YES; + _tabScrollView.delegate = self; + _tabScrollView.bounces = NO; if (@available(iOS 11.0, *)) { - _tableView2.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + _tabScrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; } else { - // Fallback on earlier versions } - [_tableView2 registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cellId"]; } - return _tableView2; + return _tabScrollView; +} +- (UITableView *)tableView { + UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped]; + tableView.delegate = self; + tableView.dataSource = self; + tableView.estimatedRowHeight = 0; + if (@available(iOS 11.0, *)) { + tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } else { + } + [tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cellId"]; + return tableView; } - (NSMutableArray *)dataSource { if (_dataSource == nil) { @@ -137,12 +181,24 @@ - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cellId" forIndexPath:indexPath]; - cell.textLabel.text = tableView == self.tableView1 ? @"tableView1" : @"tableView2"; + cell.textLabel.text = [NSString stringWithFormat:@"%ld",indexPath.row]; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; } +#pragma mark - SLMenuViewDelegate +- (void)menuView:(SLMenuView *)menuView didSelectItemAtIndex:(NSInteger)index { + [self.tabScrollView setContentOffset:CGPointMake(index* self.tabScrollView.sl_width, 0) animated:YES]; +} + +#pragma mark - UIScrollViewDelegate +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + if (scrollView == self.tabScrollView) { + self.menuView.currentPage = roundf(self.tabScrollView.contentOffset.x/self.tabScrollView.sl_width); + } +} + @end From f5db892fd2db0c1c9e26864bee1626ae9a16523c Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 3 Sep 2020 21:07:03 +0800 Subject: [PATCH 199/356] =?UTF-8?q?=E5=A4=9A=E4=B8=AAScrollView=E5=B5=8C?= =?UTF-8?q?=E5=A5=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SLMenuView.h" | 1 + .../SLMenuView.m" | 27 ++++++++++++++++--- .../SLScrollviewNesteVC.m" | 16 ++++++++++- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLMenuView.h" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLMenuView.h" index d2e55310..0e9ea39a 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLMenuView.h" +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLMenuView.h" @@ -19,6 +19,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, weak) iddelegate; @property (nonatomic, strong) NSArray *titles; @property (nonatomic, assign) NSInteger currentPage; + @end NS_ASSUME_NONNULL_END diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLMenuView.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLMenuView.m" index a03f7cab..a0b5db33 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLMenuView.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLMenuView.m" @@ -37,22 +37,32 @@ - (UILabel *)titleLabel { @interface SLMenuView () @property (nonatomic, strong) UICollectionView *collectionView; +@property (nonatomic, strong) UIView *indicatorView; @end @implementation SLMenuView #pragma mark - Override - (void)didMoveToSuperview { if (self.superview) { - [self addSubview:self.collectionView]; - self.collectionView.frame = self.bounds; + [self setupUI]; } } - (void)didMoveToWindow { if (self.superview) { - [self addSubview:self.collectionView]; - self.collectionView.frame = self.bounds; + [self setupUI]; } } +- (void)layoutSubviews { + self.collectionView.frame = self.bounds; + NSInteger count = self.titles.count == 0 ? 1 : self.titles.count; + self.indicatorView.frame = CGRectMake(_currentPage*self.bounds.size.width/count, self.bounds.size.height-2, self.bounds.size.width/count, 2); +} + +#pragma mark - UI +- (void)setupUI { + [self addSubview:self.collectionView]; + [self addSubview:self.indicatorView]; +} #pragma mark - Getter - (UICollectionView *)collectionView { @@ -68,10 +78,19 @@ - (UICollectionView *)collectionView { } return _collectionView; } +- (UIView *)indicatorView { + if (!_indicatorView) { + _indicatorView = [[UIView alloc] init]; + _indicatorView.backgroundColor = [UIColor blueColor]; + } + return _indicatorView; +} #pragma mark - Setter - (void)setCurrentPage:(NSInteger)currentPage { _currentPage = currentPage; + NSInteger count = self.titles.count == 0 ? 1 : self.titles.count; + self.indicatorView.frame = CGRectMake(_currentPage*self.bounds.size.width/count, self.bounds.size.height-2, self.bounds.size.width/count, 2); [self.collectionView reloadData]; } diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" index 60fab8c0..03282cb2 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" @@ -14,6 +14,11 @@ ///选项卡高度 static CGFloat tabHeight = 50; +@interface SLTableView : UITableView +@end + + + @interface SLScrollviewNesteVC () @property (nonatomic, strong) UIScrollView *mainScrollView; @@ -33,7 +38,6 @@ @implementation SLScrollviewNesteVC - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; - [self setupUI]; } - (void)viewWillAppear:(BOOL)animated { @@ -76,6 +80,7 @@ - (void)setupUI { for (int i = 0; i < self.menuView.titles.count; i++) { UITableView *tableView = [self tableView]; tableView.tag = i; + tableView.scrollEnabled = NO; tableView.frame = CGRectMake(i*self.tabScrollView.sl_width, 0, self.tabScrollView.sl_width, self.tabScrollView.sl_height); [self.tabScrollView addSubview:tableView]; } @@ -100,6 +105,7 @@ - (UIImageView *)headView { _headView = [[UIImageView alloc] init]; _headView.image = [UIImage imageNamed:@"wsl"]; _headView.contentMode = UIViewContentModeScaleAspectFit; + _headView.backgroundColor = [UIColor orangeColor]; } return _headView; } @@ -195,6 +201,14 @@ - (void)menuView:(SLMenuView *)menuView didSelectItemAtIndex:(NSInteger)index { #pragma mark - UIScrollViewDelegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView { + +} +- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { + if (scrollView == self.tabScrollView) { + self.menuView.currentPage = roundf(self.tabScrollView.contentOffset.x/self.tabScrollView.sl_width); + } +} +- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { if (scrollView == self.tabScrollView) { self.menuView.currentPage = roundf(self.tabScrollView.contentOffset.x/self.tabScrollView.sl_width); } From 74640a614a5ca33aea6327801b08c723cac1a448 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 3 Sep 2020 21:24:48 +0800 Subject: [PATCH 200/356] =?UTF-8?q?ScrollView=E5=B5=8C=E5=A5=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SLScrollviewNesteVC.m" | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" index 03282cb2..b8dc1799 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" @@ -201,6 +201,16 @@ - (void)menuView:(SLMenuView *)menuView didSelectItemAtIndex:(NSInteger)index { #pragma mark - UIScrollViewDelegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView { + if (scrollView == self.mainScrollView) { + if (self.mainScrollView.contentOffset.y >= mainScrollViewHeadHeight-SL_TopNavigationBarHeight) { + //滑到了顶部,悬停,开启子列表滑动功能 + for (UIView *subView in self.tabScrollView.subviews) { + if ([subView isKindOfClass:[UITableView class]]) { + [(UITableView *)subView setScrollEnabled:YES]; + } + } + } + } } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { From a8817b1ea47b33d43b9dab05d114d57012598719 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 3 Sep 2020 22:26:51 +0800 Subject: [PATCH 201/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 2 ++ 1 file changed, 2 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 862659ec..61c7a3ad 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -67,3 +67,5 @@ * 8、[有赞coder](公众号:youzan_coder) * 9、[58技术](公众号:architects_58) * 10、[音视频开发进阶](公众号:glumes_blog) +* 11、[五分钟学算法](公众号:CXYxiaowu) +* 12、[iOS成长之路](公众号:gh_fa77b2df3538) From 499d5a11c19f8abb51afe07ca0c11cd3707cc62d Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 4 Sep 2020 11:42:33 +0800 Subject: [PATCH 202/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index d5da26a2..e1b4e327 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -63,6 +63,7 @@ > [iOS优化篇之App启动时间优化](https://juejin.im/post/6861917375382929415) > [iOS如何提高10倍以上编译速度](https://juejin.im/post/6844904169124397070) > [为什么 Debug Information Format 改为 DWARF 可以提高编译速度?](https://zhuanlan.zhihu.com/p/112764192) +> [移动 APP 网络优化概述](http://blog.cnbang.net/tech/3531/) ## 二、数据结构与算法 From 3c6e42542761975df865e4f181c310d91920e4c7 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 4 Sep 2020 18:15:14 +0800 Subject: [PATCH 203/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 2 ++ 1 file changed, 2 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 61c7a3ad..9dce1b1a 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -69,3 +69,5 @@ * 10、[音视频开发进阶](公众号:glumes_blog) * 11、[五分钟学算法](公众号:CXYxiaowu) * 12、[iOS成长之路](公众号:gh_fa77b2df3538) +* 13、[京东零售技术](公众号:jd-sys) +* 14、[携程技术](公众号:ctriptech) From 4af40f9f3c334bd907448f7c5d3497dd89cc242f Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 4 Sep 2020 19:04:35 +0800 Subject: [PATCH 204/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...1\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 9dce1b1a..235b7984 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -54,6 +54,7 @@ * 52、[薛定諤](https://juejin.im/user/325111170210045) * 53、[Mr_Coder](https://juejin.im/user/3544481220795998) * 54、[冬瓜逛逼乎](https://www.zhihu.com/people/desgard-duan) +* 55、[bestswifter](https://github.com/bestswifter) ## 高质量微信公众号 From 2284c973cb9a7a0c380cf77b7e45638bb4485e23 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 7 Sep 2020 18:31:09 +0800 Subject: [PATCH 205/356] =?UTF-8?q?UIScrollView=E5=B5=8C=E5=A5=97-?= =?UTF-8?q?=E4=BB=BF=E6=8E=98=E9=87=91=E4=B8=AA=E4=BA=BA=E4=B8=AD=E5=BF=83?= =?UTF-8?q?=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nav_return_white.imageset/Contents.json | 22 +++++ .../nav_return_white@2x.png | Bin 0 -> 1365 bytes .../nav_return_white@3x.png | Bin 0 -> 1595 bytes .../SLMenuView.m" | 4 +- .../SLScrollviewNesteVC.m" | 77 ++++++++++++++---- 5 files changed, 84 insertions(+), 19 deletions(-) create mode 100644 iOS_Tips/DarkMode/Assets.xcassets/nav_return_white.imageset/Contents.json create mode 100644 iOS_Tips/DarkMode/Assets.xcassets/nav_return_white.imageset/nav_return_white@2x.png create mode 100644 iOS_Tips/DarkMode/Assets.xcassets/nav_return_white.imageset/nav_return_white@3x.png diff --git a/iOS_Tips/DarkMode/Assets.xcassets/nav_return_white.imageset/Contents.json b/iOS_Tips/DarkMode/Assets.xcassets/nav_return_white.imageset/Contents.json new file mode 100644 index 00000000..87b7a55a --- /dev/null +++ b/iOS_Tips/DarkMode/Assets.xcassets/nav_return_white.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "nav_return_white@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "nav_return_white@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS_Tips/DarkMode/Assets.xcassets/nav_return_white.imageset/nav_return_white@2x.png b/iOS_Tips/DarkMode/Assets.xcassets/nav_return_white.imageset/nav_return_white@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c949317de65571519768a8fa77c60ae2054ed006 GIT binary patch literal 1365 zcmeAS@N?(olHy`uVBq!ia0vp^VnD3I!3HFI*-p&`Qj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS=07?{;ELn2Bde0{8v^K*7iAWdWaj57fJ{tG z$}cUkRRX#c;)UD-xUqS~&|m@vn0`fKfxe-h0mw@*g}%P{mFDKcRTq~8r6Sym)!^cg z%7Rq=pw#00(xPNw#HA^NtSYc_E=o--$uA1Y&(DE{Vn9ZINq%ugeu09sGbq%|6*R&# z^HTE5i#5S|e0{Av^NLFn^O93NU2K(rrs!p6rdU}RJ6Rf-x)~cAJG&Yhx|%zho4B}I zI$1cnm>4^`8acuAy5uL9=BDPA!1Sgd^qSz*3rY^T1wfl!Qj0RnQd8WD@^cly-nPob z?G{6v=0WwQ;C71N@Uj$6r`o$OTGB7Y6 z^>lFzskpUfy03;yphVmI9!2iS2Hb|J&SEO5>SjT+HVLV6-_+PRHOMQ>Yuh576!TfS zUK@p0PyDp`WAKubNgV;l{MUVdF>lY^XV1^gd4H|=^}XVAm(9P|eYfpBzb)7M1xJIV z0izJ3Vx~Y&Lq~CK-pVfCm8{3V{V(J?wCs{tf%~P{fPddBc$e5dXkC)MAfjJfOO`dh z?*sc8Ci(Lx!&iu%51uNYU~%_O&61@GUYFD_OwHUEo+)}m{UvY4scpx)x5&jzFyUKO zy!NzeF1zQXye1?4{YJMRFjT0&6w>(g%g>0{$1-=x?M$Ql(@O4hG>EPW3cVBWvHr8G zK+a^7mo~|#UEc5sU1jA}vz(;o!RK(o=Qi#Ows+b&iOHHTNa-Sf_59WG z(?7qw9;3gW*=9n`>DS`Vmfj5!kD2s`_Zvn_HLiaQp>U@=3GQSUD%XZ{*_KsKn#vQOEX5<%m^OxknxU zEtMlx#u2JNrC&@H$X=HDJ7})4o@y9RlSt@(jz2<4vI+g~e5MP$X4tLtbAtbe^-dfv fj><3oh$b+EB_7~+yTg1NRM2_4`njxgN@xNA!pq}} literal 0 HcmV?d00001 diff --git a/iOS_Tips/DarkMode/Assets.xcassets/nav_return_white.imageset/nav_return_white@3x.png b/iOS_Tips/DarkMode/Assets.xcassets/nav_return_white.imageset/nav_return_white@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..8ef689b3b3fbb16b04fd2def0c159cdf5967cb91 GIT binary patch literal 1595 zcmeAS@N?(olHy`uVBq!ia0vp^ia>0}!3HEf%|G}6DajJoh?3y^w370~qErUQl>DSr z1<%~X^wgl##FWaylc_cg49seoArU1JzCKpT`MG+DAT@dwxdlMo3=B5*6$OdO*{LN8 zNvY|XdA3ULckfqH$V{%1*XSQL?vFu&J;D8jzb> zlBiITo0C^;Rbi_HHrEQs1_|pcDS(xfWZNo192Makpx~Tel&WB=XQrEMXl$WiZmDNz zYH49)qN8ABU}&aqV5x6tqHADiWngJ#V5k5ENh+i#(Mch>H3D2mX`VkM*2oZxQ#zd*s+85C;f3L4>= zc`5nj#hPF}zP?tTdBr7(dC94sF1AWQQ}i-3Q>-kEos5hujEs$qom~wLUCo``j7*$d zOkE6|O^l44ot$8LUGkGlb5rw5V0u#!dQEWZ1to{v0-((DOJ9vxH2VI4&M?7Y=se=1f}X)U_a1AScAccZ*<6W3QQ@ z3pcl6uY!_>O47nL3K@!BN{*~sg}PV#I1p|!@kiNTza8S!UVF}&dwl1Ijc?xEo0I)VJm7XmltE;$z9aBdgN+JoO7PwZ)7%>A(GPrh_R z6nCSaL?}z2Q{kVo6Ojwp>sZ;Rzqi)fzMRMdc$sfnPe9FWBEU#DHjTdUH+Odkmra9HqZ`CcnvmXKkcd&n+9CuB} zX$6b%>FkkqWZxRO5>KZW+Bs)F6~^as>}?N?Y>zWlRN1*frT<00 zw3E`+Dd8W5)m!v-oECnnyRdb_mgIeWXQGp43pp97mP>^`dMuRB)TqDVpqGQjrXMpz zb==w#E)+$o35hr7>K0tDy=BstEHx)M?^I$$cB#M1I-b{|F8dCPX>*=03!m4TSZa{B zcgEG^-OP5{i;JxMp3X^a*m|hg^@)^8gs028nBD6;Y?@fZgeGd=_UbyJ9g(LhxbxH7 zCoI};{D3CN{aBmg)4#Ok0&DWA6*8X2t&>Z#+P8Ok*k6hC^K_ch!^7`4C>cG=OA+SuH~+)qlH&D#+msIv%@_5Y>O6UEO{L4` zmiyeUPmIoNnDpV{cLzbqmdY?8yFcqRl$+KerAf3NUOUvRQkzO`-9NADfh8-(%>7`&N&@rU*ShR+)woaPO9c@b2c Nd%F6$taD0e0sy98R +{ + UIImage *_backgroundImage; + UIImage *_shadowImage; +} +@property (nonatomic, strong) UIView *navigationView; @property (nonatomic, strong) UIScrollView *mainScrollView; @property (nonatomic, strong) UIImageView *headView; @@ -78,21 +87,40 @@ - (void)setupUI { self.tabScrollView.contentSize = CGSizeMake(SL_kScreenWidth*self.menuView.titles.count,self.tabScrollView.frame.size.height); for (int i = 0; i < self.menuView.titles.count; i++) { - UITableView *tableView = [self tableView]; + SLPanTableView *tableView = [self tableView]; tableView.tag = i; - tableView.scrollEnabled = NO; tableView.frame = CGRectMake(i*self.tabScrollView.sl_width, 0, self.tabScrollView.sl_width, self.tabScrollView.sl_height); [self.tabScrollView addSubview:tableView]; } + + + [self.view addSubview:self.navigationView]; } #pragma mark - Data #pragma mark - Getter +- (UIView *)navigationView { + if (!_navigationView) { + _navigationView = [[UIView alloc] initWithFrame:CGRectMake(0, 0,SL_kScreenWidth , SL_TopNavigationBarHeight)]; + _navigationView.backgroundColor = [UIColor clearColor]; + UIButton *nav_return_white = [[UIButton alloc] init]; + [nav_return_white setImage:[UIImage imageNamed:@"nav_return_white"] forState:UIControlStateNormal]; + [nav_return_white addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside]; + [_navigationView addSubview:nav_return_white]; + [nav_return_white mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(10); + make.size.mas_equalTo(CGSizeMake(15, 20)); + make.bottom.mas_equalTo(-10); + }]; + } + return _navigationView; +} - (UIScrollView *)mainScrollView { if (!_mainScrollView) { _mainScrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; _mainScrollView.delegate = self; + _mainScrollView.bounces = NO; if (@available(iOS 11.0, *)) { _mainScrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; } else { @@ -105,7 +133,7 @@ - (UIImageView *)headView { _headView = [[UIImageView alloc] init]; _headView.image = [UIImage imageNamed:@"wsl"]; _headView.contentMode = UIViewContentModeScaleAspectFit; - _headView.backgroundColor = [UIColor orangeColor]; + _headView.backgroundColor = [UIColor colorWithRed:11/255.0 green:112/255.0 blue:230/255.0 alpha:1.0];; } return _headView; } @@ -119,8 +147,10 @@ - (UIView *)containerView { - (SLMenuView *)menuView { if (!_menuView) { _menuView = [[SLMenuView alloc] init]; - _menuView.backgroundColor = [UIColor orangeColor]; + _menuView.backgroundColor = [UIColor colorWithRed:248/255.0 green:248/255.0 blue:248/255.0 alpha:1.0]; _menuView.delegate = self; + _menuView.layer.borderWidth = 1.0; + _menuView.layer.borderColor = [UIColor colorWithRed:228/255.0 green:228/255.0 blue:228/255.0 alpha:1.0].CGColor; } return _menuView; } @@ -138,8 +168,8 @@ - (UIScrollView *)tabScrollView { } return _tabScrollView; } -- (UITableView *)tableView { - UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped]; +- (SLPanTableView *)tableView { + SLPanTableView *tableView = [[SLPanTableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped]; tableView.delegate = self; tableView.dataSource = self; tableView.estimatedRowHeight = 0; @@ -160,6 +190,9 @@ - (NSMutableArray *)dataSource { #pragma mark - Data #pragma mark - EventsHandle +- (void)back { + [self.navigationController popViewControllerAnimated:YES]; +} #pragma mark - HelpMethods @@ -202,16 +235,27 @@ - (void)menuView:(SLMenuView *)menuView didSelectItemAtIndex:(NSInteger)index { #pragma mark - UIScrollViewDelegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView { if (scrollView == self.mainScrollView) { - if (self.mainScrollView.contentOffset.y >= mainScrollViewHeadHeight-SL_TopNavigationBarHeight) { + //根据偏移量操作导航栏 + if(self.mainScrollView.contentOffset.y == mainScrollViewHeadHeight-SL_TopNavigationBarHeight) { + self.navigationController.navigationBar.hidden = NO; + }else { + self.navigationController.navigationBar.hidden = YES; + } + if (self.mainScrollView.contentOffset.y > mainScrollViewHeadHeight-SL_TopNavigationBarHeight) { //滑到了顶部,悬停,开启子列表滑动功能 - for (UIView *subView in self.tabScrollView.subviews) { - if ([subView isKindOfClass:[UITableView class]]) { - [(UITableView *)subView setScrollEnabled:YES]; - } - } + self.mainScrollView.contentOffset = CGPointMake(0, mainScrollViewHeadHeight-SL_TopNavigationBarHeight); + } + } + + //子列表 + if (scrollView.superview == self.tabScrollView) { + if (self.mainScrollView.contentOffset.y < mainScrollViewHeadHeight-SL_TopNavigationBarHeight) { + scrollView.contentOffset = CGPointMake(0, 0); } } + + } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { if (scrollView == self.tabScrollView) { @@ -224,5 +268,4 @@ - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { } } - @end From b8cb417514528278ee5b95ed7ad2d2b5b2a6c2c8 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 8 Sep 2020 18:38:35 +0800 Subject: [PATCH 206/356] =?UTF-8?q?=E6=8E=98=E9=87=91APP=E4=B8=AA=E4=BA=BA?= =?UTF-8?q?=E4=B8=AD=E5=BF=83=E9=A1=B5=E7=9A=84ScrollView=E5=B5=8C?= =?UTF-8?q?=E5=A5=97=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 18 ++ .../WorkIssues/SLWorkIssuesViewController.m | 2 +- .../SLPanTableView.h" | 17 ++ .../SLPanTableView.m" | 16 ++ .../SLScrollViewJuejin.h" | 18 ++ .../SLScrollViewWeibo.h" | 18 ++ .../SLScrollViewWeibo.m" | 37 +++ .../SLScrollviewNesteVC.h" | 2 +- .../SLScrollviewNesteVC.m" | 268 +++--------------- iOS_Tips/Podfile | 3 + 10 files changed, 168 insertions(+), 231 deletions(-) create mode 100644 "iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLPanTableView.h" create mode 100644 "iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLPanTableView.m" create mode 100644 "iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJuejin.h" create mode 100644 "iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.h" create mode 100644 "iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 36e52f97..59d1e6e7 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -129,6 +129,9 @@ 788ADB382441F48F00302CD9 /* SLCrashViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 788ADB362441F48F00302CD9 /* SLCrashViewController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 78908DC324FFBE5D004164C2 /* SLScrollviewNesteVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 78908DC224FFBE5D004164C2 /* SLScrollviewNesteVC.m */; }; 78908DCD2500F099004164C2 /* SLMenuView.m in Sources */ = {isa = PBXBuildFile; fileRef = 78908DCC2500F099004164C2 /* SLMenuView.m */; }; + 78908DFA25078F84004164C2 /* SLScrollViewJuejin.m in Sources */ = {isa = PBXBuildFile; fileRef = 78908DF925078F84004164C2 /* SLScrollViewJuejin.m */; }; + 78908DFD25079323004164C2 /* SLScrollViewWeibo.m in Sources */ = {isa = PBXBuildFile; fileRef = 78908DFC25079323004164C2 /* SLScrollViewWeibo.m */; }; + 78908E0025079451004164C2 /* SLPanTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 78908DFF25079451004164C2 /* SLPanTableView.m */; }; 789AD16324C99DCA00CB0B4C /* SLAPMThreadCount.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD16224C99DCA00CB0B4C /* SLAPMThreadCount.m */; }; 789AD1C824D7FA5F00CB0B4C /* SLAPMURLProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD1C724D7FA5F00CB0B4C /* SLAPMURLProtocol.m */; }; 789AD1CF24D9024300CB0B4C /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 789AD1CD24D9024300CB0B4C /* Reachability.m */; }; @@ -406,6 +409,12 @@ 78908DC224FFBE5D004164C2 /* SLScrollviewNesteVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLScrollviewNesteVC.m; sourceTree = ""; }; 78908DCB2500F099004164C2 /* SLMenuView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLMenuView.h; sourceTree = ""; }; 78908DCC2500F099004164C2 /* SLMenuView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLMenuView.m; sourceTree = ""; }; + 78908DF825078F84004164C2 /* SLScrollViewJuejin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLScrollViewJuejin.h; sourceTree = ""; }; + 78908DF925078F84004164C2 /* SLScrollViewJuejin.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLScrollViewJuejin.m; sourceTree = ""; }; + 78908DFB25079323004164C2 /* SLScrollViewWeibo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLScrollViewWeibo.h; sourceTree = ""; }; + 78908DFC25079323004164C2 /* SLScrollViewWeibo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLScrollViewWeibo.m; sourceTree = ""; }; + 78908DFE25079451004164C2 /* SLPanTableView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLPanTableView.h; sourceTree = ""; }; + 78908DFF25079451004164C2 /* SLPanTableView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLPanTableView.m; sourceTree = ""; }; 789AD16124C99DCA00CB0B4C /* SLAPMThreadCount.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMThreadCount.h; sourceTree = ""; }; 789AD16224C99DCA00CB0B4C /* SLAPMThreadCount.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLAPMThreadCount.m; sourceTree = ""; }; 789AD1C624D7FA5F00CB0B4C /* SLAPMURLProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLAPMURLProtocol.h; sourceTree = ""; }; @@ -949,6 +958,12 @@ children = ( 78908DC124FFBE5D004164C2 /* SLScrollviewNesteVC.h */, 78908DC224FFBE5D004164C2 /* SLScrollviewNesteVC.m */, + 78908DF825078F84004164C2 /* SLScrollViewJuejin.h */, + 78908DF925078F84004164C2 /* SLScrollViewJuejin.m */, + 78908DFB25079323004164C2 /* SLScrollViewWeibo.h */, + 78908DFC25079323004164C2 /* SLScrollViewWeibo.m */, + 78908DFE25079451004164C2 /* SLPanTableView.h */, + 78908DFF25079451004164C2 /* SLPanTableView.m */, 78908DCB2500F099004164C2 /* SLMenuView.h */, 78908DCC2500F099004164C2 /* SLMenuView.m */, ); @@ -1492,6 +1507,7 @@ 78DAA113235FF61E00A60F64 /* SLEditVideoClipping.m in Sources */, 782E3EB42373D8C7001E0DF9 /* SLAvWriterInput.m in Sources */, 789AD1D524D97F8500CB0B4C /* SLSystemAppInfo.m in Sources */, + 78908DFD25079323004164C2 /* SLScrollViewWeibo.m in Sources */, 78804A7E237D5E3E0087E152 /* SLWaterMarkController.m in Sources */, 78EF8B6024162B96008D0CD7 /* SLMenuViewController.m in Sources */, 7869C72224A8B6D200527546 /* SLPictureBrowseController.m in Sources */, @@ -1525,6 +1541,7 @@ 787C7DBF245D74E4005DF7ED /* NSMutableDictionary+SLCrashProtector.m in Sources */, 7830A5A42358904600BC79BA /* UIView+SLImage.m in Sources */, 78A35B1C23978A5D004BCCB7 /* SLShaderCubeViewController.m in Sources */, + 78908E0025079451004164C2 /* SLPanTableView.m in Sources */, 787C7DC0245D74E4005DF7ED /* NSDictionary+SLCrashProtector.m in Sources */, 78E1791723517F700007E4BB /* SLImageView.m in Sources */, 78E1791823517F700007E4BB /* SLImage.m in Sources */, @@ -1536,6 +1553,7 @@ 78E72D542477A4E700751373 /* SLWebTableViewController.m in Sources */, 2CEBE85D24A6E65600BA21F3 /* SLTimer.m in Sources */, 783504642452C20B0071283E /* SLMethod.m in Sources */, + 78908DFA25078F84004164C2 /* SLScrollViewJuejin.m in Sources */, 784C4BE124BC40D200D5C199 /* SLAPMViewController.m in Sources */, 787C7E4524656524005DF7ED /* UIView+SLMLeakFinder.m in Sources */, 789AD1CF24D9024300CB0B4C /* Reachability.m in Sources */, diff --git a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m index 8cda68f6..36910a88 100644 --- a/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m +++ b/iOS_Tips/DarkMode/WorkIssues/SLWorkIssuesViewController.m @@ -55,7 +55,7 @@ - (void)getData { @"二进制重排优化启动时间", @"iOS APM应用性能监控管理(doing)", @"ipa瘦身之扫描无用资源", - @"多个UIScrollView嵌套(doing)"]]; + @"多个UIScrollView嵌套"]]; [self.urlArray addObjectsFromArray:@[@"", @"https://juejin.im/post/5c0e1e73f265da616413d828", @"https://juejin.im/post/5c0e1df95188250d2722a3bc", diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLPanTableView.h" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLPanTableView.h" new file mode 100644 index 00000000..94a9c149 --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLPanTableView.h" @@ -0,0 +1,17 @@ +// +// SLPanTableView.h +// DarkMode +// +// Created by wsl on 2020/9/8. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +///此类主要用于TableView的滑动手势向下层传递 +@interface SLPanTableView : UITableView +@end + +NS_ASSUME_NONNULL_END diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLPanTableView.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLPanTableView.m" new file mode 100644 index 00000000..919c7534 --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLPanTableView.m" @@ -0,0 +1,16 @@ +// +// SLPanTableView.m +// DarkMode +// +// Created by wsl on 2020/9/8. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLPanTableView.h" + +@implementation SLPanTableView +//是否允许多个手势识别器共同识别,一个控件的手势识别后是否阻断手势识别继续向下传播,默认返回NO,上层对象识别后则不再继续传播;如果为YES,响应者链上层对象触发手势识别后,如果下层对象也添加了手势并成功识别也会继续执行。 +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { + return [gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]; +} +@end diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJuejin.h" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJuejin.h" new file mode 100644 index 00000000..88bffbe2 --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJuejin.h" @@ -0,0 +1,18 @@ +// +// SLScrollViewJuejin.h +// DarkMode +// +// Created by wsl on 2020/9/8. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +///掘金APP个人中心页的ScrollView嵌套样式 +@interface SLScrollViewJuejin : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.h" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.h" new file mode 100644 index 00000000..20a7330e --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.h" @@ -0,0 +1,18 @@ +// +// SLScrollViewWeibo.h +// DarkMode +// +// Created by wsl on 2020/9/8. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +///微博发现页ScrollView嵌套样式 +@interface SLScrollViewWeibo : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" new file mode 100644 index 00000000..9c1d2756 --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" @@ -0,0 +1,37 @@ +// +// SLScrollViewWeibo.m +// DarkMode +// +// Created by wsl on 2020/9/8. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLScrollViewWeibo.h" +#import "SLMenuView.h" +#import +#import "SLPanTableView.h" + +@interface SLScrollViewWeibo () + +@property (nonatomic, strong) UIView *navigationView; +@property (nonatomic, strong) UIScrollView *mainScrollView; +@property (nonatomic, strong) UIImageView *headView; +@property (nonatomic, assign) BOOL isTopHovering; //正在顶部悬停 + +@property (nonatomic, strong) UIView *containerView; +@property (nonatomic, strong) SLMenuView *menuView; +@property (nonatomic, strong) UIScrollView *tabScrollView; + +@property (nonatomic, assign) NSInteger dataCount; //默认 20 +@end + +@implementation SLScrollViewWeibo + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + + + +@end diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.h" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.h" index 80431081..4491ab4a 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.h" +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.h" @@ -11,7 +11,7 @@ NS_ASSUME_NONNULL_BEGIN ///多个ScrollView/TableView/CollectionView嵌套 -@interface SLScrollviewNesteVC : UIViewController +@interface SLScrollviewNesteVC : UITableViewController @end diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" index 3ef40ca3..b9632290 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" @@ -7,265 +7,75 @@ // #import "SLScrollviewNesteVC.h" -#import "SLMenuView.h" - -///mainScrollView头部高度 -static CGFloat mainScrollViewHeadHeight = 300; -///选项卡高度 -static CGFloat tabHeight = 50; - -@interface SLPanTableView : UITableView -@end -@implementation SLPanTableView -//是否允许多个手势识别器共同识别,一个控件的手势识别后是否阻断手势识别继续向下传播,默认返回NO,上层对象识别后则不再继续传播;如果为YES,响应者链上层对象触发手势识别后,如果下层对象也添加了手势并成功识别也会继续执行。 -- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { - return [gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]; -} -@end - -@interface SLScrollviewNesteVC () -{ - UIImage *_backgroundImage; - UIImage *_shadowImage; -} - -@property (nonatomic, strong) UIView *navigationView; -@property (nonatomic, strong) UIScrollView *mainScrollView; -@property (nonatomic, strong) UIImageView *headView; - -@property (nonatomic, strong) UIView *containerView; -@property (nonatomic, strong) SLMenuView *menuView; -@property (nonatomic, strong) UIScrollView *tabScrollView; - -@property (nonatomic, strong) NSMutableArray *dataSource; +#import "SLScrollViewJuejin.h" +#import "SLScrollViewWeibo.h" +@interface SLScrollviewNesteVC () +@property (nonatomic, strong) NSMutableArray *titlesArray; +@property (nonatomic, strong) NSMutableArray *classArray; @end @implementation SLScrollviewNesteVC -#pragma mark - Override - (void)viewDidLoad { [super viewDidLoad]; - self.view.backgroundColor = [UIColor whiteColor]; [self setupUI]; + [self getData]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - self.navigationController.navigationBar.hidden = YES; -} -- (void)viewDidDisappear:(BOOL)animated { - [super viewDidDisappear:animated]; self.navigationController.navigationBar.hidden = NO; } +- (BOOL)prefersStatusBarHidden { + return NO; +} #pragma mark - UI - (void)setupUI { - - [self.view addSubview:self.mainScrollView]; - - [self.mainScrollView addSubview:self.headView]; - self.headView.frame = CGRectMake(0, 0, self.mainScrollView.sl_width, mainScrollViewHeadHeight); - - self.containerView.frame = CGRectMake(0, mainScrollViewHeadHeight, SL_kScreenWidth, SL_kScreenHeight-SL_TopNavigationBarHeight); - [self.mainScrollView addSubview:self.containerView]; - self.mainScrollView.contentSize = CGSizeMake(SL_kScreenWidth, mainScrollViewHeadHeight+self.containerView.sl_height); - - [self.containerView addSubview:self.menuView]; - [self.menuView mas_makeConstraints:^(MASConstraintMaker *make) { - make.left.right.top.mas_equalTo(0); - make.height.mas_equalTo(tabHeight); - }]; - self.menuView.titles = @[@"你好",@"我好",@"大家好"]; - self.menuView.currentPage = 0; - - [self.containerView addSubview:self.tabScrollView]; - [self.tabScrollView mas_makeConstraints:^(MASConstraintMaker *make) { - make.left.right.bottom.mas_equalTo(self.containerView); - make.top.mas_equalTo(tabHeight); - }]; - [self.containerView layoutIfNeeded]; - self.tabScrollView.contentSize = CGSizeMake(SL_kScreenWidth*self.menuView.titles.count,self.tabScrollView.frame.size.height); - - for (int i = 0; i < self.menuView.titles.count; i++) { - SLPanTableView *tableView = [self tableView]; - tableView.tag = i; - tableView.frame = CGRectMake(i*self.tabScrollView.sl_width, 0, self.tabScrollView.sl_width, self.tabScrollView.sl_height); - [self.tabScrollView addSubview:tableView]; - } - - - [self.view addSubview:self.navigationView]; + self.navigationController.navigationBar.translucent = YES; + self.tableView.estimatedRowHeight = 1; + [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cellID"]; } #pragma mark - Data +- (void)getData { + [self.titlesArray addObjectsFromArray:@[ + @"掘金APP个人中心页样式", + @"微博发现页ScrollView嵌套样式"]]; + [self.classArray addObjectsFromArray:@[[SLScrollViewJuejin class], + [SLScrollViewWeibo class]]]; + [self.tableView reloadData]; +} #pragma mark - Getter -- (UIView *)navigationView { - if (!_navigationView) { - _navigationView = [[UIView alloc] initWithFrame:CGRectMake(0, 0,SL_kScreenWidth , SL_TopNavigationBarHeight)]; - _navigationView.backgroundColor = [UIColor clearColor]; - UIButton *nav_return_white = [[UIButton alloc] init]; - [nav_return_white setImage:[UIImage imageNamed:@"nav_return_white"] forState:UIControlStateNormal]; - [nav_return_white addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside]; - [_navigationView addSubview:nav_return_white]; - [nav_return_white mas_makeConstraints:^(MASConstraintMaker *make) { - make.left.mas_equalTo(10); - make.size.mas_equalTo(CGSizeMake(15, 20)); - make.bottom.mas_equalTo(-10); - }]; - } - return _navigationView; -} -- (UIScrollView *)mainScrollView { - if (!_mainScrollView) { - _mainScrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; - _mainScrollView.delegate = self; - _mainScrollView.bounces = NO; - if (@available(iOS 11.0, *)) { - _mainScrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; - } else { - } - } - return _mainScrollView; -} -- (UIImageView *)headView { - if (!_headView) { - _headView = [[UIImageView alloc] init]; - _headView.image = [UIImage imageNamed:@"wsl"]; - _headView.contentMode = UIViewContentModeScaleAspectFit; - _headView.backgroundColor = [UIColor colorWithRed:11/255.0 green:112/255.0 blue:230/255.0 alpha:1.0];; - } - return _headView; -} -- (UIView *)containerView { - if (!_containerView) { - _containerView = [[UIView alloc] init]; - _containerView.backgroundColor = [UIColor redColor]; - } - return _containerView; -} -- (SLMenuView *)menuView { - if (!_menuView) { - _menuView = [[SLMenuView alloc] init]; - _menuView.backgroundColor = [UIColor colorWithRed:248/255.0 green:248/255.0 blue:248/255.0 alpha:1.0]; - _menuView.delegate = self; - _menuView.layer.borderWidth = 1.0; - _menuView.layer.borderColor = [UIColor colorWithRed:228/255.0 green:228/255.0 blue:228/255.0 alpha:1.0].CGColor; - } - return _menuView; -} -- (UIScrollView *)tabScrollView { - if (!_tabScrollView) { - _tabScrollView = [[UIScrollView alloc] init]; - _tabScrollView.backgroundColor = [UIColor blueColor]; - _tabScrollView.pagingEnabled = YES; - _tabScrollView.delegate = self; - _tabScrollView.bounces = NO; - if (@available(iOS 11.0, *)) { - _tabScrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; - } else { - } +- (NSMutableArray *)titlesArray { + if (_titlesArray == nil) { + _titlesArray = [NSMutableArray array]; } - return _tabScrollView; + return _titlesArray; } -- (SLPanTableView *)tableView { - SLPanTableView *tableView = [[SLPanTableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped]; - tableView.delegate = self; - tableView.dataSource = self; - tableView.estimatedRowHeight = 0; - if (@available(iOS 11.0, *)) { - tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; - } else { +- (NSMutableArray *)classArray { + if (_classArray == nil) { + _classArray = [NSMutableArray array]; } - [tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cellId"]; - return tableView; -} -- (NSMutableArray *)dataSource { - if (_dataSource == nil) { - _dataSource = [NSMutableArray array]; - } - return _dataSource; -} - -#pragma mark - Data - -#pragma mark - EventsHandle -- (void)back { - [self.navigationController popViewControllerAnimated:YES]; + return _classArray; } -#pragma mark - HelpMethods - -#pragma mark - UITableViewDelegate,UITableViewDataSource -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return 1; -} -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return 20; -} -- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { - return 100; -} -- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { - return 0.1; -} -- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { - return nil; -} -- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { - return 0.1; +#pragma mark - UITableViewDelegate, UITableViewDataSource +- (NSInteger)tableView:(nonnull UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return self.titlesArray.count; } -- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { - return nil; -} -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cellId" forIndexPath:indexPath]; - cell.textLabel.text = [NSString stringWithFormat:@"%ld",indexPath.row]; +- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath { + UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cellID" forIndexPath:indexPath]; + cell.textLabel.numberOfLines = 0; + cell.textLabel.text = [NSString stringWithFormat:@"%ld、%@",(long)indexPath.row,self.titlesArray[indexPath.row]]; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - [tableView deselectRowAtIndexPath:indexPath animated:YES]; -} - -#pragma mark - SLMenuViewDelegate -- (void)menuView:(SLMenuView *)menuView didSelectItemAtIndex:(NSInteger)index { - [self.tabScrollView setContentOffset:CGPointMake(index* self.tabScrollView.sl_width, 0) animated:YES]; -} - -#pragma mark - UIScrollViewDelegate -- (void)scrollViewDidScroll:(UIScrollView *)scrollView { - if (scrollView == self.mainScrollView) { - //根据偏移量操作导航栏 - if(self.mainScrollView.contentOffset.y == mainScrollViewHeadHeight-SL_TopNavigationBarHeight) { - self.navigationController.navigationBar.hidden = NO; - }else { - self.navigationController.navigationBar.hidden = YES; - } - if (self.mainScrollView.contentOffset.y > mainScrollViewHeadHeight-SL_TopNavigationBarHeight) { - //滑到了顶部,悬停,开启子列表滑动功能 - self.mainScrollView.contentOffset = CGPointMake(0, mainScrollViewHeadHeight-SL_TopNavigationBarHeight); - } - } - - //子列表 - if (scrollView.superview == self.tabScrollView) { - if (self.mainScrollView.contentOffset.y < mainScrollViewHeadHeight-SL_TopNavigationBarHeight) { - scrollView.contentOffset = CGPointMake(0, 0); - } - } - - - -} -- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { - if (scrollView == self.tabScrollView) { - self.menuView.currentPage = roundf(self.tabScrollView.contentOffset.x/self.tabScrollView.sl_width); - } -} -- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { - if (scrollView == self.tabScrollView) { - self.menuView.currentPage = roundf(self.tabScrollView.contentOffset.x/self.tabScrollView.sl_width); - } + [tableView deselectRowAtIndexPath:indexPath animated:NO]; + UIViewController *nextVc = [[self.classArray[indexPath.row] alloc] init]; + nextVc.navigationItem.title = self.titlesArray[indexPath.row]; + [self.navigationController pushViewController:nextVc animated:YES]; } @end diff --git a/iOS_Tips/Podfile b/iOS_Tips/Podfile index b30ba260..8d5c5100 100644 --- a/iOS_Tips/Podfile +++ b/iOS_Tips/Podfile @@ -1,4 +1,5 @@ source 'https://github.com/CocoaPods/Specs.git' +#source 'https://gitee.com/mirrors/CocoaPods-Specs.git' platform :ios,’10.0’ target "DarkMode" do pod 'GPUImage' @@ -8,4 +9,6 @@ pod 'Masonry' pod 'YYImage' pod 'YYWebImage' pod 'YYModel' +pod 'YYModel' +pod 'MJRefresh' end From 73a0a3ecf376edf88daec9fb3395181ff3e2f637 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 8 Sep 2020 18:38:46 +0800 Subject: [PATCH 207/356] =?UTF-8?q?=E6=8E=98=E9=87=91APP=E4=B8=AA=E4=BA=BA?= =?UTF-8?q?=E4=B8=AD=E5=BF=83=E9=A1=B5=E7=9A=84ScrollView=E5=B5=8C?= =?UTF-8?q?=E5=A5=97=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SLScrollViewJuejin.m" | 291 ++++++++++++++++++ 1 file changed, 291 insertions(+) create mode 100644 "iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJuejin.m" diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJuejin.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJuejin.m" new file mode 100644 index 00000000..12ca0239 --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJuejin.m" @@ -0,0 +1,291 @@ +// +// SLScrollViewJuejin.m +// DarkMode +// +// Created by wsl on 2020/9/8. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLScrollViewJuejin.h" +#import "SLMenuView.h" +#import +#import "SLPanTableView.h" + +///mainScrollView头部高度 +static CGFloat mainScrollViewHeadHeight = 250; +///选项卡/菜单栏高度 +static CGFloat tabHeight = 50; + +@interface SLScrollViewJuejin () + +@property (nonatomic, strong) UIView *navigationView; +@property (nonatomic, strong) UIScrollView *mainScrollView; +@property (nonatomic, strong) UIImageView *headView; +@property (nonatomic, assign) BOOL isTopHovering; //正在顶部悬停 + +@property (nonatomic, strong) UIView *containerView; +@property (nonatomic, strong) SLMenuView *menuView; +@property (nonatomic, strong) UIScrollView *tabScrollView; + +@property (nonatomic, assign) NSInteger dataCount; //默认 20 + +@end + +@implementation SLScrollViewJuejin + +#pragma mark - Override +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor whiteColor]; + [self getData]; + [self setupUI]; +} +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + self.navigationController.navigationBar.hidden = YES; +} +- (void)viewDidDisappear:(BOOL)animated { + [super viewDidDisappear:animated]; + self.navigationController.navigationBar.hidden = NO; +} + +#pragma mark - UI +- (void)setupUI { + + [self.view addSubview:self.mainScrollView]; + + [self.mainScrollView addSubview:self.headView]; + self.headView.frame = CGRectMake(0, 0, 100, 100); + self.headView.center = CGPointMake(SL_kScreenWidth/2.0, mainScrollViewHeadHeight/2.0); + + self.containerView.frame = CGRectMake(0, mainScrollViewHeadHeight, SL_kScreenWidth, SL_kScreenHeight-SL_TopNavigationBarHeight); + [self.mainScrollView addSubview:self.containerView]; + self.mainScrollView.contentSize = CGSizeMake(SL_kScreenWidth, mainScrollViewHeadHeight+self.containerView.sl_height); + + [self.containerView addSubview:self.menuView]; + [self.menuView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.top.mas_equalTo(0); + make.height.mas_equalTo(tabHeight); + }]; + self.menuView.titles = @[@"你好",@"我好",@"大家好"]; + self.menuView.currentPage = 0; + + [self.containerView addSubview:self.tabScrollView]; + [self.tabScrollView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.bottom.mas_equalTo(self.containerView); + make.top.mas_equalTo(tabHeight); + }]; + [self.containerView layoutIfNeeded]; + self.tabScrollView.contentSize = CGSizeMake(SL_kScreenWidth*self.menuView.titles.count,self.tabScrollView.frame.size.height); + + for (int i = 0; i < self.menuView.titles.count; i++) { + SLPanTableView *tableView = [self subTableView]; + tableView.tag = 10+i; + tableView.frame = CGRectMake(i*self.tabScrollView.sl_width, 0, self.tabScrollView.sl_width, self.tabScrollView.sl_height); + [self.tabScrollView addSubview:tableView]; + } + + [self.view addSubview:self.navigationView]; +} + +#pragma mark - Data +- (void)getData { + self.dataCount = 20; +} + +#pragma mark - Getter +- (UIView *)navigationView { + if (!_navigationView) { + _navigationView = [[UIView alloc] initWithFrame:CGRectMake(0, 0,SL_kScreenWidth , SL_TopNavigationBarHeight)]; + _navigationView.backgroundColor = [UIColor clearColor]; + UIButton *nav_return_white = [[UIButton alloc] init]; + [nav_return_white setImage:[UIImage imageNamed:@"nav_return_white"] forState:UIControlStateNormal]; + [nav_return_white addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside]; + [_navigationView addSubview:nav_return_white]; + [nav_return_white mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(10); + make.size.mas_equalTo(CGSizeMake(15, 20)); + make.bottom.mas_equalTo(-10); + }]; + } + return _navigationView; +} +- (UIScrollView *)mainScrollView { + if (!_mainScrollView) { + _mainScrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; + _mainScrollView.delegate = self; + _mainScrollView.bounces = NO; + _mainScrollView.showsVerticalScrollIndicator = NO; + _mainScrollView.backgroundColor = [UIColor colorWithRed:11/255.0 green:112/255.0 blue:230/255.0 alpha:1.0]; + if (@available(iOS 11.0, *)) { + _mainScrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } else { + } + } + return _mainScrollView; +} +- (UIImageView *)headView { + if (!_headView) { + _headView = [[UIImageView alloc] init]; + _headView.image = [UIImage imageNamed:@"wsl"]; + _headView.contentMode = UIViewContentModeScaleAspectFit; + _headView.layer.cornerRadius = 50; + _headView.clipsToBounds = YES; + } + return _headView; +} +- (UIView *)containerView { + if (!_containerView) { + _containerView = [[UIView alloc] init]; + _containerView.backgroundColor = [UIColor redColor]; + } + return _containerView; +} +- (SLMenuView *)menuView { + if (!_menuView) { + _menuView = [[SLMenuView alloc] init]; + _menuView.backgroundColor = [UIColor colorWithRed:248/255.0 green:248/255.0 blue:248/255.0 alpha:1.0]; + _menuView.delegate = self; + _menuView.layer.borderWidth = 1.0; + _menuView.layer.borderColor = [UIColor colorWithRed:228/255.0 green:228/255.0 blue:228/255.0 alpha:1.0].CGColor; + } + return _menuView; +} +- (UIScrollView *)tabScrollView { + if (!_tabScrollView) { + _tabScrollView = [[UIScrollView alloc] init]; + _tabScrollView.backgroundColor = [UIColor blueColor]; + _tabScrollView.pagingEnabled = YES; + _tabScrollView.delegate = self; + _tabScrollView.bounces = NO; + if (@available(iOS 11.0, *)) { + _tabScrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } else { + } + } + return _tabScrollView; +} +- (SLPanTableView *)subTableView { + SLPanTableView *tableView = [[SLPanTableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped]; + tableView.delegate = self; + tableView.dataSource = self; + tableView.estimatedRowHeight = 0; + if (@available(iOS 11.0, *)) { + tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } else { + } + [tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cellId"]; + SL_WeakSelf; + tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{ + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + weakSelf.dataCount = 20; + [tableView reloadData]; + [tableView.mj_header endRefreshing]; + }); + }]; + tableView.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingBlock:^{ + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + weakSelf.dataCount += 20; + [tableView reloadData]; + [tableView.mj_footer endRefreshing]; + }); + }]; + return tableView; +} + +#pragma mark - Data + +#pragma mark - EventsHandle +- (void)back { + [self.navigationController popViewControllerAnimated:YES]; +} + +#pragma mark - HelpMethods +///当前子列表 +- (SLPanTableView *)currentSubListTabView { + return [self.tabScrollView viewWithTag:10+self.menuView.currentPage]; +} + +#pragma mark - UITableViewDelegate,UITableViewDataSource +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return self.dataCount; +} +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + return 88; +} +- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { + return 0.1; +} +- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { + return nil; +} +- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { + return 0.1; +} +- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { + return nil; +} +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cellId" forIndexPath:indexPath]; + cell.textLabel.text = [NSString stringWithFormat:@"%ld",indexPath.row]; + return cell; +} +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [tableView deselectRowAtIndexPath:indexPath animated:YES]; +} + +#pragma mark - SLMenuViewDelegate +- (void)menuView:(SLMenuView *)menuView didSelectItemAtIndex:(NSInteger)index { + [self.tabScrollView setContentOffset:CGPointMake(index* self.tabScrollView.sl_width, 0) animated:YES]; +} + +#pragma mark - UIScrollViewDelegate +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + + if (scrollView == self.tabScrollView) return; + + if (scrollView == self.mainScrollView) { + if (self.mainScrollView.contentOffset.y >= mainScrollViewHeadHeight-SL_TopNavigationBarHeight || _isTopHovering) { + //滑到顶部悬停 + _isTopHovering = YES; + self.mainScrollView.contentOffset = CGPointMake(0, mainScrollViewHeadHeight-SL_TopNavigationBarHeight); + } + if(_isTopHovering) { + self.navigationController.navigationBar.hidden = NO; + }else { + self.navigationController.navigationBar.hidden = YES; + } + } + + //子列表 + if (scrollView.superview == self.tabScrollView) { + if(!_isTopHovering && self.mainScrollView.contentOffset.y > 0) { + //如果主mainScrollView还未到顶部悬停,则选项子列表subTableView偏移量保持不变 + scrollView.contentOffset = CGPointZero; + } + if(_isTopHovering && scrollView.contentOffset.y > 0) { + //如果主mainScrollView在顶部悬停,而此时选项子列表subTableView还未到顶部,则保持mainScrollView继续悬停 + self.mainScrollView.contentOffset = CGPointMake(0, mainScrollViewHeadHeight-SL_TopNavigationBarHeight); + } + if (scrollView.contentOffset.y < 0) { + //如果subTableView滑动到了顶部,即将取消顶部悬停 + _isTopHovering = NO; + } + } +} +- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { + if (scrollView == self.tabScrollView) { + self.menuView.currentPage = roundf(self.tabScrollView.contentOffset.x/self.tabScrollView.sl_width); + } +} +- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { + if (scrollView == self.tabScrollView) { + self.menuView.currentPage = roundf(self.tabScrollView.contentOffset.x/self.tabScrollView.sl_width); + } +} + +@end + From 1bd142eb506d9118435f0529b1ecbdeb87341142 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 8 Sep 2020 18:42:28 +0800 Subject: [PATCH 208/356] =?UTF-8?q?=E5=BE=AE=E5=8D=9A=E5=8F=91=E7=8E=B0?= =?UTF-8?q?=E9=A1=B5ScrollView=E5=B5=8C=E5=A5=97=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SLScrollViewWeibo.m" | 254 +++++++++++++++++- .../SLScrollviewNesteVC.m" | 2 +- 2 files changed, 254 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" index 9c1d2756..54115e14 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" @@ -11,6 +11,11 @@ #import #import "SLPanTableView.h" +///mainScrollView头部高度 +static CGFloat mainScrollViewHeadHeight = 250; +///选项卡/菜单栏高度 +static CGFloat tabHeight = 50; + @interface SLScrollViewWeibo () @property (nonatomic, strong) UIView *navigationView; @@ -27,11 +32,258 @@ @interface SLScrollViewWeibo ()= mainScrollViewHeadHeight-SL_TopNavigationBarHeight || _isTopHovering) { + //滑到顶部悬停 + _isTopHovering = YES; + self.mainScrollView.contentOffset = CGPointMake(0, mainScrollViewHeadHeight-SL_TopNavigationBarHeight); + } + if(_isTopHovering) { + self.navigationController.navigationBar.hidden = NO; + }else { + self.navigationController.navigationBar.hidden = YES; + } + } + + //子列表 + if (scrollView.superview == self.tabScrollView) { + if(!_isTopHovering && self.mainScrollView.contentOffset.y > 0) { + //如果主mainScrollView还未到顶部悬停,则选项子列表subTableView偏移量保持不变 + scrollView.contentOffset = CGPointZero; + } + if(_isTopHovering && scrollView.contentOffset.y > 0) { + //如果主mainScrollView在顶部悬停,而此时选项子列表subTableView还未到顶部,则保持mainScrollView继续悬停 + self.mainScrollView.contentOffset = CGPointMake(0, mainScrollViewHeadHeight-SL_TopNavigationBarHeight); + } + if (scrollView.contentOffset.y < 0) { + //如果subTableView滑动到了顶部,即将取消顶部悬停 + _isTopHovering = NO; + } + } +} +- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { + if (scrollView == self.tabScrollView) { + self.menuView.currentPage = roundf(self.tabScrollView.contentOffset.x/self.tabScrollView.sl_width); + } +} +- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { + if (scrollView == self.tabScrollView) { + self.menuView.currentPage = roundf(self.tabScrollView.contentOffset.x/self.tabScrollView.sl_width); + } +} @end diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" index b9632290..ec7e0298 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" @@ -41,7 +41,7 @@ - (void)setupUI { - (void)getData { [self.titlesArray addObjectsFromArray:@[ @"掘金APP个人中心页样式", - @"微博发现页ScrollView嵌套样式"]]; + @"微博发现页ScrollView嵌套样式doing"]]; [self.classArray addObjectsFromArray:@[[SLScrollViewJuejin class], [SLScrollViewWeibo class]]]; [self.tableView reloadData]; From 3a06bab02d279a3842d6d2a7623ff04b5d3b4c2b Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 9 Sep 2020 10:00:28 +0800 Subject: [PATCH 209/356] =?UTF-8?q?=E5=BE=AE=E5=8D=9A=E5=8F=91=E7=8E=B0?= =?UTF-8?q?=E9=A1=B5ScrollView=E5=B5=8C=E5=A5=97=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SLScrollViewJuejin.m" | 6 +++++- .../SLScrollViewWeibo.m" | 8 +++++++- .../DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 3 ++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJuejin.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJuejin.m" index 12ca0239..3c8bcb14 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJuejin.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJuejin.m" @@ -29,6 +29,8 @@ @interface SLScrollViewJuejin () 0) { //如果主mainScrollView还未到顶部悬停,则选项子列表subTableView偏移量保持不变 - scrollView.contentOffset = CGPointZero; + scrollView.contentOffset = self.lastContentOffset; } if(_isTopHovering && scrollView.contentOffset.y > 0) { //如果主mainScrollView在顶部悬停,而此时选项子列表subTableView还未到顶部,则保持mainScrollView继续悬停 @@ -279,11 +281,13 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView { - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { if (scrollView == self.tabScrollView) { self.menuView.currentPage = roundf(self.tabScrollView.contentOffset.x/self.tabScrollView.sl_width); + self.lastContentOffset = [self currentSubListTabView].contentOffset; } } - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { if (scrollView == self.tabScrollView) { self.menuView.currentPage = roundf(self.tabScrollView.contentOffset.x/self.tabScrollView.sl_width); + self.lastContentOffset = [self currentSubListTabView].contentOffset; } } diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" index 54115e14..b1cbb575 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" @@ -28,6 +28,9 @@ @interface SLScrollViewWeibo () 0) { //如果主mainScrollView还未到顶部悬停,则选项子列表subTableView偏移量保持不变 - scrollView.contentOffset = CGPointZero; + scrollView.contentOffset = self.lastContentOffset; + } if(_isTopHovering && scrollView.contentOffset.y > 0) { //如果主mainScrollView在顶部悬停,而此时选项子列表subTableView还未到顶部,则保持mainScrollView继续悬停 @@ -278,11 +282,13 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView { - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { if (scrollView == self.tabScrollView) { self.menuView.currentPage = roundf(self.tabScrollView.contentOffset.x/self.tabScrollView.sl_width); + self.lastContentOffset = [self currentSubListTabView].contentOffset; } } - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { if (scrollView == self.tabScrollView) { self.menuView.currentPage = roundf(self.tabScrollView.contentOffset.x/self.tabScrollView.sl_width); + self.lastContentOffset = [self currentSubListTabView].contentOffset; } } diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index e1b4e327..d86f99ec 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -56,7 +56,8 @@ > [基于clang插件的一种iOS包大小瘦身方案](https://mp.weixin.qq.com/s?__biz=MzUxMzcxMzE5Ng==&mid=2247488360&idx=1&sn=94fba30a87d0f9bc0b9ff94d3fed3386&source=41#wechat_redirect) > [iOS 启动速度优化和安装包优化简单总结](https://juejin.im/post/6844903821387235341) > [iOS代码瘦身实践:删除无用的类](https://juejin.im/post/6844903921169727496) -> [优化 App 的启动时间](http://yulingtianxia.com/blog/2016/10/30/Optimizing-App-Startup-Time/) +> [优化 App 的启动时间](http://yulingtianxia.com/blog/2016/10/30/Optimizing-App-Startup-Time/) +> [AppStartTime](https://github.com/JunyiXie/AppStartTime) > [iOS App 启动性能优化](https://mp.weixin.qq.com/s/Kf3EbDIUuf0aWVT-UCEmbA) > [iOS一次立竿见影的启动时间优化](https://juejin.im/post/6844903525172903944) > [iOS Dynamic Framework 对App启动时间影响实测](https://www.jianshu.com/p/3263009e9228) From c561107121a541858da0691377ec0f678fad62c8 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 9 Sep 2020 10:21:01 +0800 Subject: [PATCH 210/356] =?UTF-8?q?///=E5=BE=AE=E5=8D=9A=E5=8F=91=E7=8E=B0?= =?UTF-8?q?=E9=A1=B5ScrollView=E5=B5=8C=E5=A5=97=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SLScrollViewJuejin.m" | 10 +++++++--- .../SLScrollViewWeibo.m" | 7 ++++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJuejin.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJuejin.m" index 3c8bcb14..b63e05dc 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJuejin.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJuejin.m" @@ -27,9 +27,10 @@ @interface SLScrollViewJuejin () 0) { //如果主mainScrollView还未到顶部悬停,则选项子列表subTableView偏移量保持不变 + if (scrollView.contentOffset.y < 0) { + self.lastContentOffset = CGPointZero; + } scrollView.contentOffset = self.lastContentOffset; } if(_isTopHovering && scrollView.contentOffset.y > 0) { diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" index b1cbb575..597a0aa9 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" @@ -29,7 +29,8 @@ @interface SLScrollViewWeibo () 0) { //如果主mainScrollView还未到顶部悬停,则选项子列表subTableView偏移量保持不变 + //如果主mainScrollView还未到顶部悬停,则选项子列表subTableView偏移量保持不变 + if (scrollView.contentOffset.y < 0) { + self.lastContentOffset = CGPointZero; + } scrollView.contentOffset = self.lastContentOffset; } From 657ce04c48d46f8cfdee76b9c8ad41fbe811fd4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Wed, 9 Sep 2020 11:09:26 +0800 Subject: [PATCH 211/356] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bf5734a7..43eb0ac9 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,8 @@ >> 6.6、iOS 自定义转场动画 >> 6.7、二进制重排优化启动速度 >> 6.8、iOS APM应用性能监控管理(doing) ->> 6.9、ipa瘦身之扫描无用资源 +>> 6.9、ipa瘦身之扫描无用资源 +>> 6.10、多个UIScrollView嵌套/个人中心页 > 7、[iOS Crash防护](#7-iOSCrash防护) > 8、[WKWebView相关](#8-WKWebView相关) From 2c38801591d4b5bb0bab7d4677071e642d3552a4 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 9 Sep 2020 11:56:40 +0800 Subject: [PATCH 212/356] =?UTF-8?q?=E5=BE=AE=E5=8D=9A=E5=8F=91=E7=8E=B0?= =?UTF-8?q?=E9=A1=B5ScrollView=E5=B5=8C=E5=A5=97=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SLScrollViewWeibo.m" | 54 +++++++++++-------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" index 597a0aa9..4105046b 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" @@ -14,7 +14,7 @@ ///mainScrollView头部高度 static CGFloat mainScrollViewHeadHeight = 250; ///选项卡/菜单栏高度 -static CGFloat tabHeight = 50; +static CGFloat tabHeight = 64; @interface SLScrollViewWeibo () @@ -61,7 +61,7 @@ - (void)setupUI { self.headView.frame = CGRectMake(0, 0, 100, 100); self.headView.center = CGPointMake(SL_kScreenWidth/2.0, mainScrollViewHeadHeight/2.0); - self.containerView.frame = CGRectMake(0, mainScrollViewHeadHeight, SL_kScreenWidth, SL_kScreenHeight-SL_TopNavigationBarHeight); + self.containerView.frame = CGRectMake(0, mainScrollViewHeadHeight, SL_kScreenWidth, SL_kScreenHeight); [self.mainScrollView addSubview:self.containerView]; self.mainScrollView.contentSize = CGSizeMake(SL_kScreenWidth, mainScrollViewHeadHeight+self.containerView.sl_height); @@ -84,6 +84,7 @@ - (void)setupUI { for (int i = 0; i < self.menuView.titles.count; i++) { SLPanTableView *tableView = [self subTableView]; tableView.tag = 10+i; + tableView.scrollEnabled = NO; tableView.frame = CGRectMake(i*self.tabScrollView.sl_width, 0, self.tabScrollView.sl_width, self.tabScrollView.sl_height); [self.tabScrollView addSubview:tableView]; } @@ -108,7 +109,7 @@ - (UIView *)navigationView { [nav_return_white mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(10); make.size.mas_equalTo(CGSizeMake(15, 20)); - make.bottom.mas_equalTo(-10); + make.bottom.mas_equalTo(-20); }]; } return _navigationView; @@ -117,13 +118,19 @@ - (UIScrollView *)mainScrollView { if (!_mainScrollView) { _mainScrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; _mainScrollView.delegate = self; - _mainScrollView.bounces = NO; _mainScrollView.showsVerticalScrollIndicator = NO; _mainScrollView.backgroundColor = [UIColor colorWithRed:11/255.0 green:112/255.0 blue:230/255.0 alpha:1.0]; if (@available(iOS 11.0, *)) { _mainScrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; } else { } + SL_WeakSelf + _mainScrollView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{ + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + weakSelf.dataCount = 20; + [weakSelf.mainScrollView.mj_header endRefreshing]; + }); + }]; } return _mainScrollView; } @@ -147,7 +154,7 @@ - (UIView *)containerView { - (SLMenuView *)menuView { if (!_menuView) { _menuView = [[SLMenuView alloc] init]; - _menuView.backgroundColor = [UIColor colorWithRed:248/255.0 green:248/255.0 blue:248/255.0 alpha:1.0]; + _menuView.backgroundColor = [UIColor orangeColor]; _menuView.delegate = self; _menuView.layer.borderWidth = 1.0; _menuView.layer.borderColor = [UIColor colorWithRed:228/255.0 green:228/255.0 blue:228/255.0 alpha:1.0].CGColor; @@ -200,7 +207,11 @@ - (SLPanTableView *)subTableView { #pragma mark - EventsHandle - (void)back { - [self.navigationController popViewControllerAnimated:YES]; + if (self.isTopHovering) { + [self.mainScrollView setContentOffset:CGPointZero animated:YES]; + }else { + [self.navigationController popViewControllerAnimated:YES]; + } } #pragma mark - HelpMethods @@ -250,19 +261,15 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView { if (scrollView == self.tabScrollView) return; - if (scrollView == self.mainScrollView) { - if (self.mainScrollView.contentOffset.y >= mainScrollViewHeadHeight-SL_TopNavigationBarHeight || _isTopHovering) { - //滑到顶部悬停 - _isTopHovering = YES; - self.mainScrollView.contentOffset = CGPointMake(0, mainScrollViewHeadHeight-SL_TopNavigationBarHeight); - } - if(_isTopHovering) { - self.navigationController.navigationBar.hidden = NO; - }else { - self.navigationController.navigationBar.hidden = YES; - } - } +// if (scrollView == self.mainScrollView) { +// if (self.mainScrollView.contentOffset.y >= mainScrollViewHeadHeight || _isTopHovering) { +// //滑到顶部悬停 +// _isTopHovering = YES; +// self.mainScrollView.contentOffset = CGPointMake(0, mainScrollViewHeadHeight); +// } +// } + /* //子列表 if (scrollView.superview == self.tabScrollView) { if(!_isTopHovering && self.mainScrollView.contentOffset.y > 0) { @@ -276,13 +283,14 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView { } if(_isTopHovering && scrollView.contentOffset.y > 0) { //如果主mainScrollView在顶部悬停,而此时选项子列表subTableView还未到顶部,则保持mainScrollView继续悬停 - self.mainScrollView.contentOffset = CGPointMake(0, mainScrollViewHeadHeight-SL_TopNavigationBarHeight); - } - if (scrollView.contentOffset.y < 0) { - //如果subTableView滑动到了顶部,即将取消顶部悬停 - _isTopHovering = NO; + self.mainScrollView.contentOffset = CGPointMake(0, mainScrollViewHeadHeight); } +// if (scrollView.contentOffset.y < 0) { +// //如果subTableView滑动到了顶部,即将取消顶部悬停 +// _isTopHovering = NO; +// } } + */ } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { if (scrollView == self.tabScrollView) { From a2dd2c20e05259fd3b7501c36fd614f8e1e5882a Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 14 Sep 2020 18:17:37 +0800 Subject: [PATCH 213/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 2 ++ ...207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 3 +++ 2 files changed, 5 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index d86f99ec..378d7141 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -83,6 +83,7 @@ * 8、[iOS Rendering 渲染全解析(长文干货)](https://juejin.im/post/6844904162765832206) * 9、[iOS | 面试知识整理 - OC基础 (二)](https://juejin.im/post/6844903945052110856) * 10、[各种精选面试题](https://github.com/iOShuyang/Book-Recommended-Interview) +* 11、[iOS | 面试知识整理 - Swift 基础(九)](https://juejin.im/post/6844903955156336654) ## 四、逆向与安全 @@ -100,6 +101,7 @@ * 1、DSBridge /JSBridge /JSPatch/ * 2、[写给自己看系列之WebViewJavascriptBridge源码分析](https://juejin.im/post/6844904097192247303) +* 3、[OCRunner:完全体的iOS热修复方案](https://silverfruity.github.io/2020/09/04/OCRunner/) ## 七、Shell脚本 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 235b7984..129900c4 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -55,6 +55,8 @@ * 53、[Mr_Coder](https://juejin.im/user/3544481220795998) * 54、[冬瓜逛逼乎](https://www.zhihu.com/people/desgard-duan) * 55、[bestswifter](https://github.com/bestswifter) +* 56、[SilverFruity](https://silverfruity.github.io/) +* 57、[孤单的衬衣](https://juejin.im/user/2735240661962638) ## 高质量微信公众号 @@ -72,3 +74,4 @@ * 12、[iOS成长之路](公众号:gh_fa77b2df3538) * 13、[京东零售技术](公众号:jd-sys) * 14、[携程技术](公众号:ctriptech) +* 15、[字节跳动技术团队](公众号:toutiaotechblog) From 70445d627bc326d6aa1ca77c11d9e8f56863e526 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 14 Sep 2020 18:47:10 +0800 Subject: [PATCH 214/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + ...1\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 2 files changed, 2 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 378d7141..8f285407 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -84,6 +84,7 @@ * 9、[iOS | 面试知识整理 - OC基础 (二)](https://juejin.im/post/6844903945052110856) * 10、[各种精选面试题](https://github.com/iOShuyang/Book-Recommended-Interview) * 11、[iOS | 面试知识整理 - Swift 基础(九)](https://juejin.im/post/6844903955156336654) +* 12、[iOSDevLevelingUp](https://github.com/ShannonChenCHN/iOSDevLevelingUp) ## 四、逆向与安全 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 129900c4..bbd3e4bc 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -57,6 +57,7 @@ * 55、[bestswifter](https://github.com/bestswifter) * 56、[SilverFruity](https://silverfruity.github.io/) * 57、[孤单的衬衣](https://juejin.im/user/2735240661962638) +* 58、[ShannonChenCHN](https://github.com/ShannonChenCHN) ## 高质量微信公众号 From 8f2d24c08aae10fca31d7f9d71417f8ecf161510 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 15 Sep 2020 10:11:35 +0800 Subject: [PATCH 215/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 8f285407..7436dff4 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -92,6 +92,7 @@ * 2、 [iOS程序员的自我修养 - 编译、链接、装载](https://juejin.im/post/5d5273b1f265da03f233c2d6) * 3、[[iOS翻译]编译器](https://juejin.im/post/6854573220612931592) * 4、[Injection:iOS热重载背后的黑魔法](https://mp.weixin.qq.com/s/hFnHdOP6pmIwzZck-zXE8g) +* 5、[高效逆向 - 为任意iOS App生成符号表](https://github.com/imoldman/DSYMCreator) ## 五、音视频 From b3703c963f3b0e71ca35eabfd03993045135716e Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 15 Sep 2020 10:22:46 +0800 Subject: [PATCH 216/356] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WKWebView/WebNative/SLWebNativeViewController.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS_Tips/DarkMode/WKWebView/WebNative/SLWebNativeViewController.m b/iOS_Tips/DarkMode/WKWebView/WebNative/SLWebNativeViewController.m index 30ffa9ec..c6e2a2cd 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebNative/SLWebNativeViewController.m +++ b/iOS_Tips/DarkMode/WKWebView/WebNative/SLWebNativeViewController.m @@ -260,7 +260,7 @@ -(void)observeValueForKeyPath:(NSString *)keyPath // 页面加载完成之后调用 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { [self.frameArray removeAllObjects]; - //根据服务器下发的标签相关的数据,用原生组件展示,这里原生组件的创建要注意按需加载和复用,类似于tableView,否则对内存还是有不小的消耗的。目前还没做处理 + //根据服务器下发的标签相关的数据,用原生组件展示,这里原生组件的创建要注意按需加载和复用,类似于tableView,否则对内存还是有不小的消耗的。 int i = 0; SL_WeakSelf; for (SLWebNativeModel *model in self.dataSource) { From bee31474118856a715357d50de2bc0dca079687a Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 15 Sep 2020 11:57:53 +0800 Subject: [PATCH 217/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...1\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index bbd3e4bc..7209e496 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -58,6 +58,7 @@ * 56、[SilverFruity](https://silverfruity.github.io/) * 57、[孤单的衬衣](https://juejin.im/user/2735240661962638) * 58、[ShannonChenCHN](https://github.com/ShannonChenCHN) +* 59、[木子Lision](https://github.com/Lision) ## 高质量微信公众号 From c8d78b3a248d58f90cc63119d0cabae03a97013a Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 15 Sep 2020 16:17:10 +0800 Subject: [PATCH 218/356] =?UTF-8?q?=E5=BE=AE=E5=8D=9A=E5=8F=91=E7=8E=B0?= =?UTF-8?q?=E9=A1=B5ScrollView=E5=B5=8C=E5=A5=97=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SLScrollViewWeibo.m" | 75 +++++++++---------- 1 file changed, 34 insertions(+), 41 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" index 4105046b..b71e84ea 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" @@ -29,9 +29,6 @@ @interface SLScrollViewWeibo ()= mainScrollViewHeadHeight || _isTopHovering) { -// //滑到顶部悬停 -// _isTopHovering = YES; -// self.mainScrollView.contentOffset = CGPointMake(0, mainScrollViewHeadHeight); -// } -// } - - /* - //子列表 - if (scrollView.superview == self.tabScrollView) { - if(!_isTopHovering && self.mainScrollView.contentOffset.y > 0) { - //如果主mainScrollView还未到顶部悬停,则选项子列表subTableView偏移量保持不变 - //如果主mainScrollView还未到顶部悬停,则选项子列表subTableView偏移量保持不变 - if (scrollView.contentOffset.y < 0) { - self.lastContentOffset = CGPointZero; - } - scrollView.contentOffset = self.lastContentOffset; - - } - if(_isTopHovering && scrollView.contentOffset.y > 0) { - //如果主mainScrollView在顶部悬停,而此时选项子列表subTableView还未到顶部,则保持mainScrollView继续悬停 + if (scrollView == self.mainScrollView) { + if (self.mainScrollView.contentOffset.y >= mainScrollViewHeadHeight && !_isTopHovering) { + //滑到顶部悬停 + _isTopHovering = YES; + self.mainScrollView.scrollEnabled = NO; + self.mainScrollView.bounces = NO; self.mainScrollView.contentOffset = CGPointMake(0, mainScrollViewHeadHeight); + for (int i = 0; i < self.menuView.titles.count; i++) { + UIView *subView = [self.tabScrollView viewWithTag:10+i]; + if ([subView isKindOfClass:[UITableView class]]) { + [(UITableView *)subView setScrollEnabled:YES]; + } + } } -// if (scrollView.contentOffset.y < 0) { -// //如果subTableView滑动到了顶部,即将取消顶部悬停 -// _isTopHovering = NO; -// } } - */ } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { if (scrollView == self.tabScrollView) { self.menuView.currentPage = roundf(self.tabScrollView.contentOffset.x/self.tabScrollView.sl_width); - self.lastContentOffset = [self currentSubListTabView].contentOffset; } } - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { if (scrollView == self.tabScrollView) { self.menuView.currentPage = roundf(self.tabScrollView.contentOffset.x/self.tabScrollView.sl_width); - self.lastContentOffset = [self currentSubListTabView].contentOffset; + } + + if (scrollView == self.mainScrollView && self.mainScrollView.contentOffset.y != mainScrollViewHeadHeight) { + _isTopHovering = NO; + self.mainScrollView.scrollEnabled = YES; + self.mainScrollView.bounces = YES; + for (int i = 0; i < self.menuView.titles.count; i++) { + UIView *subView = [self.tabScrollView viewWithTag:10+i]; + if ([subView isKindOfClass:[UITableView class]]) { + [(UITableView *)subView setScrollEnabled:NO]; + [(UITableView *)subView setContentOffset:CGPointZero]; + } + } } } From 04eb9c29588a08111b3e7b757b38be2a8c02f775 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 15 Sep 2020 17:07:06 +0800 Subject: [PATCH 219/356] =?UTF-8?q?ScrollView=E5=B5=8C=E5=A5=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 6 + .../SLScrollViewJianShu.h" | 17 + .../SLScrollViewJianShu.m" | 302 ++++++++++++++++++ .../SLScrollViewJuejin.m" | 5 +- .../SLScrollViewWeibo.m" | 2 - .../SLScrollviewNesteVC.m" | 7 +- 6 files changed, 332 insertions(+), 7 deletions(-) create mode 100644 "iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJianShu.h" create mode 100644 "iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJianShu.m" diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 59d1e6e7..3bb416a6 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -161,6 +161,7 @@ 78D30965239688EF00DC373A /* GLESMath.c in Sources */ = {isa = PBXBuildFile; fileRef = 78D30960239688EF00DC373A /* GLESMath.c */; }; 78DAA113235FF61E00A60F64 /* SLEditVideoClipping.m in Sources */ = {isa = PBXBuildFile; fileRef = 78DAA112235FF61E00A60F64 /* SLEditVideoClipping.m */; }; 78DAA1162360256200A60F64 /* SLEditSelectedBox.m in Sources */ = {isa = PBXBuildFile; fileRef = 78DAA1152360256200A60F64 /* SLEditSelectedBox.m */; }; + 78DF7F652510B45000F6C007 /* SLScrollViewJianShu.m in Sources */ = {isa = PBXBuildFile; fileRef = 78DF7F642510B45000F6C007 /* SLScrollViewJianShu.m */; }; 78E1791723517F700007E4BB /* SLImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 78E1791223517F700007E4BB /* SLImageView.m */; }; 78E1791823517F700007E4BB /* SLImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 78E1791323517F700007E4BB /* SLImage.m */; }; 78E1791923517F700007E4BB /* SLImageDecoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 78E1791423517F700007E4BB /* SLImageDecoder.m */; }; @@ -473,6 +474,8 @@ 78DAA112235FF61E00A60F64 /* SLEditVideoClipping.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLEditVideoClipping.m; sourceTree = ""; }; 78DAA1142360256200A60F64 /* SLEditSelectedBox.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLEditSelectedBox.h; sourceTree = ""; }; 78DAA1152360256200A60F64 /* SLEditSelectedBox.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLEditSelectedBox.m; sourceTree = ""; }; + 78DF7F632510B45000F6C007 /* SLScrollViewJianShu.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLScrollViewJianShu.h; sourceTree = ""; }; + 78DF7F642510B45000F6C007 /* SLScrollViewJianShu.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLScrollViewJianShu.m; sourceTree = ""; }; 78E1791123517F700007E4BB /* SLImageDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLImageDecoder.h; sourceTree = ""; }; 78E1791223517F700007E4BB /* SLImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLImageView.m; sourceTree = ""; }; 78E1791323517F700007E4BB /* SLImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLImage.m; sourceTree = ""; }; @@ -962,6 +965,8 @@ 78908DF925078F84004164C2 /* SLScrollViewJuejin.m */, 78908DFB25079323004164C2 /* SLScrollViewWeibo.h */, 78908DFC25079323004164C2 /* SLScrollViewWeibo.m */, + 78DF7F632510B45000F6C007 /* SLScrollViewJianShu.h */, + 78DF7F642510B45000F6C007 /* SLScrollViewJianShu.m */, 78908DFE25079451004164C2 /* SLPanTableView.h */, 78908DFF25079451004164C2 /* SLPanTableView.m */, 78908DCB2500F099004164C2 /* SLMenuView.h */, @@ -1500,6 +1505,7 @@ 78FA0FA02354141E003E456B /* SLAvEditExport.m in Sources */, 78A179A8249B0AA8006F52E3 /* NSDictionary+SLExtension.m in Sources */, 78BDE050248E0AFB002ED386 /* SLWebNativeViewController.m in Sources */, + 78DF7F652510B45000F6C007 /* SLScrollViewJianShu.m in Sources */, 78F42023237915730093497C /* SLGPUImageController.m in Sources */, 7860D791239922B4008C53EC /* SLGLKPyramidVC.m in Sources */, 787C7DC3245D74E4005DF7ED /* NSString+SLCrashProtector.m in Sources */, diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJianShu.h" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJianShu.h" new file mode 100644 index 00000000..f046e1fb --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJianShu.h" @@ -0,0 +1,17 @@ +// +// SLScrollViewJianShu.h +// DarkMode +// +// Created by wsl on 2020/9/15. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface SLScrollViewJianShu : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJianShu.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJianShu.m" new file mode 100644 index 00000000..b94ff87d --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJianShu.m" @@ -0,0 +1,302 @@ +// +// SLScrollViewJianShu.m +// DarkMode +// +// Created by wsl on 2020/9/15. +// Copyright © 2020 https://github.com/wsl2ls ----- . All rights reserved. +// + +#import "SLScrollViewJianShu.h" +#import "SLMenuView.h" +#import +#import "SLPanTableView.h" + +///mainScrollView头部高度 +static CGFloat mainScrollViewHeadHeight = 250; +///选项卡/菜单栏高度 +static CGFloat tabHeight = 50; + +@interface SLScrollViewJianShu () + + +@property (nonatomic, strong) UIView *navigationView; +@property (nonatomic, strong) UIScrollView *mainScrollView; +@property (nonatomic, strong) UIImageView *headView; +@property (nonatomic, assign) BOOL isTopHovering; //正在顶部悬停 + +@property (nonatomic, strong) UIView *containerView; +@property (nonatomic, strong) SLMenuView *menuView; +@property (nonatomic, strong) UIScrollView *tabScrollView; + +//默认 20 +@property (nonatomic, assign) NSInteger dataCount; +//滑动到当前子列表时的偏移量,主要处理顶部未悬停且子列表未置顶偏移量不为0时的情况 +@property (nonatomic, assign) CGPoint lastContentOffset; +@end + +@implementation SLScrollViewJianShu + +#pragma mark - Override +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor whiteColor]; + [self setupUI]; + [self getData]; +} +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + self.navigationController.navigationBar.hidden = YES; +} +- (void)viewDidDisappear:(BOOL)animated { + [super viewDidDisappear:animated]; + self.navigationController.navigationBar.hidden = NO; +} + +#pragma mark - UI +- (void)setupUI { + + [self.view addSubview:self.mainScrollView]; + + [self.mainScrollView addSubview:self.headView]; + self.headView.frame = CGRectMake(0, 0, 100, 100); + self.headView.center = CGPointMake(SL_kScreenWidth/2.0, mainScrollViewHeadHeight/2.0); + + self.containerView.frame = CGRectMake(0, mainScrollViewHeadHeight, SL_kScreenWidth, SL_kScreenHeight-SL_TopNavigationBarHeight); + [self.mainScrollView addSubview:self.containerView]; + self.mainScrollView.contentSize = CGSizeMake(SL_kScreenWidth, mainScrollViewHeadHeight+self.containerView.sl_height); + + [self.containerView addSubview:self.menuView]; + [self.menuView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.top.mas_equalTo(0); + make.height.mas_equalTo(tabHeight); + }]; + self.menuView.titles = @[@"你好",@"我好",@"大家好"]; + self.menuView.currentPage = 0; + + [self.containerView addSubview:self.tabScrollView]; + [self.tabScrollView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.bottom.mas_equalTo(self.containerView); + make.top.mas_equalTo(tabHeight); + }]; + [self.containerView layoutIfNeeded]; + self.tabScrollView.contentSize = CGSizeMake(SL_kScreenWidth*self.menuView.titles.count,self.tabScrollView.frame.size.height); + + for (int i = 0; i < self.menuView.titles.count; i++) { + SLPanTableView *tableView = [self subTableView]; + tableView.tag = 10+i; + tableView.frame = CGRectMake(i*self.tabScrollView.sl_width, 0, self.tabScrollView.sl_width, self.tabScrollView.sl_height); + [self.tabScrollView addSubview:tableView]; + } + + [self.view addSubview:self.navigationView]; +} + +#pragma mark - Data +- (void)getData { + self.dataCount = 20; + [[self currentSubListTabView].mj_header beginRefreshing]; +} + +#pragma mark - Getter +- (UIView *)navigationView { + if (!_navigationView) { + _navigationView = [[UIView alloc] initWithFrame:CGRectMake(0, 0,SL_kScreenWidth , SL_TopNavigationBarHeight)]; + _navigationView.backgroundColor = [UIColor clearColor]; + UIButton *nav_return_white = [[UIButton alloc] init]; + [nav_return_white setImage:[UIImage imageNamed:@"nav_return_white"] forState:UIControlStateNormal]; + [nav_return_white addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside]; + [_navigationView addSubview:nav_return_white]; + [nav_return_white mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(10); + make.size.mas_equalTo(CGSizeMake(15, 20)); + make.bottom.mas_equalTo(-10); + }]; + } + return _navigationView; +} +- (UIScrollView *)mainScrollView { + if (!_mainScrollView) { + _mainScrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; + _mainScrollView.delegate = self; + _mainScrollView.bounces = YES; + _mainScrollView.showsVerticalScrollIndicator = NO; + _mainScrollView.backgroundColor = [UIColor colorWithRed:11/255.0 green:112/255.0 blue:230/255.0 alpha:1.0]; + if (@available(iOS 11.0, *)) { + _mainScrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } else { + } + } + return _mainScrollView; +} +- (UIImageView *)headView { + if (!_headView) { + _headView = [[UIImageView alloc] init]; + _headView.image = [UIImage imageNamed:@"wsl"]; + _headView.contentMode = UIViewContentModeScaleAspectFit; + _headView.layer.cornerRadius = 50; + _headView.clipsToBounds = YES; + } + return _headView; +} +- (UIView *)containerView { + if (!_containerView) { + _containerView = [[UIView alloc] init]; + _containerView.backgroundColor = [UIColor redColor]; + } + return _containerView; +} +- (SLMenuView *)menuView { + if (!_menuView) { + _menuView = [[SLMenuView alloc] init]; + _menuView.backgroundColor = [UIColor colorWithRed:248/255.0 green:248/255.0 blue:248/255.0 alpha:1.0]; + _menuView.delegate = self; + _menuView.layer.borderWidth = 1.0; + _menuView.layer.borderColor = [UIColor colorWithRed:228/255.0 green:228/255.0 blue:228/255.0 alpha:1.0].CGColor; + } + return _menuView; +} +- (UIScrollView *)tabScrollView { + if (!_tabScrollView) { + _tabScrollView = [[UIScrollView alloc] init]; + _tabScrollView.backgroundColor = [UIColor blueColor]; + _tabScrollView.pagingEnabled = YES; + _tabScrollView.delegate = self; + _tabScrollView.bounces = NO; + if (@available(iOS 11.0, *)) { + _tabScrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } else { + } + } + return _tabScrollView; +} +- (SLPanTableView *)subTableView { + SLPanTableView *tableView = [[SLPanTableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped]; + tableView.delegate = self; + tableView.dataSource = self; + tableView.estimatedRowHeight = 0; + if (@available(iOS 11.0, *)) { + tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } else { + } + [tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cellId"]; + SL_WeakSelf; + tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{ + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + weakSelf.dataCount = 20; + [tableView reloadData]; + [tableView.mj_header endRefreshing]; + }); + }]; + tableView.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingBlock:^{ + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + weakSelf.dataCount += 20; + [tableView reloadData]; + [tableView.mj_footer endRefreshing]; + }); + }]; + return tableView; +} + +#pragma mark - EventsHandle +- (void)back { + [self.navigationController popViewControllerAnimated:YES]; +} + +#pragma mark - HelpMethods +///当前子列表 +- (SLPanTableView *)currentSubListTabView { + return [self.tabScrollView viewWithTag:10+self.menuView.currentPage]; +} + +#pragma mark - UITableViewDelegate,UITableViewDataSource +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return self.dataCount; +} +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + return 88; +} +- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { + return 0.1; +} +- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { + return nil; +} +- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { + return 0.1; +} +- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { + return nil; +} +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cellId" forIndexPath:indexPath]; + cell.textLabel.text = [NSString stringWithFormat:@"%ld",indexPath.row]; + return cell; +} +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [tableView deselectRowAtIndexPath:indexPath animated:YES]; +} + +#pragma mark - SLMenuViewDelegate +- (void)menuView:(SLMenuView *)menuView didSelectItemAtIndex:(NSInteger)index { + [self.tabScrollView setContentOffset:CGPointMake(index* self.tabScrollView.sl_width, 0) animated:YES]; +} + +#pragma mark - UIScrollViewDelegate +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + + if (scrollView == self.tabScrollView) return; + + if (scrollView == self.mainScrollView) { + if (self.mainScrollView.contentOffset.y >= mainScrollViewHeadHeight-SL_TopNavigationBarHeight || _isTopHovering) { + //滑到顶部悬停 + _isTopHovering = YES; + self.mainScrollView.contentOffset = CGPointMake(0, mainScrollViewHeadHeight-SL_TopNavigationBarHeight); + } + if(_isTopHovering) { + self.navigationController.navigationBar.hidden = NO; + }else { + self.navigationController.navigationBar.hidden = YES; + } + + if (self.mainScrollView.contentOffset.y <= 0 ) { + //头部放大 + self.headView.transform = CGAffineTransformMakeScale(fabs(self.mainScrollView.contentOffset.y)/self.headView.sl_height+1, fabs(self.mainScrollView.contentOffset.y)/self.headView.sl_height+1); + } + } + + //子列表 + if (scrollView.superview == self.tabScrollView) { + if((!_isTopHovering && self.mainScrollView.contentOffset.y > 0) || (self.mainScrollView.contentOffset.y < 0 ) ) { + //如果主mainScrollView还未到顶部悬停,则选项子列表subTableView偏移量保持不变 + if (scrollView.contentOffset.y < 0) { + self.lastContentOffset = CGPointZero; + } + scrollView.contentOffset = self.lastContentOffset; + } + if(_isTopHovering && scrollView.contentOffset.y > 0) { + //如果主mainScrollView在顶部悬停,而此时选项子列表subTableView还未到顶部,则保持mainScrollView继续悬停 + self.mainScrollView.contentOffset = CGPointMake(0, mainScrollViewHeadHeight-SL_TopNavigationBarHeight); + } + if (scrollView.contentOffset.y < 0) { + //如果subTableView滑动到了顶部,即将取消顶部悬停 + _isTopHovering = NO; + } + } +} +- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { + if (scrollView == self.tabScrollView) { + self.menuView.currentPage = roundf(self.tabScrollView.contentOffset.x/self.tabScrollView.sl_width); + self.lastContentOffset = [self currentSubListTabView].contentOffset; + } +} +- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { + if (scrollView == self.tabScrollView) { + self.menuView.currentPage = roundf(self.tabScrollView.contentOffset.x/self.tabScrollView.sl_width); + self.lastContentOffset = [self currentSubListTabView].contentOffset; + } +} + +@end diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJuejin.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJuejin.m" index b63e05dc..18bb53ad 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJuejin.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewJuejin.m" @@ -40,8 +40,8 @@ @implementation SLScrollViewJuejin - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; - [self getData]; [self setupUI]; + [self getData]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; @@ -94,6 +94,7 @@ - (void)setupUI { #pragma mark - Data - (void)getData { self.dataCount = 20; + [[self currentSubListTabView].mj_header beginRefreshing]; } #pragma mark - Getter @@ -196,8 +197,6 @@ - (SLPanTableView *)subTableView { return tableView; } -#pragma mark - Data - #pragma mark - EventsHandle - (void)back { [self.navigationController popViewControllerAnimated:YES]; diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" index b71e84ea..5261431c 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollViewWeibo.m" @@ -200,8 +200,6 @@ - (UITableView *)subTableView { return tableView; } -#pragma mark - Data - #pragma mark - EventsHandle - (void)back { if (self.isTopHovering) { diff --git "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" index ec7e0298..8b9b7807 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" +++ "b/iOS_Tips/DarkMode/WorkIssues/ScrollView\345\265\214\345\245\227/SLScrollviewNesteVC.m" @@ -9,6 +9,7 @@ #import "SLScrollviewNesteVC.h" #import "SLScrollViewJuejin.h" #import "SLScrollViewWeibo.h" +#import "SLScrollViewJianShu.h" @interface SLScrollviewNesteVC () @property (nonatomic, strong) NSMutableArray *titlesArray; @@ -41,9 +42,11 @@ - (void)setupUI { - (void)getData { [self.titlesArray addObjectsFromArray:@[ @"掘金APP个人中心页样式", - @"微博发现页ScrollView嵌套样式doing"]]; + @"微博发现页ScrollView嵌套样式", + @"简书APP个人中心页样式"]]; [self.classArray addObjectsFromArray:@[[SLScrollViewJuejin class], - [SLScrollViewWeibo class]]]; + [SLScrollViewWeibo class], + [SLScrollViewJianShu class]]]; [self.tableView reloadData]; } From e299e543a387e53d8b4db624d66a82d6abdb39b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Tue, 15 Sep 2020 17:28:31 +0800 Subject: [PATCH 220/356] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 43eb0ac9..cfd3506e 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,10 @@ > 扫描项目中无用的图片、类等文件资源, 此示例主要针对于此项目中的图片资源,其他类型资源实现原理相同。 +#### 6.10、多个UIScrollView嵌套/个人中心页 + +![多个UIScrollView嵌套](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/多个UIScrollView嵌套.gif) + ## 7-iOSCrash防护 > Crash防护内容涉及 NSArray/NSMutableArray、NSDictionary/NSMutableDictionary、NSString/NSMutableString、Unrecognized Selector、KVO、KVC 、异步线程刷新UI、野指针定位、内存泄漏/循环引用;主要是对常见易错的地方进行容错处理,避免崩溃,并保存出错时的函数调用栈,以方便快速定位代码,主要是利用的runtime和fishook知识。 From 8c76028a7c3fc9fdaab17940180905e9286a38a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Tue, 15 Sep 2020 17:40:43 +0800 Subject: [PATCH 221/356] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cfd3506e..33b232c0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# iOS_Tips +# [iOS_Tips](https://github.com/wsl2ls/iOS_Tips) > iOS的一些示例,不定时更新~ | [简书 ](https://www.jianshu.com/u/e15d1f644bea) | [掘金](https://juejin.im/user/5c00d97b6fb9a049fb436288) | From b9debb9a2af1b44fc7154d6fad40f51a7a26204f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Tue, 15 Sep 2020 19:05:49 +0800 Subject: [PATCH 222/356] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 33b232c0..56be18f6 100644 --- a/README.md +++ b/README.md @@ -159,6 +159,7 @@ > * 4、小视频拍摄录制失败,主要集中在plus和X系列手机上:可能是由于写入的视频宽高videoSize设置的问题,各位可以先试试这样设置 avCaptureTool.videoSize = CGSizeMake(self.view.width * 0.8, self.view.height * 0.8); > * 5、当你编译的时候,XCode出现Unable to load contents of file list 错误,导致出现此原因是pods版本不一致,请更新pods版本或者重新安装。 +> * 6、如果发现我简书或掘金上的文章无法查看了,请联系我。 #### Welcome to you 👏 您的follow和start,是我前进的动力,Thanks♪(・ω・)ノ 🤝 From fdf35ede7cfead2a3628e1cb269b9c5639059ae3 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 18 Sep 2020 10:38:22 +0800 Subject: [PATCH 223/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 6 +++++- ...\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 7436dff4..def9d09f 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -98,12 +98,14 @@ * 1、[(强烈推荐)移动端音视频从零到上手](https://juejin.im/post/6844903889007820813) * 2、[移动开发者的必知音视频基础知识](https://juejin.im/post/6844904039503626247) +* 3、[GoPlay是一款基于FFmpeg/OpenGLES2.0的iOS播放器](https://github.com/letqingbin/GoPlay) ## 六、跨平台/热更新 * 1、DSBridge /JSBridge /JSPatch/ * 2、[写给自己看系列之WebViewJavascriptBridge源码分析](https://juejin.im/post/6844904097192247303) * 3、[OCRunner:完全体的iOS热修复方案](https://silverfruity.github.io/2020/09/04/OCRunner/) +* 4、[DynamicOC](https://github.com/letqingbin/DynamicOC) ## 七、Shell脚本 @@ -111,7 +113,6 @@ * 1、[Shell脚本编程30分钟入门](https://github.com/qinjx/30min_guides/blob/master/shell.md) - ## 八、网络 * 1、[TCP序列号和确认号详解](https://blog.csdn.net/fujibao/article/details/80857180) @@ -128,6 +129,9 @@ ## 十、架构/设计模式 +## 十一、优秀三方源码解析 + + ## 其它 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 7209e496..22028d4b 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -59,6 +59,7 @@ * 57、[孤单的衬衣](https://juejin.im/user/2735240661962638) * 58、[ShannonChenCHN](https://github.com/ShannonChenCHN) * 59、[木子Lision](https://github.com/Lision) +* 59、[letqingbin](https://github.com/letqingbin) ## 高质量微信公众号 From 2b9d873047d002de9f5afe818870bd74c7ddd16c Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 18 Sep 2020 15:55:09 +0800 Subject: [PATCH 224/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + ...207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index def9d09f..b10fac7e 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -99,6 +99,7 @@ * 1、[(强烈推荐)移动端音视频从零到上手](https://juejin.im/post/6844903889007820813) * 2、[移动开发者的必知音视频基础知识](https://juejin.im/post/6844904039503626247) * 3、[GoPlay是一款基于FFmpeg/OpenGLES2.0的iOS播放器](https://github.com/letqingbin/GoPlay) +* 4、[CainCamera](https://github.com/CainKernel/blog) ## 六、跨平台/热更新 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 22028d4b..bd2a7a4d 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -59,7 +59,8 @@ * 57、[孤单的衬衣](https://juejin.im/user/2735240661962638) * 58、[ShannonChenCHN](https://github.com/ShannonChenCHN) * 59、[木子Lision](https://github.com/Lision) -* 59、[letqingbin](https://github.com/letqingbin) +* 59、[letqingbin](https://github.com/letqingbin) +* 60、[CainCamera](https://github.com/CainKernel/blog) ## 高质量微信公众号 From 6ef388ac43ff61b8128ca9d773a18ef479d06c17 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 21 Sep 2020 14:16:43 +0800 Subject: [PATCH 225/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + ...207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index b10fac7e..b859ef58 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -85,6 +85,7 @@ * 10、[各种精选面试题](https://github.com/iOShuyang/Book-Recommended-Interview) * 11、[iOS | 面试知识整理 - Swift 基础(九)](https://juejin.im/post/6844903955156336654) * 12、[iOSDevLevelingUp](https://github.com/ShannonChenCHN/iOSDevLevelingUp) +* 13、[iOS 基础](https://juejin.im/user/940837683069549/posts) ## 四、逆向与安全 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index bd2a7a4d..bc8a30ce 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -60,7 +60,8 @@ * 58、[ShannonChenCHN](https://github.com/ShannonChenCHN) * 59、[木子Lision](https://github.com/Lision) * 59、[letqingbin](https://github.com/letqingbin) -* 60、[CainCamera](https://github.com/CainKernel/blog) +* 60、[CainCamera](https://github.com/CainKernel/blog) +* 60、[行走少年郎](https://juejin.im/user/2488950054725101/posts) ## 高质量微信公众号 From 1f26023f361c001cfb1fa9ddc6fa139cda43c9ed Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 22 Sep 2020 18:06:42 +0800 Subject: [PATCH 226/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SLBinaryResetViewController.h" | 4 +++- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.h" "b/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.h" index 5b2b7fbd..21458aeb 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.h" +++ "b/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.h" @@ -10,7 +10,9 @@ NS_ASSUME_NONNULL_BEGIN -///二进制重排优化启动时间 参考:https://juejin.im/post/5e97c3c751882573b86f9d00#heading-17 +//参考:https://juejin.im/post/5e97c3c751882573b86f9d00#heading-17 +// https://github.com/rhythmkay/PGOAnalyzer +///二进制重排优化启动时间 @interface SLBinaryResetViewController : SLViewController @end diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index b859ef58..363120f8 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -64,7 +64,8 @@ > [iOS优化篇之App启动时间优化](https://juejin.im/post/6861917375382929415) > [iOS如何提高10倍以上编译速度](https://juejin.im/post/6844904169124397070) > [为什么 Debug Information Format 改为 DWARF 可以提高编译速度?](https://zhuanlan.zhihu.com/p/112764192) -> [移动 APP 网络优化概述](http://blog.cnbang.net/tech/3531/) +> [移动 APP 网络优化概述](http://blog.cnbang.net/tech/3531/) +> [二进制重排-编译插桩与动态trace结合](https://github.com/rhythmkay/PGOAnalyzer) ## 二、数据结构与算法 From f905a4406ce050e20667e8dcb0bc0b2131971372 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 23 Sep 2020 10:14:20 +0800 Subject: [PATCH 227/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + ...217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 363120f8..ff1afeb2 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -95,6 +95,7 @@ * 3、[[iOS翻译]编译器](https://juejin.im/post/6854573220612931592) * 4、[Injection:iOS热重载背后的黑魔法](https://mp.weixin.qq.com/s/hFnHdOP6pmIwzZck-zXE8g) * 5、[高效逆向 - 为任意iOS App生成符号表](https://github.com/imoldman/DSYMCreator) +* 6、[iOS LLVM-Clang 浅谈](https://www.jianshu.com/p/7ceca351a045) ## 五、音视频 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index bc8a30ce..cfb35862 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -59,9 +59,10 @@ * 57、[孤单的衬衣](https://juejin.im/user/2735240661962638) * 58、[ShannonChenCHN](https://github.com/ShannonChenCHN) * 59、[木子Lision](https://github.com/Lision) -* 59、[letqingbin](https://github.com/letqingbin) -* 60、[CainCamera](https://github.com/CainKernel/blog) -* 60、[行走少年郎](https://juejin.im/user/2488950054725101/posts) +* 60、[letqingbin](https://github.com/letqingbin) +* 61、[CainCamera](https://github.com/CainKernel/blog) +* 62、[行走少年郎](https://juejin.im/user/2488950054725101/posts) +* 63、[翻译、开发心得或学习笔记](https://github.com/nixzhu/dev-blog) ## 高质量微信公众号 From 0374db8ff9946e2b562403cef5540ebfe98c9e98 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 23 Sep 2020 10:29:03 +0800 Subject: [PATCH 228/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index ff1afeb2..7f0a3079 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -66,6 +66,7 @@ > [为什么 Debug Information Format 改为 DWARF 可以提高编译速度?](https://zhuanlan.zhihu.com/p/112764192) > [移动 APP 网络优化概述](http://blog.cnbang.net/tech/3531/) > [二进制重排-编译插桩与动态trace结合](https://github.com/rhythmkay/PGOAnalyzer) +> [关于WKWebView 秒开方案](https://www.jianshu.com/p/74fad07ec640) ## 二、数据结构与算法 From cc1f868afad1ae29a12ccab692558318e5513ead Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 23 Sep 2020 11:15:32 +0800 Subject: [PATCH 229/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 7f0a3079..f3f4e3da 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -111,6 +111,7 @@ * 2、[写给自己看系列之WebViewJavascriptBridge源码分析](https://juejin.im/post/6844904097192247303) * 3、[OCRunner:完全体的iOS热修复方案](https://silverfruity.github.io/2020/09/04/OCRunner/) * 4、[DynamicOC](https://github.com/letqingbin/DynamicOC) +* 5、[js-native 通信的 6 种方式](https://mp.weixin.qq.com/s/_Xo6O3NoE1z9AIMJm_uSsA) ## 七、Shell脚本 From 203e28b392d275302f7bae733825521be6244287 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 24 Sep 2020 18:41:12 +0800 Subject: [PATCH 230/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WKWebView/WebTableView/SLScrollViewController.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/iOS_Tips/DarkMode/WKWebView/WebTableView/SLScrollViewController.m b/iOS_Tips/DarkMode/WKWebView/WebTableView/SLScrollViewController.m index 25b5af22..84174e41 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebTableView/SLScrollViewController.m +++ b/iOS_Tips/DarkMode/WKWebView/WebTableView/SLScrollViewController.m @@ -18,7 +18,8 @@ @interface SLScrollView : UIView Date: Fri, 25 Sep 2020 10:00:15 +0800 Subject: [PATCH 231/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\347\254\224\350\256\260.md" | 1 + ...\200\346\234\257\345\215\232\345\256\242.md" | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index f3f4e3da..fb768ca2 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -104,6 +104,7 @@ * 2、[移动开发者的必知音视频基础知识](https://juejin.im/post/6844904039503626247) * 3、[GoPlay是一款基于FFmpeg/OpenGLES2.0的iOS播放器](https://github.com/letqingbin/GoPlay) * 4、[CainCamera](https://github.com/CainKernel/blog) +* 5、[Android 音视频开发学习思路](https://www.cnblogs.com/renhui/p/7452572.html) ## 六、跨平台/热更新 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index cfb35862..ca9aff8a 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -81,3 +81,20 @@ * 13、[京东零售技术](公众号:jd-sys) * 14、[携程技术](公众号:ctriptech) * 15、[字节跳动技术团队](公众号:toutiaotechblog) + + +## 书籍 + +* 1、[iOS全埋点解决方案-神策数据](电子书) +* 2、[跟戴铭学iOS编程:理顺核心知识点 - 戴铭](电子书) +* 3、[程序员的自我修养:链接、装载与库](电子书) +* 4、[iOS动画学习手册2.0](电子书) +* 5、[Objective-C高级编程 iOS与OS X多线程和内存管理](电子书) +* 6、[App架构师实践指南](电子书) +* 7、[OpenGL ES 3.0编程指南 ](电子书) +* 8、[音视频开发进阶指南:基于Android与iOS平台的实践 ](电子书) +* 9、[AVFoundation开发秘籍 ](电子书) +* 10、[计算机网络 ](电子书) +* 11、[计算机操作系统 ](电子书) +* 12、[数据结构与算法 ](电子书) +* 13、[编译原理 ](电子书) From a00aab1ee31f165eae8184f35c30ade2c73fca36 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 25 Sep 2020 11:40:54 +0800 Subject: [PATCH 232/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 2 ++ 1 file changed, 2 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index fb768ca2..a5e006ba 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -138,6 +138,8 @@ ## 十一、优秀三方源码解析 +* 1、[优秀的三方源码](https://github.com/iOShuyang/Book-Recommend-Github) + ## 其它 From 4be71fe72b2b55e243f629aefbfda437875229a6 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sun, 27 Sep 2020 11:40:12 +0800 Subject: [PATCH 233/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index a5e006ba..7cd696cd 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -123,7 +123,7 @@ ## 八、网络 * 1、[TCP序列号和确认号详解](https://blog.csdn.net/fujibao/article/details/80857180) - +* 2、[探索现代的移动网络](https://mp.weixin.qq.com/s/ds6QkVrBwcurxp3RkvZe8Q) ## 九、效率 From 1e68f8f305d3c9b94cf9a99b8eda26d598326d3e Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 28 Sep 2020 10:05:24 +0800 Subject: [PATCH 234/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + ...1\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 2 files changed, 2 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 7cd696cd..536e343d 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -88,6 +88,7 @@ * 11、[iOS | 面试知识整理 - Swift 基础(九)](https://juejin.im/post/6844903955156336654) * 12、[iOSDevLevelingUp](https://github.com/ShannonChenCHN/iOSDevLevelingUp) * 13、[iOS 基础](https://juejin.im/user/940837683069549/posts) +* 14、[深入理解RunLoop](https://blog.ibireme.com/2015/05/18/runloop/) ## 四、逆向与安全 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index ca9aff8a..65b5fd41 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -63,6 +63,7 @@ * 61、[CainCamera](https://github.com/CainKernel/blog) * 62、[行走少年郎](https://juejin.im/user/2488950054725101/posts) * 63、[翻译、开发心得或学习笔记](https://github.com/nixzhu/dev-blog) +* 64、[ibireme-YYKit作者](https://blog.ibireme.com) ## 高质量微信公众号 From 0980e80278b447a594d1097ac8c6f6d7d5ee79ee Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 28 Sep 2020 14:55:54 +0800 Subject: [PATCH 235/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 3 ++- ...207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 536e343d..2591c025 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -67,6 +67,7 @@ > [移动 APP 网络优化概述](http://blog.cnbang.net/tech/3531/) > [二进制重排-编译插桩与动态trace结合](https://github.com/rhythmkay/PGOAnalyzer) > [关于WKWebView 秒开方案](https://www.jianshu.com/p/74fad07ec640) +> [如何自建 Crash 平台](https://www.xuyanlan.com/2019/02/20/iOS-crash-report/) ## 二、数据结构与算法 @@ -140,7 +141,7 @@ ## 十一、优秀三方源码解析 * 1、[优秀的三方源码](https://github.com/iOShuyang/Book-Recommend-Github) - +* 2、[波儿菜](https://juejin.im/user/2735240659351112) ## 其它 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 65b5fd41..4e8af30c 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -82,6 +82,7 @@ * 13、[京东零售技术](公众号:jd-sys) * 14、[携程技术](公众号:ctriptech) * 15、[字节跳动技术团队](公众号:toutiaotechblog) +* 16、[老司机技术周报](公众号:LSJCoding) ## 书籍 From cdc6dde14cdf8c1184e9d07928cca04609e4659b Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 28 Sep 2020 15:12:01 +0800 Subject: [PATCH 236/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 4e8af30c..e79d533e 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -84,7 +84,6 @@ * 15、[字节跳动技术团队](公众号:toutiaotechblog) * 16、[老司机技术周报](公众号:LSJCoding) - ## 书籍 * 1、[iOS全埋点解决方案-神策数据](电子书) @@ -100,3 +99,8 @@ * 11、[计算机操作系统 ](电子书) * 12、[数据结构与算法 ](电子书) * 13、[编译原理 ](电子书) + +## 找工作内推 + +* [2020:iOS 靠谱内推专题](https://www.yuque.com/iosalliance/article/bhutav) +* [谁在招人?](https://github.com/ruanyf/weekly/issues/1315) From 7626178f655deb8bb9ed51060c30420aa9fcc09b Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 28 Sep 2020 15:27:54 +0800 Subject: [PATCH 237/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 2591c025..505da499 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -107,6 +107,7 @@ * 3、[GoPlay是一款基于FFmpeg/OpenGLES2.0的iOS播放器](https://github.com/letqingbin/GoPlay) * 4、[CainCamera](https://github.com/CainKernel/blog) * 5、[Android 音视频开发学习思路](https://www.cnblogs.com/renhui/p/7452572.html) +* 6、[loyinglin](https://github.com/loyinglin) ## 六、跨平台/热更新 From a1ccf1a6408f87d005435c44989705219ca7bbec Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 29 Sep 2020 09:21:32 +0800 Subject: [PATCH 238/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 4 ++++ "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 6 ++++++ ...\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 2 +- 4 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 "iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 3bb416a6..2ac84f8d 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -79,6 +79,7 @@ 7851CB43233222E2002295B5 /* UIView+SLFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 7851CB41233222E2002295B5 /* UIView+SLFrame.m */; }; 7857977823725C21004CD664 /* SLFaceDetectController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7857977723725C21004CD664 /* SLFaceDetectController.m */; }; 7857FD4B24729E8500D3D986 /* BSBacktraceLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 7857FD4A24729E8500D3D986 /* BSBacktraceLogger.m */; }; + 785D06642522C32700F174BA /* 面试题.md in Resources */ = {isa = PBXBuildFile; fileRef = 785D06632522C32700F174BA /* 面试题.md */; }; 7860D78E2398D34E008C53EC /* SLMixColorTextureVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 7860D78D2398D34E008C53EC /* SLMixColorTextureVC.m */; }; 7860D791239922B4008C53EC /* SLGLKPyramidVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 7860D790239922B4008C53EC /* SLGLKPyramidVC.m */; }; 786147F12362A39500C5424C /* Resources.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 786147F02362A39500C5424C /* Resources.bundle */; }; @@ -317,6 +318,7 @@ 7857977723725C21004CD664 /* SLFaceDetectController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLFaceDetectController.m; sourceTree = ""; }; 7857FD4924729E8500D3D986 /* BSBacktraceLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BSBacktraceLogger.h; sourceTree = ""; }; 7857FD4A24729E8500D3D986 /* BSBacktraceLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BSBacktraceLogger.m; sourceTree = ""; }; + 785D06632522C32700F174BA /* 面试题.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = "面试题.md"; sourceTree = ""; }; 7860D78C2398D34E008C53EC /* SLMixColorTextureVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLMixColorTextureVC.h; sourceTree = ""; }; 7860D78D2398D34E008C53EC /* SLMixColorTextureVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLMixColorTextureVC.m; sourceTree = ""; }; 7860D78F239922B4008C53EC /* SLGLKPyramidVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLGLKPyramidVC.h; sourceTree = ""; }; @@ -935,6 +937,7 @@ children = ( 784C4C6F24C5B5DD00D5C199 /* 高质量技术博客.md */, 784C4C6D24C5B4F500D5C199 /* 笔记.md */, + 785D06632522C32700F174BA /* 面试题.md */, 7884247D2492102900C2E505 /* SLWorkIssuesViewController.h */, 7884247E2492102900C2E505 /* SLWorkIssuesViewController.m */, 78908DC024FFBD83004164C2 /* ScrollView嵌套 */, @@ -1410,6 +1413,7 @@ 782CFB6D239E69F3001B5528 /* Scale.fsh in Resources */, 782CFB71239E69FA001B5528 /* Shake.vsh in Resources */, 78B1048B232F57C30051579F /* Main.storyboard in Resources */, + 785D06642522C32700F174BA /* 面试题.md in Resources */, 78799EB224F1027300DA8C7A /* unused.png in Resources */, 782CFB27239DFD89001B5528 /* SplitScreen_1.fsh in Resources */, 783FB4612394A76B0039AEFD /* shaderf.fsh in Resources */, diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 505da499..88f195bc 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -68,6 +68,7 @@ > [二进制重排-编译插桩与动态trace结合](https://github.com/rhythmkay/PGOAnalyzer) > [关于WKWebView 秒开方案](https://www.jianshu.com/p/74fad07ec640) > [如何自建 Crash 平台](https://www.xuyanlan.com/2019/02/20/iOS-crash-report/) +> [iOS客户端稳定性体系](https://778477.github.io/2018/02/23/2018-02-23-iOS客户端稳定性体系/) ## 二、数据结构与算法 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" new file mode 100644 index 00000000..245cad9c --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -0,0 +1,6 @@ + + +## 面试知识点 + +* 1、 [为什么iOS更新UI操作必须在主线程?](https://778477.github.io/2017/06/19/2017-06-19-为什么iOS更新UI操作必须在主线程/) +* 2、 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index e79d533e..4f56a6a5 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -63,7 +63,7 @@ * 61、[CainCamera](https://github.com/CainKernel/blog) * 62、[行走少年郎](https://juejin.im/user/2488950054725101/posts) * 63、[翻译、开发心得或学习笔记](https://github.com/nixzhu/dev-blog) -* 64、[ibireme-YYKit作者](https://blog.ibireme.com) +* 64、[778477](https://778477.github.io) ## 高质量微信公众号 From c35d95051f407ff506a130650b72f6cf51f73ed7 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 29 Sep 2020 09:30:45 +0800 Subject: [PATCH 239/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 88f195bc..2020f3ff 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -144,6 +144,7 @@ * 1、[优秀的三方源码](https://github.com/iOShuyang/Book-Recommend-Github) * 2、[波儿菜](https://juejin.im/user/2735240659351112) +* 3、[写给自己看系列之WebViewJavascriptBridge源码分析](https://juejin.im/post/6844904097192247303) ## 其它 From ce99072ea72594f85a4fcd00e13b692df88df449 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 29 Sep 2020 09:33:42 +0800 Subject: [PATCH 240/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/.DS_Store | Bin 14340 -> 14340 bytes .../WorkIssues/\347\254\224\350\256\260.md" | 1 + 2 files changed, 1 insertion(+) diff --git a/iOS_Tips/DarkMode/.DS_Store b/iOS_Tips/DarkMode/.DS_Store index 391c9b5974f79831590c0bcac6bf0bc171a695dc..e5fa5b0fb1e5ebf6b6ae4be8472a30e8c86e4bb3 100644 GIT binary patch delta 93 zcmZoEXepTB&*--?U^hRb>f}H{k=}Z6k0X;f;b>kVNquD9_&}0zGq=Jw7*CXOGrPfGb^zpV B60raP diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 2020f3ff..060ace3c 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -69,6 +69,7 @@ > [关于WKWebView 秒开方案](https://www.jianshu.com/p/74fad07ec640) > [如何自建 Crash 平台](https://www.xuyanlan.com/2019/02/20/iOS-crash-report/) > [iOS客户端稳定性体系](https://778477.github.io/2018/02/23/2018-02-23-iOS客户端稳定性体系/) +> [iOS 包瘦身浅析](https://github.com/778477/iOS-LinkMapAnalyzer) ## 二、数据结构与算法 From 192a0045a5d562e5bb979d60730393650a4c3d40 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 29 Sep 2020 09:39:19 +0800 Subject: [PATCH 241/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...1\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 4f56a6a5..f3a97dad 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -64,6 +64,7 @@ * 62、[行走少年郎](https://juejin.im/user/2488950054725101/posts) * 63、[翻译、开发心得或学习笔记](https://github.com/nixzhu/dev-blog) * 64、[778477](https://778477.github.io) +* 65、[ibireme-YYKit作者](https://blog.ibireme.com) ## 高质量微信公众号 From 87ad165905b5c30d8f66ab2a136d6f4bab13c22e Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 29 Sep 2020 09:42:48 +0800 Subject: [PATCH 242/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\347\254\224\350\256\260.md" | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 060ace3c..f11555fd 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -37,7 +37,8 @@ > 代码混淆 -> * 资料 +> * 资料 + > [iOS-Performance-Optimization](https://github.com/skyming/iOS-Performance-Optimization) > [深入剖析 iOS 性能优化-戴明](https://ming1016.github.io/2017/06/20/deeply-ios-performance-optimization/#more) > [DoraemonKit](https://github.com/didi/DoraemonKit/blob/master/README_CN.md) @@ -59,16 +60,16 @@ > [优化 App 的启动时间](http://yulingtianxia.com/blog/2016/10/30/Optimizing-App-Startup-Time/) > [AppStartTime](https://github.com/JunyiXie/AppStartTime) > [iOS App 启动性能优化](https://mp.weixin.qq.com/s/Kf3EbDIUuf0aWVT-UCEmbA) -> [iOS一次立竿见影的启动时间优化](https://juejin.im/post/6844903525172903944) -> [iOS Dynamic Framework 对App启动时间影响实测](https://www.jianshu.com/p/3263009e9228) -> [iOS优化篇之App启动时间优化](https://juejin.im/post/6861917375382929415) -> [iOS如何提高10倍以上编译速度](https://juejin.im/post/6844904169124397070) -> [为什么 Debug Information Format 改为 DWARF 可以提高编译速度?](https://zhuanlan.zhihu.com/p/112764192) +> [iOS一次立竿见影的启动时间优化](https://juejin.im/post/6844903525172903944) +> [iOS Dynamic Framework 对App启动时间影响实测](https://www.jianshu.com/p/3263009e9228) +> [iOS优化篇之App启动时间优化](https://juejin.im/post/6861917375382929415) +> [iOS如何提高10倍以上编译速度](https://juejin.im/post/6844904169124397070) +> [为什么 Debug Information Format 改为 DWARF 可以提高编译速度?](https://zhuanlan.zhihu.com/p/112764192) > [移动 APP 网络优化概述](http://blog.cnbang.net/tech/3531/) -> [二进制重排-编译插桩与动态trace结合](https://github.com/rhythmkay/PGOAnalyzer) -> [关于WKWebView 秒开方案](https://www.jianshu.com/p/74fad07ec640) -> [如何自建 Crash 平台](https://www.xuyanlan.com/2019/02/20/iOS-crash-report/) -> [iOS客户端稳定性体系](https://778477.github.io/2018/02/23/2018-02-23-iOS客户端稳定性体系/) +> [二进制重排-编译插桩与动态trace结合](https://github.com/rhythmkay/PGOAnalyzer) +> [关于WKWebView 秒开方案](https://www.jianshu.com/p/74fad07ec640) +> [如何自建 Crash 平台](https://www.xuyanlan.com/2019/02/20/iOS-crash-report/) +> [iOS客户端稳定性体系](https://778477.github.io/2018/02/23/2018-02-23-iOS客户端稳定性体系/) > [iOS 包瘦身浅析](https://github.com/778477/iOS-LinkMapAnalyzer) ## 二、数据结构与算法 From fbab06a72d08b2ef94a2871c3c92390a2b1de856 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 29 Sep 2020 10:49:15 +0800 Subject: [PATCH 243/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index f11555fd..0750275e 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -70,7 +70,8 @@ > [关于WKWebView 秒开方案](https://www.jianshu.com/p/74fad07ec640) > [如何自建 Crash 平台](https://www.xuyanlan.com/2019/02/20/iOS-crash-report/) > [iOS客户端稳定性体系](https://778477.github.io/2018/02/23/2018-02-23-iOS客户端稳定性体系/) -> [iOS 包瘦身浅析](https://github.com/778477/iOS-LinkMapAnalyzer) +> [iOS 包瘦身浅析](https://github.com/778477/iOS-LinkMapAnalyzer) +> [iOS 崩溃排查技巧:如何获取系统库源码](https://mp.weixin.qq.com/s/YjJo-FB9weGgxEaOfCwBvg) ## 二、数据结构与算法 From 40e800976a024b315e37cb8fba45e717e5588286 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 30 Sep 2020 20:43:34 +0800 Subject: [PATCH 244/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 0750275e..33367f28 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -120,6 +120,7 @@ * 3、[OCRunner:完全体的iOS热修复方案](https://silverfruity.github.io/2020/09/04/OCRunner/) * 4、[DynamicOC](https://github.com/letqingbin/DynamicOC) * 5、[js-native 通信的 6 种方式](https://mp.weixin.qq.com/s/_Xo6O3NoE1z9AIMJm_uSsA) +* 6、[美团外卖客户端容器化架构的演进](https://mp.weixin.qq.com/s/kW5wu7GM7pMRRvN-dQvE2g) ## 七、Shell脚本 From f6432f283a14f0abe7fa4f2142e0b50365e4b92d Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 30 Sep 2020 20:58:07 +0800 Subject: [PATCH 245/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 4 ++-- ...07\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 33367f28..90b9de3e 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -122,7 +122,6 @@ * 5、[js-native 通信的 6 种方式](https://mp.weixin.qq.com/s/_Xo6O3NoE1z9AIMJm_uSsA) * 6、[美团外卖客户端容器化架构的演进](https://mp.weixin.qq.com/s/kW5wu7GM7pMRRvN-dQvE2g) - ## 七、Shell脚本 * 1、[Shell脚本编程30分钟入门](https://github.com/qinjx/30min_guides/blob/master/shell.md) @@ -149,7 +148,7 @@ * 1、[优秀的三方源码](https://github.com/iOShuyang/Book-Recommend-Github) * 2、[波儿菜](https://juejin.im/user/2735240659351112) * 3、[写给自己看系列之WebViewJavascriptBridge源码分析](https://juejin.im/post/6844904097192247303) - +* 4、[JSBridge 实现原理解析](https://github.com/mcuking/blog/issues/39) ## 其它 @@ -159,3 +158,4 @@ * 4、[OCLint 实现 Code Review - 给你的代码提提质量](https://juejin.im/post/6844903853775650830) * 5、[(译)开源软件架构之 LLVM(The Architecture of Open Source Applications LLVM)](https://juejin.im/post/6844904034134917134) * 6、[你真的会用 CocoaPods 吗?](https://juejin.im/post/6844903506734759949) +* 7、[你知道 Git 是如何做版本控制的吗?](https://juejin.im/post/6844903967525208078) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index f3a97dad..816be77b 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -65,6 +65,7 @@ * 63、[翻译、开发心得或学习笔记](https://github.com/nixzhu/dev-blog) * 64、[778477](https://778477.github.io) * 65、[ibireme-YYKit作者](https://blog.ibireme.com) +* 66、[mcuking](https://github.com/mcuking/blog) ## 高质量微信公众号 From f97f999e124486ad143bc520f19e1720701cc5cb Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 9 Oct 2020 10:09:13 +0800 Subject: [PATCH 246/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 816be77b..fa714a94 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -65,7 +65,8 @@ * 63、[翻译、开发心得或学习笔记](https://github.com/nixzhu/dev-blog) * 64、[778477](https://778477.github.io) * 65、[ibireme-YYKit作者](https://blog.ibireme.com) -* 66、[mcuking](https://github.com/mcuking/blog) +* 66、[mcuking](https://github.com/mcuking/blog) +* 67、[冬瓜争做全栈瓜](https://www.desgard.com) ## 高质量微信公众号 From a3cd7f2f2ddb895c90286211f5f622cece326c2c Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sat, 10 Oct 2020 19:11:30 +0800 Subject: [PATCH 247/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 90b9de3e..ac543e15 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -142,6 +142,7 @@ ## 十、架构/设计模式 +*1、[IOS设计模式探索(大话设计模式)](https://github.com/huang303513/Design-Pattern-For-iOS.git) ## 十一、优秀三方源码解析 From 86eeaeb1d37fc9a6ddac089a6bc4570f6d59be76 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 13 Oct 2020 10:46:27 +0800 Subject: [PATCH 248/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 2 ++ 1 file changed, 2 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index ac543e15..249a8da8 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -72,6 +72,7 @@ > [iOS客户端稳定性体系](https://778477.github.io/2018/02/23/2018-02-23-iOS客户端稳定性体系/) > [iOS 包瘦身浅析](https://github.com/778477/iOS-LinkMapAnalyzer) > [iOS 崩溃排查技巧:如何获取系统库源码](https://mp.weixin.qq.com/s/YjJo-FB9weGgxEaOfCwBvg) +> [iOS 性能优化:优化 App 启动速度](https://mp.weixin.qq.com/s/h3vB_zEJBAHCfGmD5EkMcw) ## 二、数据结构与算法 @@ -94,6 +95,7 @@ * 12、[iOSDevLevelingUp](https://github.com/ShannonChenCHN/iOSDevLevelingUp) * 13、[iOS 基础](https://juejin.im/user/940837683069549/posts) * 14、[深入理解RunLoop](https://blog.ibireme.com/2015/05/18/runloop/) +* 15、[BoyangBlog](https://github.com/BiBoyang/BoyangBlog.git) ## 四、逆向与安全 From 3d82b0c1aeedcb15219196e88bfdc290fc375de8 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 15 Oct 2020 18:29:52 +0800 Subject: [PATCH 249/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 249a8da8..d3fa7bb2 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -144,7 +144,8 @@ ## 十、架构/设计模式 -*1、[IOS设计模式探索(大话设计模式)](https://github.com/huang303513/Design-Pattern-For-iOS.git) +* 1、[IOS设计模式探索(大话设计模式)](https://github.com/huang303513/Design-Pattern-For-iOS.git) +* 2、[面向对象设计的设计原则和设计模式](https://github.com/knightsj/object-oriented-design) ## 十一、优秀三方源码解析 From e3c03154074556e927be370db001ddd41b760cf7 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 16 Oct 2020 14:05:32 +0800 Subject: [PATCH 250/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index d3fa7bb2..ab574516 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -72,7 +72,9 @@ > [iOS客户端稳定性体系](https://778477.github.io/2018/02/23/2018-02-23-iOS客户端稳定性体系/) > [iOS 包瘦身浅析](https://github.com/778477/iOS-LinkMapAnalyzer) > [iOS 崩溃排查技巧:如何获取系统库源码](https://mp.weixin.qq.com/s/YjJo-FB9weGgxEaOfCwBvg) -> [iOS 性能优化:优化 App 启动速度](https://mp.weixin.qq.com/s/h3vB_zEJBAHCfGmD5EkMcw) +> [iOS 性能优化:优化 App 启动速度](https://mp.weixin.qq.com/s/h3vB_zEJBAHCfGmD5EkMcw) +> [iOS 性能优化:使用 MetricKit 2.0 收集数据](https://mp.weixin.qq.com/s/cbP0QlxVlr5oeTrf6yYfFw) + ## 二、数据结构与算法 From 2f42a8079b14cb0a95a62ca47282a5b7e14e61d9 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 16 Oct 2020 16:41:08 +0800 Subject: [PATCH 251/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 2 ++ 1 file changed, 2 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index fa714a94..6bd62d05 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -86,6 +86,8 @@ * 14、[携程技术](公众号:ctriptech) * 15、[字节跳动技术团队](公众号:toutiaotechblog) * 16、[老司机技术周报](公众号:LSJCoding) +* 17、[淘系技术](公众号:AlibabaMTT) +* 18、[我是程序员小贱](公众号:Lanj1995Q) ## 书籍 From 7dcc4a03a2fd69754688ca0271dd9a766b073987 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 19 Oct 2020 10:39:45 +0800 Subject: [PATCH 252/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 2 +- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 3 ++- ...207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index ab574516..8d4cf506 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -74,7 +74,7 @@ > [iOS 崩溃排查技巧:如何获取系统库源码](https://mp.weixin.qq.com/s/YjJo-FB9weGgxEaOfCwBvg) > [iOS 性能优化:优化 App 启动速度](https://mp.weixin.qq.com/s/h3vB_zEJBAHCfGmD5EkMcw) > [iOS 性能优化:使用 MetricKit 2.0 收集数据](https://mp.weixin.qq.com/s/cbP0QlxVlr5oeTrf6yYfFw) - +> [iOS性能优化实践:头条抖音如何实现OOM崩溃率下降50%+](https://mp.weixin.qq.com/s/4-4M9E8NziAgshlwB7Sc6g) ## 二、数据结构与算法 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 245cad9c..9014df61 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -3,4 +3,5 @@ ## 面试知识点 * 1、 [为什么iOS更新UI操作必须在主线程?](https://778477.github.io/2017/06/19/2017-06-19-为什么iOS更新UI操作必须在主线程/) -* 2、 +* 2、Swift和OC的方法调用流程区别? +* 3、[iOS性能优化实践:头条抖音如何实现OOM崩溃率下降50%+](https://mp.weixin.qq.com/s/4-4M9E8NziAgshlwB7Sc6g) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 6bd62d05..e0f7d62a 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -67,6 +67,7 @@ * 65、[ibireme-YYKit作者](https://blog.ibireme.com) * 66、[mcuking](https://github.com/mcuking/blog) * 67、[冬瓜争做全栈瓜](https://www.desgard.com) +* 68、[iOS一叶](https://juejin.im/user/1899557248829438) ## 高质量微信公众号 From e1adc29e163747cd33e74913808f36fdd739c7eb Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 19 Oct 2020 15:22:11 +0800 Subject: [PATCH 253/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 8d4cf506..f95e837f 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -116,6 +116,7 @@ * 4、[CainCamera](https://github.com/CainKernel/blog) * 5、[Android 音视频开发学习思路](https://www.cnblogs.com/renhui/p/7452572.html) * 6、[loyinglin](https://github.com/loyinglin) +* 7、[CC老师](https://www.jianshu.com/u/1b4c832fb2ca) ## 六、跨平台/热更新 From 8bd8bec428b6eb2962ed960f2adf50b2b513ec1a Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 21 Oct 2020 14:47:23 +0800 Subject: [PATCH 254/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/.DS_Store | Bin 10244 -> 10244 bytes iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 8 -------- 2 files changed, 8 deletions(-) diff --git a/iOS_Tips/.DS_Store b/iOS_Tips/.DS_Store index a974884ba5ff36efe8aeac7d0c23d2fed1031529..eb789d1cbce05a223d2409d53c0fa2f23ef865b4 100644 GIT binary patch delta 40 tcmZn(XbIS0CBft+G5LVFhCo4vVQ_MOZUF-bFcmON-XNi~d4WU Date: Wed, 21 Oct 2020 14:49:49 +0800 Subject: [PATCH 255/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 20 ++++++++++---------- iOS_Tips/DarkMode/OpenGL/.DS_Store | Bin 6148 -> 6148 bytes 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index 6a4b7483..e7bb88ba 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -586,6 +586,13 @@ name = Frameworks; sourceTree = ""; }; + 2C09ED9425401113009E96B6 /* 设计模式 */ = { + isa = PBXGroup; + children = ( + ); + path = "设计模式"; + sourceTree = ""; + }; 7811F76C24B2C70D000AA044 /* 二进制重排 */ = { isa = PBXGroup; children = ( @@ -794,7 +801,6 @@ children = ( 783FB45D2394A7580039AEFD /* ShaderLanguage */, 78777CDC238FEA15006FA671 /* Controller */, - 78777CDD238FEA15006FA671 /* View */, ); path = OpenGL; sourceTree = ""; @@ -802,6 +808,8 @@ 78777CDC238FEA15006FA671 /* Controller */ = { isa = PBXGroup; children = ( + 782CFB1E239DEA05001B5528 /* SLSplitScreenCell.h */, + 782CFB1F239DEA05001B5528 /* SLSplitScreenCell.m */, 78777CDE238FEA48006FA671 /* SLOpenGLController.h */, 78777CDF238FEA48006FA671 /* SLOpenGLController.m */, 788ACD602390BFD400737EC2 /* SLLoadImageVC.h */, @@ -826,15 +834,6 @@ path = Controller; sourceTree = ""; }; - 78777CDD238FEA15006FA671 /* View */ = { - isa = PBXGroup; - children = ( - 782CFB1E239DEA05001B5528 /* SLSplitScreenCell.h */, - 782CFB1F239DEA05001B5528 /* SLSplitScreenCell.m */, - ); - path = View; - sourceTree = ""; - }; 78777CE1238FF551006FA671 /* Tool */ = { isa = PBXGroup; children = ( @@ -1057,6 +1056,7 @@ 7884247C24920FCA00C2E505 /* WorkIssues */, 788ADB342441F46500302CD9 /* Crash */, 78E72D4E24766E1300751373 /* WKWebView */, + 2C09ED9425401113009E96B6 /* 设计模式 */, 78B1048C232F57C50051579F /* Assets.xcassets */, 78B10489232F57C30051579F /* Main.storyboard */, 78B1048E232F57C50051579F /* LaunchScreen.storyboard */, diff --git a/iOS_Tips/DarkMode/OpenGL/.DS_Store b/iOS_Tips/DarkMode/OpenGL/.DS_Store index 669244197c424da5bace70d5bc1f7546d9793524..7d1ef82493efbe1e7c105b7b149f0ac03ab935ee 100644 GIT binary patch delta 180 zcmZoMXfc=|#>B)qu~2NHo+2aX#DLw4KQJ;fa!yWQl$fl-xILGJA&eoDA(f##C*3eO zIX}060RiB0x%nB`mu~2NHo+2ab#DLw5tdkR%BqpmcZQmTiyqRTVLnY&8b`E|HpsLM* Y%-@+O^NUz=FaQA~0|V3M0Ff=s0HCZ9Pyhe` From 025724c3f466b096a01d6fa1bf356a68582a0495 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 21 Oct 2020 14:50:47 +0800 Subject: [PATCH 256/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 16 ++++++++++++---- .../{Controller => View}/SLSplitScreenCell.h | 0 .../{Controller => View}/SLSplitScreenCell.m | 0 3 files changed, 12 insertions(+), 4 deletions(-) rename iOS_Tips/DarkMode/OpenGL/{Controller => View}/SLSplitScreenCell.h (100%) rename iOS_Tips/DarkMode/OpenGL/{Controller => View}/SLSplitScreenCell.m (100%) diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index e7bb88ba..d7fe7eb0 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -235,8 +235,8 @@ 7822CCF7235B054200E70C29 /* SLPaddingLabel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLPaddingLabel.m; sourceTree = ""; }; 782CFB1B239DDE95001B5528 /* SLSplitScreenViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLSplitScreenViewController.h; sourceTree = ""; }; 782CFB1C239DDE95001B5528 /* SLSplitScreenViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SLSplitScreenViewController.m; sourceTree = ""; }; - 782CFB1E239DEA05001B5528 /* SLSplitScreenCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SLSplitScreenCell.h; path = DarkMode/OpenGL/Controller/SLSplitScreenCell.h; sourceTree = SOURCE_ROOT; }; - 782CFB1F239DEA05001B5528 /* SLSplitScreenCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SLSplitScreenCell.m; path = DarkMode/OpenGL/Controller/SLSplitScreenCell.m; sourceTree = SOURCE_ROOT; }; + 782CFB1E239DEA05001B5528 /* SLSplitScreenCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SLSplitScreenCell.h; path = DarkMode/OpenGL/View/SLSplitScreenCell.h; sourceTree = SOURCE_ROOT; }; + 782CFB1F239DEA05001B5528 /* SLSplitScreenCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SLSplitScreenCell.m; path = DarkMode/OpenGL/View/SLSplitScreenCell.m; sourceTree = SOURCE_ROOT; }; 782CFB21239DFD0F001B5528 /* SplitScreen_2.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SplitScreen_2.fsh; sourceTree = ""; }; 782CFB22239DFD0F001B5528 /* SplitScreen_2.vsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SplitScreen_2.vsh; sourceTree = ""; }; 782CFB25239DFD88001B5528 /* SplitScreen_1.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = SplitScreen_1.fsh; sourceTree = ""; }; @@ -593,6 +593,15 @@ path = "设计模式"; sourceTree = ""; }; + 2C09ED95254011A2009E96B6 /* View */ = { + isa = PBXGroup; + children = ( + 782CFB1E239DEA05001B5528 /* SLSplitScreenCell.h */, + 782CFB1F239DEA05001B5528 /* SLSplitScreenCell.m */, + ); + path = View; + sourceTree = ""; + }; 7811F76C24B2C70D000AA044 /* 二进制重排 */ = { isa = PBXGroup; children = ( @@ -799,6 +808,7 @@ 78777CDB238FEA15006FA671 /* OpenGL */ = { isa = PBXGroup; children = ( + 2C09ED95254011A2009E96B6 /* View */, 783FB45D2394A7580039AEFD /* ShaderLanguage */, 78777CDC238FEA15006FA671 /* Controller */, ); @@ -808,8 +818,6 @@ 78777CDC238FEA15006FA671 /* Controller */ = { isa = PBXGroup; children = ( - 782CFB1E239DEA05001B5528 /* SLSplitScreenCell.h */, - 782CFB1F239DEA05001B5528 /* SLSplitScreenCell.m */, 78777CDE238FEA48006FA671 /* SLOpenGLController.h */, 78777CDF238FEA48006FA671 /* SLOpenGLController.m */, 788ACD602390BFD400737EC2 /* SLLoadImageVC.h */, diff --git a/iOS_Tips/DarkMode/OpenGL/Controller/SLSplitScreenCell.h b/iOS_Tips/DarkMode/OpenGL/View/SLSplitScreenCell.h similarity index 100% rename from iOS_Tips/DarkMode/OpenGL/Controller/SLSplitScreenCell.h rename to iOS_Tips/DarkMode/OpenGL/View/SLSplitScreenCell.h diff --git a/iOS_Tips/DarkMode/OpenGL/Controller/SLSplitScreenCell.m b/iOS_Tips/DarkMode/OpenGL/View/SLSplitScreenCell.m similarity index 100% rename from iOS_Tips/DarkMode/OpenGL/Controller/SLSplitScreenCell.m rename to iOS_Tips/DarkMode/OpenGL/View/SLSplitScreenCell.m From 809f978834d3bd1b0264d29e3f3941ab34521626 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 22 Oct 2020 20:01:35 +0800 Subject: [PATCH 257/356] =?UTF-8?q?bi=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../OpenGL/Controller/SLOpenGLController.m | 19 +++++++++++++++++-- .../SLShaderLanguageViewController.m | 2 +- .../WorkIssues/\347\254\224\350\256\260.md" | 1 + 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/iOS_Tips/DarkMode/OpenGL/Controller/SLOpenGLController.m b/iOS_Tips/DarkMode/OpenGL/Controller/SLOpenGLController.m index bc266f93..52886a3a 100644 --- a/iOS_Tips/DarkMode/OpenGL/Controller/SLOpenGLController.m +++ b/iOS_Tips/DarkMode/OpenGL/Controller/SLOpenGLController.m @@ -47,8 +47,23 @@ - (void)setupUI { #pragma mark - Data - (void)getData { //tableView、UIAlertView等系统控件,在不自定义颜色的情况下,默认颜色都是动态的,支持暗黑模式 - [self.dataSource addObjectsFromArray:@[@" GLKit 加载图片", @" GLKit 绘制正方体", @" GLKit 颜色和纹理混合金字塔",@" OpenGL ShaderLanguage(GLSL) 加载图片", @" GLSL 绘制金字塔", @" GLSL 颜色和纹理混合", @" GLSL 分屏特效", @" GLSL 滤镜集合", @"GLSL 抖音部分特效集合"]]; - [self.classArray addObjectsFromArray:@[[SLLoadImageVC class], [SLCubeViewController class], [SLGLKPyramidVC class], [SLShaderLanguageViewController class], [SLShaderCubeViewController class], [SLMixColorTextureVC class], [SLSplitScreenViewController class], [SLShaderFilterViewController class], [SLSpecialEffectsViewController class]]]; + [self.dataSource addObjectsFromArray:@[@" GLKit 加载图片", + @" GLKit 绘制正方体", + @" GLKit 颜色和纹理混合金字塔", + @" OpenGL ShaderLanguage(GLSL) 加载图片", + @" GLSL 绘制金字塔", @" GLSL 颜色和纹理混合", + @" GLSL 分屏特效", + @" GLSL 滤镜集合", + @"GLSL 抖音部分特效集合"]]; + [self.classArray addObjectsFromArray:@[[SLLoadImageVC class], + [SLCubeViewController class], + [SLGLKPyramidVC class], + [SLShaderLanguageViewController class], + [SLShaderCubeViewController class], + [SLMixColorTextureVC class], + [SLSplitScreenViewController class], + [SLShaderFilterViewController class], + [SLSpecialEffectsViewController class]]]; [self.tableView reloadData]; } #pragma mark - Getter diff --git a/iOS_Tips/DarkMode/OpenGL/Controller/SLShaderLanguageViewController.m b/iOS_Tips/DarkMode/OpenGL/Controller/SLShaderLanguageViewController.m index 3f46c8b4..7974b9f8 100644 --- a/iOS_Tips/DarkMode/OpenGL/Controller/SLShaderLanguageViewController.m +++ b/iOS_Tips/DarkMode/OpenGL/Controller/SLShaderLanguageViewController.m @@ -326,7 +326,7 @@ -(void)renderLayer { [self setupTexture]; //11. 设置纹理采样器 sampler2D 纹理单元GL_TEXTURE0 - GL_TEXTURE15 总共有16个纹理单元 - glUniform1i(glGetUniformLocation(self.myPrograme, "colorMap"), 0); + glUniform1i(glGetUniformLocation(self.myPrograme, "colorMap"), GL_TEXTURE0); //12.不使用索引数组 绘图 从第0个顶点开始,共六个顶点 glDrawArrays(GL_TRIANGLES, 0, 6); diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index f95e837f..e022916c 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -126,6 +126,7 @@ * 4、[DynamicOC](https://github.com/letqingbin/DynamicOC) * 5、[js-native 通信的 6 种方式](https://mp.weixin.qq.com/s/_Xo6O3NoE1z9AIMJm_uSsA) * 6、[美团外卖客户端容器化架构的演进](https://mp.weixin.qq.com/s/kW5wu7GM7pMRRvN-dQvE2g) +* 7、[SYWebViewBridge](https://mp.weixin.qq.com/s/JDCyWg1AYemxbnFbvY5E9w) ## 七、Shell脚本 From 072aeb4556bd6d8b8803e09d066414f138f35f15 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 22 Oct 2020 20:17:17 +0800 Subject: [PATCH 258/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../OpenGL/Controller/SLShaderLanguageViewController.m | 10 +++++----- iOS_Tips/DarkMode/OpenGL/ShaderLanguage/shaderf.fsh | 4 +++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/iOS_Tips/DarkMode/OpenGL/Controller/SLShaderLanguageViewController.m b/iOS_Tips/DarkMode/OpenGL/Controller/SLShaderLanguageViewController.m index 7974b9f8..7e8f5769 100644 --- a/iOS_Tips/DarkMode/OpenGL/Controller/SLShaderLanguageViewController.m +++ b/iOS_Tips/DarkMode/OpenGL/Controller/SLShaderLanguageViewController.m @@ -21,8 +21,8 @@ OpenGL ES 3种变量修饰符(varying, attribute, uniform) https://blog.csdn.net/hgl868/article/details/7846269 uniform: 由外部客户端传入,由函数glUniform** 提供赋值功能,类似于const, 被uniform 修饰变量在顶点/片元着色器中 只能用,不能修改 一般用来修饰矩阵 - attribute:只能在顶点着色器出现 - varying:中间传递,顶点和片元着色器之间传递数据 + attribute:只能在顶点着色器出现, + varying:中间传递,由顶点着色器传向片元着色器的数据变量 lowp, mediump和highp:精度修饰符声明了底层实现存储这些变量必须要使用的最小范围和精度。实现可能会使用比要求更大的范围和精度,但绝对不会比要求少。 @@ -325,8 +325,8 @@ -(void)renderLayer { //10.加载纹理 [self setupTexture]; - //11. 设置纹理采样器 sampler2D 纹理单元GL_TEXTURE0 - GL_TEXTURE15 总共有16个纹理单元 - glUniform1i(glGetUniformLocation(self.myPrograme, "colorMap"), GL_TEXTURE0); + //11. 设置纹理采样器sampler2D 纹理单元GL_TEXTURE0 - GL_TEXTURE15 总共有16个纹理单元 + glUniform1i(glGetUniformLocation(self.myPrograme, "colorMap"), 0); //12.不使用索引数组 绘图 从第0个顶点开始,共六个顶点 glDrawArrays(GL_TRIANGLES, 0, 6); @@ -424,7 +424,7 @@ - (GLuint)setupTexture{ //7、画图完毕就释放上下文 CGContextRelease(spriteContext); - //8、绑定纹理到默认的纹理ID( + //8、绑定纹理到默认的纹理ID: 0( glBindTexture(GL_TEXTURE_2D, 0); //9.设置纹理属性 diff --git a/iOS_Tips/DarkMode/OpenGL/ShaderLanguage/shaderf.fsh b/iOS_Tips/DarkMode/OpenGL/ShaderLanguage/shaderf.fsh index 636fc5d6..b411d604 100644 --- a/iOS_Tips/DarkMode/OpenGL/ShaderLanguage/shaderf.fsh +++ b/iOS_Tips/DarkMode/OpenGL/ShaderLanguage/shaderf.fsh @@ -7,4 +7,6 @@ void main() } -// 后缀.vsh和.fsh 是可以自定义的,只是为了区分和管理顶点着色器和片元着色器,也可以用字符串存储 +// 后缀.vsh(顶点着色器)和.fsh(片元着色器) 是可以自定义的,只是为了区分和管理顶点着色器和片元着色器,也可以用字符串存储 +// colorMap 采样器 +// varyTextCoord 纹理坐标 由顶点着色器传入,必须和.vsh(顶点着色器)的变量保持一致 From 28a5aa7fcf88071225e91c1c71fa80061f4cf9dd Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 23 Oct 2020 20:10:38 +0800 Subject: [PATCH 259/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xcshareddata/xcschemes/DarkMode.xcscheme | 6 +++++- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/iOS_Tips/DarkMode.xcodeproj/xcshareddata/xcschemes/DarkMode.xcscheme b/iOS_Tips/DarkMode.xcodeproj/xcshareddata/xcschemes/DarkMode.xcscheme index d70c5f89..55ea58eb 100644 --- a/iOS_Tips/DarkMode.xcodeproj/xcshareddata/xcschemes/DarkMode.xcscheme +++ b/iOS_Tips/DarkMode.xcodeproj/xcshareddata/xcschemes/DarkMode.xcscheme @@ -1,7 +1,7 @@ + version = "1.7"> @@ -77,6 +77,10 @@ isEnabled = "YES"> + + Date: Mon, 26 Oct 2020 13:38:58 +0800 Subject: [PATCH 260/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 1dba4a7c..da4f966f 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -74,7 +74,8 @@ > [iOS 崩溃排查技巧:如何获取系统库源码](https://mp.weixin.qq.com/s/YjJo-FB9weGgxEaOfCwBvg) > [iOS 性能优化:优化 App 启动速度](https://mp.weixin.qq.com/s/h3vB_zEJBAHCfGmD5EkMcw) > [iOS 性能优化:使用 MetricKit 2.0 收集数据](https://mp.weixin.qq.com/s/cbP0QlxVlr5oeTrf6yYfFw) -> [iOS性能优化实践:头条抖音如何实现OOM崩溃率下降50%+](https://mp.weixin.qq.com/s/4-4M9E8NziAgshlwB7Sc6g) +> [iOS性能优化实践:头条抖音如何实现OOM崩溃率下降50%+](https://mp.weixin.qq.com/s/4-4M9E8NziAgshlwB7Sc6g) +> [抖音品质建设 - iOS启动优化《原理篇》](https://mp.weixin.qq.com/s/3-Sbqe9gxdV6eI1f435BDg) ## 二、数据结构与算法 From 767064c29d201f88a912118dc557711cea6b134e Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 26 Oct 2020 23:13:01 +0800 Subject: [PATCH 261/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 5 +++-- ...7\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index da4f966f..89be735f 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -75,7 +75,8 @@ > [iOS 性能优化:优化 App 启动速度](https://mp.weixin.qq.com/s/h3vB_zEJBAHCfGmD5EkMcw) > [iOS 性能优化:使用 MetricKit 2.0 收集数据](https://mp.weixin.qq.com/s/cbP0QlxVlr5oeTrf6yYfFw) > [iOS性能优化实践:头条抖音如何实现OOM崩溃率下降50%+](https://mp.weixin.qq.com/s/4-4M9E8NziAgshlwB7Sc6g) -> [抖音品质建设 - iOS启动优化《原理篇》](https://mp.weixin.qq.com/s/3-Sbqe9gxdV6eI1f435BDg) +> [抖音品质建设 - iOS启动优化《原理篇》](https://mp.weixin.qq.com/s/3-Sbqe9gxdV6eI1f435BDg) +> [iOS Rendering 渲染全解析(长文干货)](https://juejin.im/post/6844904162765832206) ## 二、数据结构与算法 @@ -163,7 +164,7 @@ * 1、[CocoaPods 都做了什么?](https://www.jianshu.com/p/84936d9344ff) * 2、[1. 版本管理工具及 Ruby 工具链环境](https://mp.weixin.qq.com/s/s2yJEb2P0_Kk-rIpYBi_9A) -* 3、[2. 整体把握 CocoaPods 核心组件](https://mp.weixin.qq.com/s/eyjrhPgPFdidPWO7t2SDcA) +* 3、[2. 整体把握 CocoaPods 核心组件](https://looseyi.github.io/post/sourcecode-cocoapods/02-cocoapods-corecomponents/) * 4、[OCLint 实现 Code Review - 给你的代码提提质量](https://juejin.im/post/6844903853775650830) * 5、[(译)开源软件架构之 LLVM(The Architecture of Open Source Applications LLVM)](https://juejin.im/post/6844904034134917134) * 6、[你真的会用 CocoaPods 吗?](https://juejin.im/post/6844903506734759949) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index e0f7d62a..e0238a42 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -68,6 +68,7 @@ * 66、[mcuking](https://github.com/mcuking/blog) * 67、[冬瓜争做全栈瓜](https://www.desgard.com) * 68、[iOS一叶](https://juejin.im/user/1899557248829438) +* 68、[土土Edmond木](https://looseyi.github.io) ## 高质量微信公众号 @@ -89,6 +90,7 @@ * 16、[老司机技术周报](公众号:LSJCoding) * 17、[淘系技术](公众号:AlibabaMTT) * 18、[我是程序员小贱](公众号:Lanj1995Q) +* 19、[腾讯技术工程](公众号:Tencent_TEG) ## 书籍 From 20166a5a87b72508eb6f68a40e484032f8d64c22 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 27 Oct 2020 15:05:08 +0800 Subject: [PATCH 262/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 4 +++- ...07\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 89be735f..8cd98ec9 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -76,7 +76,8 @@ > [iOS 性能优化:使用 MetricKit 2.0 收集数据](https://mp.weixin.qq.com/s/cbP0QlxVlr5oeTrf6yYfFw) > [iOS性能优化实践:头条抖音如何实现OOM崩溃率下降50%+](https://mp.weixin.qq.com/s/4-4M9E8NziAgshlwB7Sc6g) > [抖音品质建设 - iOS启动优化《原理篇》](https://mp.weixin.qq.com/s/3-Sbqe9gxdV6eI1f435BDg) -> [iOS Rendering 渲染全解析(长文干货)](https://juejin.im/post/6844904162765832206) +> [iOS Rendering 渲染全解析(长文干货)](https://juejin.im/post/6844904162765832206) +> [再谈 iOS App Crash 防护](https://mp.weixin.qq.com/s/l5S_g1PBCiwm4KDtqNFb-A) ## 二、数据结构与算法 @@ -109,6 +110,7 @@ * 4、[Injection:iOS热重载背后的黑魔法](https://mp.weixin.qq.com/s/hFnHdOP6pmIwzZck-zXE8g) * 5、[高效逆向 - 为任意iOS App生成符号表](https://github.com/imoldman/DSYMCreator) * 6、[iOS LLVM-Clang 浅谈](https://www.jianshu.com/p/7ceca351a045) +* 7、[iOSer逆向](https://iosre.com) ## 五、音视频 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index e0238a42..eb57b37c 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -68,7 +68,8 @@ * 66、[mcuking](https://github.com/mcuking/blog) * 67、[冬瓜争做全栈瓜](https://www.desgard.com) * 68、[iOS一叶](https://juejin.im/user/1899557248829438) -* 68、[土土Edmond木](https://looseyi.github.io) +* 69、[土土Edmond木](https://looseyi.github.io) +* 70、[iOSer逆向](https://iosre.com) ## 高质量微信公众号 From 52b968c162e4fdb44ba5ac10b1cbe10eee7ad9dd Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 27 Oct 2020 22:27:54 +0800 Subject: [PATCH 263/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 2 ++ 1 file changed, 2 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 9014df61..6eca63ed 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -5,3 +5,5 @@ * 1、 [为什么iOS更新UI操作必须在主线程?](https://778477.github.io/2017/06/19/2017-06-19-为什么iOS更新UI操作必须在主线程/) * 2、Swift和OC的方法调用流程区别? * 3、[iOS性能优化实践:头条抖音如何实现OOM崩溃率下降50%+](https://mp.weixin.qq.com/s/4-4M9E8NziAgshlwB7Sc6g) +* 4、[GCD](https://looseyi.github.io/post/notes/01-gcd/) +* 5、[runloop](https://blog.ibireme.com/2015/05/18/runloop/) From 59cf229ffe28799658620b35a7bf8e908d5a7d6c Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 29 Oct 2020 19:58:11 +0800 Subject: [PATCH 264/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 5 ++++- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 8cd98ec9..10440b4d 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -77,12 +77,14 @@ > [iOS性能优化实践:头条抖音如何实现OOM崩溃率下降50%+](https://mp.weixin.qq.com/s/4-4M9E8NziAgshlwB7Sc6g) > [抖音品质建设 - iOS启动优化《原理篇》](https://mp.weixin.qq.com/s/3-Sbqe9gxdV6eI1f435BDg) > [iOS Rendering 渲染全解析(长文干货)](https://juejin.im/post/6844904162765832206) -> [再谈 iOS App Crash 防护](https://mp.weixin.qq.com/s/l5S_g1PBCiwm4KDtqNFb-A) +> [再谈 iOS App Crash 防护](https://mp.weixin.qq.com/s/l5S_g1PBCiwm4KDtqNFb-A) +> [iOS 网络优化: 使你的 App 网络交互更流畅](https://mp.weixin.qq.com/s/YLvpYBwaz8L6fnmzL78Mfg) ## 二、数据结构与算法 * 1、 [LeetcodeTop](https://github.com/afatcoder/LeetcodeTop) * 2、[小浩算法](https://www.geekxh.com) +* 3、[labuladong的算法小抄](https://labuladong.gitbook.io/algo/) ## 三、面试题相关 @@ -111,6 +113,7 @@ * 5、[高效逆向 - 为任意iOS App生成符号表](https://github.com/imoldman/DSYMCreator) * 6、[iOS LLVM-Clang 浅谈](https://www.jianshu.com/p/7ceca351a045) * 7、[iOSer逆向](https://iosre.com) +* 8、[fishhook 原理探究](https://mp.weixin.qq.com/s/uP3PASr7IoOMCQ-yy4RanA) ## 五、音视频 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 6eca63ed..2b727d18 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -7,3 +7,8 @@ * 3、[iOS性能优化实践:头条抖音如何实现OOM崩溃率下降50%+](https://mp.weixin.qq.com/s/4-4M9E8NziAgshlwB7Sc6g) * 4、[GCD](https://looseyi.github.io/post/notes/01-gcd/) * 5、[runloop](https://blog.ibireme.com/2015/05/18/runloop/) +* 6、[Weak的实现原理]() +* 6、[Block() +* 6、[AutoreleasePool]() +* 6、[编译过程]() +* 6、[启动过程]() From 44ab90e54192cf2fa1853dbf2470a600af90ea67 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 29 Oct 2020 21:56:19 +0800 Subject: [PATCH 265/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 10440b4d..b6b8e73f 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -103,6 +103,7 @@ * 13、[iOS 基础](https://juejin.im/user/940837683069549/posts) * 14、[深入理解RunLoop](https://blog.ibireme.com/2015/05/18/runloop/) * 15、[BoyangBlog](https://github.com/BiBoyang/BoyangBlog.git) +*16、[阿里、字节:一套高效的iOS面试题](https://juejin.im/post/6844904064937902094) ## 四、逆向与安全 From 91a1c5dff17610bf8dce30c64b7bd75dbe270c62 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 3 Nov 2020 14:45:04 +0800 Subject: [PATCH 266/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 4 +++- ...07\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index b6b8e73f..fd9ef70b 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -78,7 +78,9 @@ > [抖音品质建设 - iOS启动优化《原理篇》](https://mp.weixin.qq.com/s/3-Sbqe9gxdV6eI1f435BDg) > [iOS Rendering 渲染全解析(长文干货)](https://juejin.im/post/6844904162765832206) > [再谈 iOS App Crash 防护](https://mp.weixin.qq.com/s/l5S_g1PBCiwm4KDtqNFb-A) -> [iOS 网络优化: 使你的 App 网络交互更流畅](https://mp.weixin.qq.com/s/YLvpYBwaz8L6fnmzL78Mfg) +> [iOS 网络优化: 使你的 App 网络交互更流畅](https://mp.weixin.qq.com/s/YLvpYBwaz8L6fnmzL78Mfg) +> [GoldHouse-for-iOS](https://github.com/BiBoyang/GoldHouse-for-iOS) + ## 二、数据结构与算法 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index eb57b37c..a989b897 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -70,6 +70,7 @@ * 68、[iOS一叶](https://juejin.im/user/1899557248829438) * 69、[土土Edmond木](https://looseyi.github.io) * 70、[iOSer逆向](https://iosre.com) +* 71、[GoldHouse-for-iOS](https://github.com/BiBoyang/GoldHouse-for-iOS) ## 高质量微信公众号 From 715adb2efc807edabca9927f655f852043546e19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=AE=E5=8D=9A=40=E4=B8=94=E8=A1=8C=E4=B8=94=E7=8F=8D?= =?UTF-8?q?=E6=83=9C=5FiOS?= <15324956576@163.com> Date: Thu, 5 Nov 2020 17:02:14 +0800 Subject: [PATCH 267/356] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 56be18f6..b53ce6c0 100644 --- a/README.md +++ b/README.md @@ -83,8 +83,6 @@ > 效果描述:实时拍摄添加水印和滤镜、本地视频添加水印、GIF图水印 -* 遗留问题:一个启动周期内,第一次启动摄像头时打开特慢,之后就特别块,还没找到原因,望知道到的告知一下🤝 - ![GPUImage框架的使用](https://github.com/wsl2ls/iOS_TipsPreview/blob/master/PrviewPicture/6、GPUImage.gif) #### 3.5-VideoToolBox和AudioToolBox音视频编解码 From 1b4698cd069621b7b5505a3b8baa2175087ace66 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 5 Nov 2020 20:40:50 +0800 Subject: [PATCH 268/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 10 +- iOS_Tips/DarkMode/.DS_Store | Bin 14340 -> 14340 bytes iOS_Tips/DarkMode/General/Tool/HMLog.h | 236 ++++++++++++++++++ .../\345\267\262\346\265\217\350\247\210.md" | 14 ++ .../\351\235\242\350\257\225\351\242\230.md" | 10 +- ...00\346\234\257\345\215\232\345\256\242.md" | 6 +- 6 files changed, 268 insertions(+), 8 deletions(-) create mode 100644 iOS_Tips/DarkMode/General/Tool/HMLog.h create mode 100644 "iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index d7fe7eb0..a1cccdf1 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 2CC813682553CE88009DAC9B /* 已浏览.md in Resources */ = {isa = PBXBuildFile; fileRef = 2CC813672553CE88009DAC9B /* 已浏览.md */; }; 2CEBE85D24A6E65600BA21F3 /* SLTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CEBE85B24A6E65600BA21F3 /* SLTimer.m */; }; 780F5303236D8462000D0EA8 /* SLGridView.m in Sources */ = {isa = PBXBuildFile; fileRef = 780F5302236D8462000D0EA8 /* SLGridView.m */; }; 780F5306236D8570000D0EA8 /* SLImageClipController.m in Sources */ = {isa = PBXBuildFile; fileRef = 780F5305236D8570000D0EA8 /* SLImageClipController.m */; }; @@ -213,6 +214,8 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 2CC813672553CE88009DAC9B /* 已浏览.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = "已浏览.md"; sourceTree = ""; }; + 2CC8137925540CB8009DAC9B /* HMLog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HMLog.h; sourceTree = ""; }; 2CEBE85B24A6E65600BA21F3 /* SLTimer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLTimer.m; sourceTree = ""; }; 2CEBE85C24A6E65600BA21F3 /* SLTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLTimer.h; sourceTree = ""; }; 780F5301236D845B000D0EA8 /* SLGridView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLGridView.h; sourceTree = ""; }; @@ -846,6 +849,7 @@ isa = PBXGroup; children = ( 78AA10F42371A7B50044A6F8 /* PrefixHeader.pch */, + 2CC8137925540CB8009DAC9B /* HMLog.h */, 78F4E41224E5404A000B2ADE /* SLToolMacro.h */, 78777CE4238FF65C006FA671 /* SLDelayPerform.h */, 78777CE5238FF65C006FA671 /* SLDelayPerform.m */, @@ -938,6 +942,7 @@ 784C4C6F24C5B5DD00D5C199 /* 高质量技术博客.md */, 784C4C6D24C5B4F500D5C199 /* 笔记.md */, 785D06632522C32700F174BA /* 面试题.md */, + 2CC813672553CE88009DAC9B /* 已浏览.md */, 7884247D2492102900C2E505 /* SLWorkIssuesViewController.h */, 7884247E2492102900C2E505 /* SLWorkIssuesViewController.m */, 78908DC024FFBD83004164C2 /* ScrollView嵌套 */, @@ -1427,6 +1432,7 @@ 7811F77124B2C818000AA044 /* wsl.order in Resources */, 78E72D59247BA29600751373 /* WebTableView.html in Resources */, 782CFB7A239E6A11001B5528 /* Glitch.vsh in Resources */, + 2CC813682553CE88009DAC9B /* 已浏览.md in Resources */, 782CFB5A239E6227001B5528 /* Gray.fsh in Resources */, 782CFB66239E6651001B5528 /* HexagonMosaic.fsh in Resources */, 782CFB79239E6A11001B5528 /* Glitch.fsh in Resources */, @@ -1814,7 +1820,7 @@ NEW_SETTING = ""; ORDER_FILE = "$(SRCROOT)/DarkMode/WorkIssues/二进制重排/wsl.order"; OTHER_CFLAGS = "-fsanitize-coverage=func,trace-pc-guard"; - PRODUCT_BUNDLE_IDENTIFIER = com.wsl2ls.tips; + PRODUCT_BUNDLE_IDENTIFIER = com.wsl2ls.iostip; PRODUCT_NAME = SLTips; PROVISIONING_PROFILE_SPECIFIER = ""; TARGETED_DEVICE_FAMILY = "1,2"; @@ -1846,7 +1852,7 @@ NEW_SETTING = ""; ORDER_FILE = "$(SRCROOT)/DarkMode/WorkIssues/二进制重排/wsl.order"; OTHER_CFLAGS = "-fsanitize-coverage=func,trace-pc-guard"; - PRODUCT_BUNDLE_IDENTIFIER = com.wsl2ls.tips; + PRODUCT_BUNDLE_IDENTIFIER = com.wsl2ls.iostip; PRODUCT_NAME = SLTips; PROVISIONING_PROFILE_SPECIFIER = ""; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/iOS_Tips/DarkMode/.DS_Store b/iOS_Tips/DarkMode/.DS_Store index e5fa5b0fb1e5ebf6b6ae4be8472a30e8c86e4bb3..05e7465d5ddd335c7f5ec7003ee1faa1b3eac77a 100644 GIT binary patch delta 23 bcmZoEXerpROOnaJZ1Wz;fBaxt(}NEHa&ZX1 delta 23 bcmZoEXerpROOnaVa`PU^fBaxt(}NEHb1?|f diff --git a/iOS_Tips/DarkMode/General/Tool/HMLog.h b/iOS_Tips/DarkMode/General/Tool/HMLog.h new file mode 100644 index 00000000..ef1bf35f --- /dev/null +++ b/iOS_Tips/DarkMode/General/Tool/HMLog.h @@ -0,0 +1,236 @@ +// The MIT License (MIT) +// +// Copyright (c) 2020 Huimao Chen +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +// GCC_C_LANGUAGE_STANDARD = gnu99 + +#ifndef HMLog_h +#define HMLog_h + +#import + +#pragma mark - Parameters + +// All optional parameters should be defined before import "HMLog.h", or you can modify the source code + +#ifndef HMLogEnable +#define HMLogEnable 1 +#endif // HMLogEnable + +#ifndef HMPrintEnable +#define HMPrintEnable 1 +#endif // HMPrintEnable + +#ifndef HMLogPrefix +#define HMLogPrefix(index, valueString) [NSString stringWithFormat:@"%d: %s = ", index, valueString] +#endif // HMLogPrefix + +#ifndef HMLogHeaderFormatString +#define HMLogHeaderFormatString(FUNC, LINE) \ + [NSString stringWithFormat:@"================ %s [%d] ================\n", FUNC, LINE] +#endif // HMLogHeaderFormatString + +#ifndef HMLogTypeExtension +#define HMLogTypeExtension +#endif // HMLogTypeExtension + +#pragma mark - Core + +// format, private macro +#define _HMLogFormat(VAR) \ + , HMStringify(VAR), @encode(__typeof__(VAR)), (VAR) + +// HMFormatString +#define HMFormatString(...) \ + HMExpand(_HMFormatString(__func__, __LINE__, HMArgCount(__VA_ARGS__) HMForeach(_HMLogFormat, __VA_ARGS__))) + +// HMLog +#if HMLogEnable + #define HMLog(...) \ + _HMLog(HMFormatString(__VA_ARGS__)) +#else + #define HMLog(...) +#endif // HMLogEnable + +// HMPrint +#if HMPrintEnable + #define HMPrint(...) \ + _HMPrint(HMFormatString(__VA_ARGS__)) +#else + #define HMPrint(...) +#endif // HMPrintEnable + + +static inline NSString * _HMFormatString(const char *func, int line, int count, ...) { // func, line, count, [valueString, TypeEncode, value] + NSMutableString *result = [[NSMutableString alloc] init]; + + // handle header + [result appendString:HMLogHeaderFormatString(func, line)]; + + // handle arguments + va_list v; + va_start(v, count); + for (int i = 0; i < count; ++i) { + char *valueString = va_arg(v, char *); + char *type = va_arg(v, char *); + + id obj = nil; + if (strcmp(type, @encode(id)) == 0) { // "@" id + id actual = va_arg(v, id); + obj = actual; + + } else if (strcmp(type, @encode(CGPoint)) == 0) { // "{CGPoint=dd}" CGPoint + CGPoint actual = (CGPoint)va_arg(v, CGPoint); + obj = [NSValue value:&actual withObjCType:type]; + + } else if (strcmp(type, @encode(CGSize)) == 0) { // "{CGSize=dd}" CGSize + CGSize actual = (CGSize)va_arg(v, CGSize); + obj = [NSValue value:&actual withObjCType:type]; + + } else if (strcmp(type, @encode(CGRect)) == 0) { // "{CGRect={CGPoint=dd}{CGSize=dd}}" CGRect + CGRect actual = (CGRect)va_arg(v, CGRect); + obj = [NSValue value:&actual withObjCType:type]; + + } else if (strcmp(type, @encode(UIEdgeInsets)) == 0) { // "{UIEdgeInsets=dddd}" UIEdgeInsets + UIEdgeInsets actual = (UIEdgeInsets)va_arg(v, UIEdgeInsets); + obj = NSStringFromUIEdgeInsets(actual); + + } else if (strcmp(type, @encode(NSRange)) == 0) { // "{_NSRange=QQ}" NSRange + NSRange actual = (NSRange)va_arg(v, NSRange); + obj = NSStringFromRange(actual); + + } else if (strcmp(type, @encode(SEL)) == 0) { // ":" SEL + SEL actual = (SEL)va_arg(v, SEL); + obj = [NSString stringWithFormat:@"SEL: %@", NSStringFromSelector(actual)]; + + } else if (strcmp(type, @encode(Class)) == 0) { // "#" Class + Class actual = (Class)va_arg(v, Class); + obj = NSStringFromClass(actual); + + } else if (strcmp(type, @encode(char *)) == 0) { // "*" char * + char * actual = (char *)va_arg(v, char *); + obj = [NSString stringWithFormat:@"%s", actual]; + + } else if (strcmp(type, @encode(double)) == 0) { // "d" double + double actual = (double)va_arg(v, double); + obj = [NSNumber numberWithDouble:actual]; + + } else if (strcmp(type, @encode(float)) == 0) { // "f" float + float actual = (float)va_arg(v, double); + obj = [NSNumber numberWithFloat:actual]; + + } else if (strcmp(type, @encode(int)) == 0) { // "i" int + int actual = (int)va_arg(v, int); + obj = [NSNumber numberWithInt:actual]; + + } else if (strcmp(type, @encode(long)) == 0) { // "q" long + long actual = (long)va_arg(v, long); + obj = [NSNumber numberWithLong:actual]; + + } else if (strcmp(type, @encode(long long)) == 0) { // "q" long long + long long actual = (long long)va_arg(v, long long); + obj = [NSNumber numberWithLongLong:actual]; + + } else if (strcmp(type, @encode(short)) == 0) { // "s" short + short actual = (short)va_arg(v, int); + obj = [NSNumber numberWithShort:actual]; + + } else if (strcmp(type, @encode(char)) == 0) { // "c" char & BOOL(32bit) + char actual = (char)va_arg(v, int); + obj = [NSString stringWithFormat:@"%d char:%c", actual, actual]; + + } else if (strcmp(type, @encode(bool)) == 0) { // "B" bool & BOOL(64bit) + bool actual = (bool)va_arg(v, int); + obj = actual ? @"YES" : @"NO"; + + } else if (strcmp(type, @encode(unsigned char)) == 0) { // "C" unsigned char + unsigned char actual = (unsigned char)va_arg(v, unsigned int); + obj = [NSString stringWithFormat:@"%d unsigned char:%c", actual, actual]; + + } else if (strcmp(type, @encode(unsigned int)) == 0) { // "I" unsigned int + unsigned int actual = (unsigned int)va_arg(v, unsigned int); + obj = [NSNumber numberWithUnsignedInt:actual]; + + } else if (strcmp(type, @encode(unsigned long)) == 0) { // "Q" unsigned long + unsigned long actual = (unsigned long)va_arg(v, unsigned long); + obj = [NSNumber numberWithUnsignedLong:actual]; + + } else if (strcmp(type, @encode(unsigned long long)) == 0) { // "Q" unsigned long long + unsigned long long actual = (unsigned long long)va_arg(v, unsigned long long); + obj = [NSNumber numberWithUnsignedLongLong:actual]; + + } else if (strcmp(type, @encode(unsigned short)) == 0) { // "S" unsigned short + unsigned short actual = (unsigned short)va_arg(v, unsigned int); + obj = [NSNumber numberWithUnsignedShort:actual]; + + } HMLogTypeExtension else { + [result appendString:@"Error: unknown type"]; + break; + } + + [result appendFormat:@"%@%@\n", ((void)(valueString), HMLogPrefix(i, valueString)), obj]; + } + va_end(v); + + return [result copy]; +} + +static inline void _HMLog(NSString *str) { + NSLog(@"\n%@", str); +} + +static inline void _HMPrint(NSString *str) { + printf("%s\n", str.UTF8String); +} + +#pragma mark - Helper + +#define HMStringify(VALUE) _HMStringify(VALUE) +#define _HMStringify(VALUE) # VALUE + +#define HMConcat(A, B) _HMConcat(A, B) +#define _HMConcat(A, B) A ## B + +// Return the number of arguments (up to twenty) provided to the macro. +#define HMArgCount(...) _HMArgCount(A, ##__VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) +#define _HMArgCount(A, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, COUNT, ...) COUNT + +// If the number of arguments is 0, return 0, otherwise return N. +#define HMArgCheck(...) _HMArgCheck(A, ##__VA_ARGS__, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, 0) +#define _HMArgCheck(A, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, OBJ, ...) OBJ + +// Each argument will be passed to the MACRO, the MACRO must be this form: MACRO(arg). Inspired by https://stackoverflow.com/questions/3136686/is-the-c99-preprocessor-turing-complete/10526117#10526117 +#define HMForeach(MACRO, ...) HMConcat(_HMForeach, HMArgCheck(__VA_ARGS__)) (MACRO, ##__VA_ARGS__) +#define _HMForeach() HMForeach +#define _HMForeach0(MACRO) +#define _HMForeachN(MACRO, A, ...) MACRO(A) HMDefer(_HMForeach)() (MACRO, ##__VA_ARGS__) + +#define HMEmpty() +#define HMDefer(ID) ID HMEmpty() + +// For more scans +#define HMExpand(...) _HMExpand1(_HMExpand1(_HMExpand1(__VA_ARGS__))) +#define _HMExpand1(...) _HMExpand2(_HMExpand2(_HMExpand2(__VA_ARGS__))) +#define _HMExpand2(...) _HMExpand3(_HMExpand3(_HMExpand3(__VA_ARGS__))) +#define _HMExpand3(...) __VA_ARGS__ + + +#endif // HMLog_h diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" new file mode 100644 index 00000000..60604f9e --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -0,0 +1,14 @@ + + +## 已浏览 + +* 1、[iOS插件化架构探索](https://mp.weixin.qq.com/s/QJ9YHX-Uy6lDIhJe_5wPGw) +* 2、 +* 3、 +* 4、 +* 5、 +* 6、 +* 7、 +* 8、 +* 9、 +* 10、 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 2b727d18..d68114d1 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -3,12 +3,12 @@ ## 面试知识点 * 1、 [为什么iOS更新UI操作必须在主线程?](https://778477.github.io/2017/06/19/2017-06-19-为什么iOS更新UI操作必须在主线程/) -* 2、Swift和OC的方法调用流程区别? +* 2、[Swift和OC的方法调用流程区别]() * 3、[iOS性能优化实践:头条抖音如何实现OOM崩溃率下降50%+](https://mp.weixin.qq.com/s/4-4M9E8NziAgshlwB7Sc6g) * 4、[GCD](https://looseyi.github.io/post/notes/01-gcd/) * 5、[runloop](https://blog.ibireme.com/2015/05/18/runloop/) * 6、[Weak的实现原理]() -* 6、[Block() -* 6、[AutoreleasePool]() -* 6、[编译过程]() -* 6、[启动过程]() +* 7、[Block() +* 8、[AutoreleasePool]() +* 9、[编译过程]() +* 10、[启动过程]() diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index a989b897..d76570c3 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -1,5 +1,5 @@ -## 高质量技术博客集合 +## 高质量技术博客 * 1、[WeRead团队博客](https://wereadteam.github.io/) * 2、[美团技术团队](https://tech.meituan.com/) @@ -71,6 +71,8 @@ * 69、[土土Edmond木](https://looseyi.github.io) * 70、[iOSer逆向](https://iosre.com) * 71、[GoldHouse-for-iOS](https://github.com/BiBoyang/GoldHouse-for-iOS) +* 72、[折腾范儿の味精](http://awhisper.github.io) + ## 高质量微信公众号 @@ -93,6 +95,8 @@ * 17、[淘系技术](公众号:AlibabaMTT) * 18、[我是程序员小贱](公众号:Lanj1995Q) * 19、[腾讯技术工程](公众号:Tencent_TEG) +* 20、[搜狐技术产品](公众号:sohu-tech) +* 21、[百度APP技术](公众号:gh_59f5931152fe) ## 书籍 From a03356c5984505c3454f23cd35c22c69fb620b53 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 5 Nov 2020 22:42:48 +0800 Subject: [PATCH 269/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index fd9ef70b..90bcf8b9 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -137,6 +137,7 @@ * 5、[js-native 通信的 6 种方式](https://mp.weixin.qq.com/s/_Xo6O3NoE1z9AIMJm_uSsA) * 6、[美团外卖客户端容器化架构的演进](https://mp.weixin.qq.com/s/kW5wu7GM7pMRRvN-dQvE2g) * 7、[SYWebViewBridge](https://mp.weixin.qq.com/s/JDCyWg1AYemxbnFbvY5E9w) +* 8、[JSPatch-实现原理详解](https://github.com/bang590/JSPatch/wiki/JSPatch-实现原理详解) ## 七、Shell脚本 From 85cf9f2e34a386ed91b1b7611a2be00f30eeea29 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 6 Nov 2020 14:45:36 +0800 Subject: [PATCH 270/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 2 +- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 60604f9e..95b36c35 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -3,7 +3,7 @@ ## 已浏览 * 1、[iOS插件化架构探索](https://mp.weixin.qq.com/s/QJ9YHX-Uy6lDIhJe_5wPGw) -* 2、 +* 2、[WKWebview秒开实践分享及问题解决方案](https://juejin.im/post/6887161842406260744) * 3、 * 4、 * 5、 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 90bcf8b9..623e4b0a 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -138,6 +138,7 @@ * 6、[美团外卖客户端容器化架构的演进](https://mp.weixin.qq.com/s/kW5wu7GM7pMRRvN-dQvE2g) * 7、[SYWebViewBridge](https://mp.weixin.qq.com/s/JDCyWg1AYemxbnFbvY5E9w) * 8、[JSPatch-实现原理详解](https://github.com/bang590/JSPatch/wiki/JSPatch-实现原理详解) +* 9、[WKWebview秒开实践分享及问题解决方案](https://juejin.im/post/6887161842406260744) ## 七、Shell脚本 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index d68114d1..82d20c72 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -12,3 +12,5 @@ * 8、[AutoreleasePool]() * 9、[编译过程]() * 10、[启动过程]() +* 11、[http1.0->1.1->2.2分别升级了什么……](https://www.cnblogs.com/riwang/p/12370785.html) +* 12、[就是这个HTTP1.1这个什么身份认证](https://blog.csdn.net/zhongshanxian/article/details/81294829) From f83f9d4d0265fef73d9540c6281d930e761b7e7c Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 6 Nov 2020 23:52:01 +0800 Subject: [PATCH 271/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/APM/APMMonitor/SLSystemAppInfo.h | 2 +- .../WorkIssues/APM/APMMonitor/SLSystemAppInfo.m | 2 +- .../\345\267\262\346\265\217\350\247\210.md" | 2 +- .../WorkIssues/\347\254\224\350\256\260.md" | 4 ++-- .../\351\235\242\350\257\225\351\242\230.md" | 15 ++++++++++----- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h index 83334dca..cbb31b7f 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h @@ -42,7 +42,7 @@ NS_ASSUME_NONNULL_BEGIN + (NSString *)systemName; ///获取用户手机别名 用户定义的名称 通用-关于本机-名称 wsl的iphone + (NSString *)userPhoneName; -///设备唯一标识的字母数字字符串 C5668446-C443-4898-A213-209AECE3626C +///设备唯一标识的字母数字字符串 但如果用户重新安装,那么这个 UUID 就会发生变化。 C5668446-C443-4898-A213-209AECE3626C + (NSString *)uuidString; ///是否是iPhoneX系列/刘海屏 + (BOOL)isIPhoneXSeries; diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m index 2094a5b6..974e58fc 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m @@ -150,7 +150,7 @@ + (NSString *)userPhoneName { NSString* userPhoneName = [[UIDevice currentDevice] name]; return userPhoneName; } -///设备唯一标识的字母数字字符串 C5668446-C443-4898-A213-209AECE3626C +///设备唯一标识的字母数字字符串,但如果用户重新安装,那么这个 UUID 就会发生变化。 C5668446-C443-4898-A213-209AECE3626C + (NSString *)uuidString { NSString *UUIDString = [[UIDevice currentDevice] identifierForVendor].UUIDString; return UUIDString; diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 95b36c35..9a23ee02 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -4,7 +4,7 @@ * 1、[iOS插件化架构探索](https://mp.weixin.qq.com/s/QJ9YHX-Uy6lDIhJe_5wPGw) * 2、[WKWebview秒开实践分享及问题解决方案](https://juejin.im/post/6887161842406260744) -* 3、 +* 3、[iOS基础](https://juejin.im/user/4371313963043661/posts) * 4、 * 5、 * 6、 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 623e4b0a..8ed9804a 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -79,8 +79,8 @@ > [iOS Rendering 渲染全解析(长文干货)](https://juejin.im/post/6844904162765832206) > [再谈 iOS App Crash 防护](https://mp.weixin.qq.com/s/l5S_g1PBCiwm4KDtqNFb-A) > [iOS 网络优化: 使你的 App 网络交互更流畅](https://mp.weixin.qq.com/s/YLvpYBwaz8L6fnmzL78Mfg) -> [GoldHouse-for-iOS](https://github.com/BiBoyang/GoldHouse-for-iOS) - +> [GoldHouse-for-iOS](https://github.com/BiBoyang/GoldHouse-for-iOS) +> [卡顿率降低50%!京东商城APP卡顿监控及优化实践](https://mp.weixin.qq.com/s/aJeAUAjcKOMvznDMGj2UUA) ## 二、数据结构与算法 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 82d20c72..ad4c8e8e 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -1,6 +1,6 @@ -## 面试知识点 +## 面试题 * 1、 [为什么iOS更新UI操作必须在主线程?](https://778477.github.io/2017/06/19/2017-06-19-为什么iOS更新UI操作必须在主线程/) * 2、[Swift和OC的方法调用流程区别]() @@ -10,7 +10,12 @@ * 6、[Weak的实现原理]() * 7、[Block() * 8、[AutoreleasePool]() -* 9、[编译过程]() -* 10、[启动过程]() -* 11、[http1.0->1.1->2.2分别升级了什么……](https://www.cnblogs.com/riwang/p/12370785.html) -* 12、[就是这个HTTP1.1这个什么身份认证](https://blog.csdn.net/zhongshanxian/article/details/81294829) +* 9、[编译过程](https://juejin.im/post/6844904040841641998) +* 10、[启动过程](https://juejin.im/post/6844904041873408013) +* 11、[http1.0->1.1->2.2->3区别](https://www.cnblogs.com/riwang/p/12370785.html) +* 12、[HTTP1.1身份认证-摘要认证](https://blog.csdn.net/zhongshanxian/article/details/81294829) +* 13、[聊聊DNS劫持](https://www.jianshu.com/p/63a94cb46cd2) +* 14、[如何保障客户端与服务器交互中的数据安全](https://netsecurity.51cto.com/art/202002/610473.htm) +* 15、[设计一个线程池](https://www.jianshu.com/p/5bb4123e415c)、[iOS 任务调度器:为 CPU和内存减负](https://www.jianshu.com/p/f2a610c77d26) +* 16、[线程怎么保活](https://www.jianshu.com/p/2ffa6678f83d) +* 17、[内存满了之后如何处理](https://juejin.im/post/6844903550187733000) From e6edfdc8ebb950246c80a34e7102c306010c1279 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sun, 8 Nov 2020 16:37:57 +0800 Subject: [PATCH 272/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\347\254\224\350\256\260.md" | 8 +++++- .../\351\235\242\350\257\225\351\242\230.md" | 28 ++++++++++++++----- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 8ed9804a..3140b470 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -105,7 +105,8 @@ * 13、[iOS 基础](https://juejin.im/user/940837683069549/posts) * 14、[深入理解RunLoop](https://blog.ibireme.com/2015/05/18/runloop/) * 15、[BoyangBlog](https://github.com/BiBoyang/BoyangBlog.git) -*16、[阿里、字节:一套高效的iOS面试题](https://juejin.im/post/6844904064937902094) +* 16、[阿里、字节:一套高效的iOS面试题](https://juejin.im/post/6844904064937902094) +* 17、[《招聘一个靠谱的 iOS》](https://github.com/ChenYilong/iOSInterviewQuestions) ## 四、逆向与安全 @@ -169,6 +170,11 @@ * 2、[波儿菜](https://juejin.im/user/2735240659351112) * 3、[写给自己看系列之WebViewJavascriptBridge源码分析](https://juejin.im/post/6844904097192247303) * 4、[JSBridge 实现原理解析](https://github.com/mcuking/blog/issues/39) +* 5、[MLeaksFinder]() +* 6、[JSPatch]() +* 7、[Fishook]() +* 8、[Aspect]() + ## 其它 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index ad4c8e8e..2db9598c 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -2,6 +2,9 @@ ## 面试题 + +### iOS + * 1、 [为什么iOS更新UI操作必须在主线程?](https://778477.github.io/2017/06/19/2017-06-19-为什么iOS更新UI操作必须在主线程/) * 2、[Swift和OC的方法调用流程区别]() * 3、[iOS性能优化实践:头条抖音如何实现OOM崩溃率下降50%+](https://mp.weixin.qq.com/s/4-4M9E8NziAgshlwB7Sc6g) @@ -12,10 +15,21 @@ * 8、[AutoreleasePool]() * 9、[编译过程](https://juejin.im/post/6844904040841641998) * 10、[启动过程](https://juejin.im/post/6844904041873408013) -* 11、[http1.0->1.1->2.2->3区别](https://www.cnblogs.com/riwang/p/12370785.html) -* 12、[HTTP1.1身份认证-摘要认证](https://blog.csdn.net/zhongshanxian/article/details/81294829) -* 13、[聊聊DNS劫持](https://www.jianshu.com/p/63a94cb46cd2) -* 14、[如何保障客户端与服务器交互中的数据安全](https://netsecurity.51cto.com/art/202002/610473.htm) -* 15、[设计一个线程池](https://www.jianshu.com/p/5bb4123e415c)、[iOS 任务调度器:为 CPU和内存减负](https://www.jianshu.com/p/f2a610c77d26) -* 16、[线程怎么保活](https://www.jianshu.com/p/2ffa6678f83d) -* 17、[内存满了之后如何处理](https://juejin.im/post/6844903550187733000) +* 11、[设计一个线程池](https://www.jianshu.com/p/5bb4123e415c)、[iOS 任务调度器:为 CPU和内存减负](https://www.jianshu.com/p/f2a610c77d26) +* 12、[线程怎么保活](https://www.jianshu.com/p/2ffa6678f83d) +* 13、[内存满了之后如何处理](https://juejin.im/post/6844903550187733000) +* 14、[如何使用 Runtime 给现有的类添加 weak 属性](https://github.com/ChenYilong/iOSInterviewQuestions) +* 15、[加载一个图片经历那些过程](https://www.jianshu.com/p/72dd074728d8) + + +### 网络 + +* 1、[http1.0->1.1->2.2->3区别](https://www.cnblogs.com/riwang/p/12370785.html) +* 2、[HTTP1.1身份认证-摘要认证](https://blog.csdn.net/zhongshanxian/article/details/81294829) +* 3、[聊聊DNS劫持](https://www.jianshu.com/p/63a94cb46cd2) +* 4、[如何保障客户端与服务器交互中的数据安全](https://netsecurity.51cto.com/art/202002/610473.htm) + + +### 算法 + + From c4cec31674f3f41075fed531f980bd7992b95dfa Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 9 Nov 2020 00:19:41 +0800 Subject: [PATCH 273/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/Crash/SLCrashViewController.m | 2 +- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 2 +- .../DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 6 ++++-- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 9 +++++++-- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m index 8df2f28e..daee8442 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m @@ -119,7 +119,7 @@ - (void)crashHandlerDidOutputCrashError:(SLCrashError *)crashError { //调试模式时,强制抛出异常,提醒开发者代码有问题 #if DEBUG - @throw crashError.exception; +// @throw crashError.exception; #endif } diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 9a23ee02..8f3240db 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -5,7 +5,7 @@ * 1、[iOS插件化架构探索](https://mp.weixin.qq.com/s/QJ9YHX-Uy6lDIhJe_5wPGw) * 2、[WKWebview秒开实践分享及问题解决方案](https://juejin.im/post/6887161842406260744) * 3、[iOS基础](https://juejin.im/user/4371313963043661/posts) -* 4、 +* 4、[【性能优化】今日头条iOS客户端启动速度优化](https://www.jianshu.com/p/7096478ccbe7) * 5、 * 6、 * 7、 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 3140b470..78e70fc1 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -19,7 +19,7 @@ * 1.4、启动时间优化 -> 合并减少动态库和类、二进制重排/减少缺页中断、load 的方法处理和耗时监听、异步延时加载、业务流程优化、rootViewController的加载 +> 合并减少动态库和类、尽量不要用C++虚函数(创建虚函数表有开销),、二进制重排/减少缺页中断、load 的方法处理和耗时监听、异步延时加载、业务流程优化、rootViewController的加载 * 1.5、编译时间优化 @@ -80,7 +80,9 @@ > [再谈 iOS App Crash 防护](https://mp.weixin.qq.com/s/l5S_g1PBCiwm4KDtqNFb-A) > [iOS 网络优化: 使你的 App 网络交互更流畅](https://mp.weixin.qq.com/s/YLvpYBwaz8L6fnmzL78Mfg) > [GoldHouse-for-iOS](https://github.com/BiBoyang/GoldHouse-for-iOS) -> [卡顿率降低50%!京东商城APP卡顿监控及优化实践](https://mp.weixin.qq.com/s/aJeAUAjcKOMvznDMGj2UUA) +> [卡顿率降低50%!京东商城APP卡顿监控及优化实践](https://mp.weixin.qq.com/s/aJeAUAjcKOMvznDMGj2UUA) +> [【性能优化】今日头条iOS客户端启动速度优化](https://www.jianshu.com/p/7096478ccbe7) + ## 二、数据结构与算法 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 2db9598c..a7987fd8 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -20,7 +20,10 @@ * 13、[内存满了之后如何处理](https://juejin.im/post/6844903550187733000) * 14、[如何使用 Runtime 给现有的类添加 weak 属性](https://github.com/ChenYilong/iOSInterviewQuestions) * 15、[加载一个图片经历那些过程](https://www.jianshu.com/p/72dd074728d8) - +* 16、[Performselector方法里到底干了啥](https://www.jianshu.com/p/ac14e03d9345) +* 17、[C++虚函数我们一般哪里有用到啊,还有它开销了什么东西?为啥减少使用能优化启动速度?](https://www.dazhuanlan.com/2019/12/09/5dedcdb02c287/) +* 18、[内存缓存优化](https://www.jianshu.com/p/f7376a321c2e) +* 19、[autoreleasepool什么时候释放](https://www.jianshu.com/p/50bdd8438857) ### 网络 @@ -32,4 +35,6 @@ ### 算法 - +* 1、[最大子序和](https://leetcode-cn.com/problems/maximum-subarray/) +* 2、[最大子矩阵](https://leetcode-cn.com/problems/max-submatrix-lcci/) +* 3、[乘积最大子数组](https://leetcode-cn.com/problems/maximum-product-subarray/) From 372b04bcd2f8d6e8107856ab39670e4e5dc373f5 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 9 Nov 2020 18:21:43 +0800 Subject: [PATCH 274/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\345\267\262\346\265\217\350\247\210.md" | 4 ++-- .../\351\235\242\350\257\225\351\242\230.md" | 16 +++++++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 8f3240db..46ac9a4b 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -6,8 +6,8 @@ * 2、[WKWebview秒开实践分享及问题解决方案](https://juejin.im/post/6887161842406260744) * 3、[iOS基础](https://juejin.im/user/4371313963043661/posts) * 4、[【性能优化】今日头条iOS客户端启动速度优化](https://www.jianshu.com/p/7096478ccbe7) -* 5、 -* 6、 +* 5、 [iOS为什么必须在主线程操作UI?](https://juejin.im/post/6844903763011076110) +* 6、[iOS Rendering 渲染全解析(长文干货)](https://juejin.im/post/6844904162765832206#heading-18) * 7、 * 8、 * 9、 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index a7987fd8..91a9a629 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -5,7 +5,7 @@ ### iOS -* 1、 [为什么iOS更新UI操作必须在主线程?](https://778477.github.io/2017/06/19/2017-06-19-为什么iOS更新UI操作必须在主线程/) +* 1、 [iOS为什么必须在主线程操作UI?](https://778477.github.io/2017/06/19/2017-06-19-为什么iOS更新UI操作必须在主线程/) * 2、[Swift和OC的方法调用流程区别]() * 3、[iOS性能优化实践:头条抖音如何实现OOM崩溃率下降50%+](https://mp.weixin.qq.com/s/4-4M9E8NziAgshlwB7Sc6g) * 4、[GCD](https://looseyi.github.io/post/notes/01-gcd/) @@ -24,6 +24,15 @@ * 17、[C++虚函数我们一般哪里有用到啊,还有它开销了什么东西?为啥减少使用能优化启动速度?](https://www.dazhuanlan.com/2019/12/09/5dedcdb02c287/) * 18、[内存缓存优化](https://www.jianshu.com/p/f7376a321c2e) * 19、[autoreleasepool什么时候释放](https://www.jianshu.com/p/50bdd8438857) +* 20、[响应链机制]() +* 21、[instrment的Time profilter实现原理原理]() +* 22、[多线程之栅栏函数](https://zhuanlan.zhihu.com/p/142368783) +* 23、[iOS 图像渲染过程、离屏渲染](https://juejin.im/post/6844904162765832206#heading-18) + + + + + ### 网络 @@ -33,6 +42,11 @@ * 4、[如何保障客户端与服务器交互中的数据安全](https://netsecurity.51cto.com/art/202002/610473.htm) + + + + + ### 算法 * 1、[最大子序和](https://leetcode-cn.com/problems/maximum-subarray/) From 7f7b4ae5b3240be13642a804bb0ecbf15077902f Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 10 Nov 2020 00:38:45 +0800 Subject: [PATCH 275/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\345\267\262\346\265\217\350\247\210.md" | 8 ++++---- .../\351\235\242\350\257\225\351\242\230.md" | 15 +++++++++------ ...12\200\346\234\257\345\215\232\345\256\242.md" | 1 + 3 files changed, 14 insertions(+), 10 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 46ac9a4b..36fb715b 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -8,7 +8,7 @@ * 4、[【性能优化】今日头条iOS客户端启动速度优化](https://www.jianshu.com/p/7096478ccbe7) * 5、 [iOS为什么必须在主线程操作UI?](https://juejin.im/post/6844903763011076110) * 6、[iOS Rendering 渲染全解析(长文干货)](https://juejin.im/post/6844904162765832206#heading-18) -* 7、 -* 8、 -* 9、 -* 10、 +* 7、[iOS面试指南(2020年6月)参考答案](https://mp.weixin.qq.com/s/n8d0WSQs0n0SlmxqdUU-jg) +* 8、[关于iOS离屏渲染的深入研究](https://zhuanlan.zhihu.com/p/72653360) +* 9、[如何通过静态分析提高iOS代码质量](https://juejin.im/post/6844904164552605709#heading-10) +* 10、[OC项目转Swift指南](https://juejin.im/post/6844904078166720520) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 91a9a629..00d7c63f 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -6,7 +6,7 @@ ### iOS * 1、 [iOS为什么必须在主线程操作UI?](https://778477.github.io/2017/06/19/2017-06-19-为什么iOS更新UI操作必须在主线程/) -* 2、[Swift和OC的方法调用流程区别]() +* 2、[Swift和OC的方法调用流程区别](https://kemchenj.github.io/2017-01-09/) * 3、[iOS性能优化实践:头条抖音如何实现OOM崩溃率下降50%+](https://mp.weixin.qq.com/s/4-4M9E8NziAgshlwB7Sc6g) * 4、[GCD](https://looseyi.github.io/post/notes/01-gcd/) * 5、[runloop](https://blog.ibireme.com/2015/05/18/runloop/) @@ -28,6 +28,10 @@ * 21、[instrment的Time profilter实现原理原理]() * 22、[多线程之栅栏函数](https://zhuanlan.zhihu.com/p/142368783) * 23、[iOS 图像渲染过程、离屏渲染](https://juejin.im/post/6844904162765832206#heading-18) +* 24、[iOS 架构模式--浅析MVC, MVP, MVVM 和 VIPER]() +* 25、[iOS面试备战-多线程](https://juejin.im/post/6854573211011514382) +* 26、[设计模式]() +* 26、[组件化]() @@ -40,11 +44,7 @@ * 2、[HTTP1.1身份认证-摘要认证](https://blog.csdn.net/zhongshanxian/article/details/81294829) * 3、[聊聊DNS劫持](https://www.jianshu.com/p/63a94cb46cd2) * 4、[如何保障客户端与服务器交互中的数据安全](https://netsecurity.51cto.com/art/202002/610473.htm) - - - - - +* 5、[iOS面试备战-网络篇](https://juejin.im/post/6844904202523639822#comment) ### 算法 @@ -52,3 +52,6 @@ * 1、[最大子序和](https://leetcode-cn.com/problems/maximum-subarray/) * 2、[最大子矩阵](https://leetcode-cn.com/problems/max-submatrix-lcci/) * 3、[乘积最大子数组](https://leetcode-cn.com/problems/maximum-product-subarray/) +* 4、[爬楼梯]() +* 5、[快速排序]() +* 6、[整数反转]() diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index d76570c3..48802b3b 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -72,6 +72,7 @@ * 70、[iOSer逆向](https://iosre.com) * 71、[GoldHouse-for-iOS](https://github.com/BiBoyang/GoldHouse-for-iOS) * 72、[折腾范儿の味精](http://awhisper.github.io) +* 73、[zhangferry](https://juejin.im/user/2242659450368119) ## 高质量微信公众号 From ff1e1e753ef4afc925d538f159d5be1fa2242ada Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 10 Nov 2020 00:39:04 +0800 Subject: [PATCH 276/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 00d7c63f..30429f41 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -31,7 +31,7 @@ * 24、[iOS 架构模式--浅析MVC, MVP, MVVM 和 VIPER]() * 25、[iOS面试备战-多线程](https://juejin.im/post/6854573211011514382) * 26、[设计模式]() -* 26、[组件化]() +* 27、[组件化]() From 16fed96bfde0b04846ee363c86cdc2d2a4302eaa Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 3 Nov 2020 14:45:04 +0800 Subject: [PATCH 277/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 4 +++- ...07\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index b6b8e73f..fd9ef70b 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -78,7 +78,9 @@ > [抖音品质建设 - iOS启动优化《原理篇》](https://mp.weixin.qq.com/s/3-Sbqe9gxdV6eI1f435BDg) > [iOS Rendering 渲染全解析(长文干货)](https://juejin.im/post/6844904162765832206) > [再谈 iOS App Crash 防护](https://mp.weixin.qq.com/s/l5S_g1PBCiwm4KDtqNFb-A) -> [iOS 网络优化: 使你的 App 网络交互更流畅](https://mp.weixin.qq.com/s/YLvpYBwaz8L6fnmzL78Mfg) +> [iOS 网络优化: 使你的 App 网络交互更流畅](https://mp.weixin.qq.com/s/YLvpYBwaz8L6fnmzL78Mfg) +> [GoldHouse-for-iOS](https://github.com/BiBoyang/GoldHouse-for-iOS) + ## 二、数据结构与算法 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index eb57b37c..a989b897 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -70,6 +70,7 @@ * 68、[iOS一叶](https://juejin.im/user/1899557248829438) * 69、[土土Edmond木](https://looseyi.github.io) * 70、[iOSer逆向](https://iosre.com) +* 71、[GoldHouse-for-iOS](https://github.com/BiBoyang/GoldHouse-for-iOS) ## 高质量微信公众号 From fe53b8c0a4a1086d13bb57dfdc7d5e876c404c6b Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 5 Nov 2020 20:40:50 +0800 Subject: [PATCH 278/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 10 +- iOS_Tips/DarkMode/.DS_Store | Bin 14340 -> 14340 bytes iOS_Tips/DarkMode/General/Tool/HMLog.h | 236 ++++++++++++++++++ .../\345\267\262\346\265\217\350\247\210.md" | 14 ++ .../\351\235\242\350\257\225\351\242\230.md" | 10 +- ...00\346\234\257\345\215\232\345\256\242.md" | 6 +- 6 files changed, 268 insertions(+), 8 deletions(-) create mode 100644 iOS_Tips/DarkMode/General/Tool/HMLog.h create mode 100644 "iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" diff --git a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj index d7fe7eb0..a1cccdf1 100644 --- a/iOS_Tips/DarkMode.xcodeproj/project.pbxproj +++ b/iOS_Tips/DarkMode.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 2CC813682553CE88009DAC9B /* 已浏览.md in Resources */ = {isa = PBXBuildFile; fileRef = 2CC813672553CE88009DAC9B /* 已浏览.md */; }; 2CEBE85D24A6E65600BA21F3 /* SLTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = 2CEBE85B24A6E65600BA21F3 /* SLTimer.m */; }; 780F5303236D8462000D0EA8 /* SLGridView.m in Sources */ = {isa = PBXBuildFile; fileRef = 780F5302236D8462000D0EA8 /* SLGridView.m */; }; 780F5306236D8570000D0EA8 /* SLImageClipController.m in Sources */ = {isa = PBXBuildFile; fileRef = 780F5305236D8570000D0EA8 /* SLImageClipController.m */; }; @@ -213,6 +214,8 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 2CC813672553CE88009DAC9B /* 已浏览.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = "已浏览.md"; sourceTree = ""; }; + 2CC8137925540CB8009DAC9B /* HMLog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HMLog.h; sourceTree = ""; }; 2CEBE85B24A6E65600BA21F3 /* SLTimer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLTimer.m; sourceTree = ""; }; 2CEBE85C24A6E65600BA21F3 /* SLTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLTimer.h; sourceTree = ""; }; 780F5301236D845B000D0EA8 /* SLGridView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SLGridView.h; sourceTree = ""; }; @@ -846,6 +849,7 @@ isa = PBXGroup; children = ( 78AA10F42371A7B50044A6F8 /* PrefixHeader.pch */, + 2CC8137925540CB8009DAC9B /* HMLog.h */, 78F4E41224E5404A000B2ADE /* SLToolMacro.h */, 78777CE4238FF65C006FA671 /* SLDelayPerform.h */, 78777CE5238FF65C006FA671 /* SLDelayPerform.m */, @@ -938,6 +942,7 @@ 784C4C6F24C5B5DD00D5C199 /* 高质量技术博客.md */, 784C4C6D24C5B4F500D5C199 /* 笔记.md */, 785D06632522C32700F174BA /* 面试题.md */, + 2CC813672553CE88009DAC9B /* 已浏览.md */, 7884247D2492102900C2E505 /* SLWorkIssuesViewController.h */, 7884247E2492102900C2E505 /* SLWorkIssuesViewController.m */, 78908DC024FFBD83004164C2 /* ScrollView嵌套 */, @@ -1427,6 +1432,7 @@ 7811F77124B2C818000AA044 /* wsl.order in Resources */, 78E72D59247BA29600751373 /* WebTableView.html in Resources */, 782CFB7A239E6A11001B5528 /* Glitch.vsh in Resources */, + 2CC813682553CE88009DAC9B /* 已浏览.md in Resources */, 782CFB5A239E6227001B5528 /* Gray.fsh in Resources */, 782CFB66239E6651001B5528 /* HexagonMosaic.fsh in Resources */, 782CFB79239E6A11001B5528 /* Glitch.fsh in Resources */, @@ -1814,7 +1820,7 @@ NEW_SETTING = ""; ORDER_FILE = "$(SRCROOT)/DarkMode/WorkIssues/二进制重排/wsl.order"; OTHER_CFLAGS = "-fsanitize-coverage=func,trace-pc-guard"; - PRODUCT_BUNDLE_IDENTIFIER = com.wsl2ls.tips; + PRODUCT_BUNDLE_IDENTIFIER = com.wsl2ls.iostip; PRODUCT_NAME = SLTips; PROVISIONING_PROFILE_SPECIFIER = ""; TARGETED_DEVICE_FAMILY = "1,2"; @@ -1846,7 +1852,7 @@ NEW_SETTING = ""; ORDER_FILE = "$(SRCROOT)/DarkMode/WorkIssues/二进制重排/wsl.order"; OTHER_CFLAGS = "-fsanitize-coverage=func,trace-pc-guard"; - PRODUCT_BUNDLE_IDENTIFIER = com.wsl2ls.tips; + PRODUCT_BUNDLE_IDENTIFIER = com.wsl2ls.iostip; PRODUCT_NAME = SLTips; PROVISIONING_PROFILE_SPECIFIER = ""; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/iOS_Tips/DarkMode/.DS_Store b/iOS_Tips/DarkMode/.DS_Store index e5fa5b0fb1e5ebf6b6ae4be8472a30e8c86e4bb3..05e7465d5ddd335c7f5ec7003ee1faa1b3eac77a 100644 GIT binary patch delta 23 bcmZoEXerpROOnaJZ1Wz;fBaxt(}NEHa&ZX1 delta 23 bcmZoEXerpROOnaVa`PU^fBaxt(}NEHb1?|f diff --git a/iOS_Tips/DarkMode/General/Tool/HMLog.h b/iOS_Tips/DarkMode/General/Tool/HMLog.h new file mode 100644 index 00000000..ef1bf35f --- /dev/null +++ b/iOS_Tips/DarkMode/General/Tool/HMLog.h @@ -0,0 +1,236 @@ +// The MIT License (MIT) +// +// Copyright (c) 2020 Huimao Chen +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +// GCC_C_LANGUAGE_STANDARD = gnu99 + +#ifndef HMLog_h +#define HMLog_h + +#import + +#pragma mark - Parameters + +// All optional parameters should be defined before import "HMLog.h", or you can modify the source code + +#ifndef HMLogEnable +#define HMLogEnable 1 +#endif // HMLogEnable + +#ifndef HMPrintEnable +#define HMPrintEnable 1 +#endif // HMPrintEnable + +#ifndef HMLogPrefix +#define HMLogPrefix(index, valueString) [NSString stringWithFormat:@"%d: %s = ", index, valueString] +#endif // HMLogPrefix + +#ifndef HMLogHeaderFormatString +#define HMLogHeaderFormatString(FUNC, LINE) \ + [NSString stringWithFormat:@"================ %s [%d] ================\n", FUNC, LINE] +#endif // HMLogHeaderFormatString + +#ifndef HMLogTypeExtension +#define HMLogTypeExtension +#endif // HMLogTypeExtension + +#pragma mark - Core + +// format, private macro +#define _HMLogFormat(VAR) \ + , HMStringify(VAR), @encode(__typeof__(VAR)), (VAR) + +// HMFormatString +#define HMFormatString(...) \ + HMExpand(_HMFormatString(__func__, __LINE__, HMArgCount(__VA_ARGS__) HMForeach(_HMLogFormat, __VA_ARGS__))) + +// HMLog +#if HMLogEnable + #define HMLog(...) \ + _HMLog(HMFormatString(__VA_ARGS__)) +#else + #define HMLog(...) +#endif // HMLogEnable + +// HMPrint +#if HMPrintEnable + #define HMPrint(...) \ + _HMPrint(HMFormatString(__VA_ARGS__)) +#else + #define HMPrint(...) +#endif // HMPrintEnable + + +static inline NSString * _HMFormatString(const char *func, int line, int count, ...) { // func, line, count, [valueString, TypeEncode, value] + NSMutableString *result = [[NSMutableString alloc] init]; + + // handle header + [result appendString:HMLogHeaderFormatString(func, line)]; + + // handle arguments + va_list v; + va_start(v, count); + for (int i = 0; i < count; ++i) { + char *valueString = va_arg(v, char *); + char *type = va_arg(v, char *); + + id obj = nil; + if (strcmp(type, @encode(id)) == 0) { // "@" id + id actual = va_arg(v, id); + obj = actual; + + } else if (strcmp(type, @encode(CGPoint)) == 0) { // "{CGPoint=dd}" CGPoint + CGPoint actual = (CGPoint)va_arg(v, CGPoint); + obj = [NSValue value:&actual withObjCType:type]; + + } else if (strcmp(type, @encode(CGSize)) == 0) { // "{CGSize=dd}" CGSize + CGSize actual = (CGSize)va_arg(v, CGSize); + obj = [NSValue value:&actual withObjCType:type]; + + } else if (strcmp(type, @encode(CGRect)) == 0) { // "{CGRect={CGPoint=dd}{CGSize=dd}}" CGRect + CGRect actual = (CGRect)va_arg(v, CGRect); + obj = [NSValue value:&actual withObjCType:type]; + + } else if (strcmp(type, @encode(UIEdgeInsets)) == 0) { // "{UIEdgeInsets=dddd}" UIEdgeInsets + UIEdgeInsets actual = (UIEdgeInsets)va_arg(v, UIEdgeInsets); + obj = NSStringFromUIEdgeInsets(actual); + + } else if (strcmp(type, @encode(NSRange)) == 0) { // "{_NSRange=QQ}" NSRange + NSRange actual = (NSRange)va_arg(v, NSRange); + obj = NSStringFromRange(actual); + + } else if (strcmp(type, @encode(SEL)) == 0) { // ":" SEL + SEL actual = (SEL)va_arg(v, SEL); + obj = [NSString stringWithFormat:@"SEL: %@", NSStringFromSelector(actual)]; + + } else if (strcmp(type, @encode(Class)) == 0) { // "#" Class + Class actual = (Class)va_arg(v, Class); + obj = NSStringFromClass(actual); + + } else if (strcmp(type, @encode(char *)) == 0) { // "*" char * + char * actual = (char *)va_arg(v, char *); + obj = [NSString stringWithFormat:@"%s", actual]; + + } else if (strcmp(type, @encode(double)) == 0) { // "d" double + double actual = (double)va_arg(v, double); + obj = [NSNumber numberWithDouble:actual]; + + } else if (strcmp(type, @encode(float)) == 0) { // "f" float + float actual = (float)va_arg(v, double); + obj = [NSNumber numberWithFloat:actual]; + + } else if (strcmp(type, @encode(int)) == 0) { // "i" int + int actual = (int)va_arg(v, int); + obj = [NSNumber numberWithInt:actual]; + + } else if (strcmp(type, @encode(long)) == 0) { // "q" long + long actual = (long)va_arg(v, long); + obj = [NSNumber numberWithLong:actual]; + + } else if (strcmp(type, @encode(long long)) == 0) { // "q" long long + long long actual = (long long)va_arg(v, long long); + obj = [NSNumber numberWithLongLong:actual]; + + } else if (strcmp(type, @encode(short)) == 0) { // "s" short + short actual = (short)va_arg(v, int); + obj = [NSNumber numberWithShort:actual]; + + } else if (strcmp(type, @encode(char)) == 0) { // "c" char & BOOL(32bit) + char actual = (char)va_arg(v, int); + obj = [NSString stringWithFormat:@"%d char:%c", actual, actual]; + + } else if (strcmp(type, @encode(bool)) == 0) { // "B" bool & BOOL(64bit) + bool actual = (bool)va_arg(v, int); + obj = actual ? @"YES" : @"NO"; + + } else if (strcmp(type, @encode(unsigned char)) == 0) { // "C" unsigned char + unsigned char actual = (unsigned char)va_arg(v, unsigned int); + obj = [NSString stringWithFormat:@"%d unsigned char:%c", actual, actual]; + + } else if (strcmp(type, @encode(unsigned int)) == 0) { // "I" unsigned int + unsigned int actual = (unsigned int)va_arg(v, unsigned int); + obj = [NSNumber numberWithUnsignedInt:actual]; + + } else if (strcmp(type, @encode(unsigned long)) == 0) { // "Q" unsigned long + unsigned long actual = (unsigned long)va_arg(v, unsigned long); + obj = [NSNumber numberWithUnsignedLong:actual]; + + } else if (strcmp(type, @encode(unsigned long long)) == 0) { // "Q" unsigned long long + unsigned long long actual = (unsigned long long)va_arg(v, unsigned long long); + obj = [NSNumber numberWithUnsignedLongLong:actual]; + + } else if (strcmp(type, @encode(unsigned short)) == 0) { // "S" unsigned short + unsigned short actual = (unsigned short)va_arg(v, unsigned int); + obj = [NSNumber numberWithUnsignedShort:actual]; + + } HMLogTypeExtension else { + [result appendString:@"Error: unknown type"]; + break; + } + + [result appendFormat:@"%@%@\n", ((void)(valueString), HMLogPrefix(i, valueString)), obj]; + } + va_end(v); + + return [result copy]; +} + +static inline void _HMLog(NSString *str) { + NSLog(@"\n%@", str); +} + +static inline void _HMPrint(NSString *str) { + printf("%s\n", str.UTF8String); +} + +#pragma mark - Helper + +#define HMStringify(VALUE) _HMStringify(VALUE) +#define _HMStringify(VALUE) # VALUE + +#define HMConcat(A, B) _HMConcat(A, B) +#define _HMConcat(A, B) A ## B + +// Return the number of arguments (up to twenty) provided to the macro. +#define HMArgCount(...) _HMArgCount(A, ##__VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) +#define _HMArgCount(A, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, COUNT, ...) COUNT + +// If the number of arguments is 0, return 0, otherwise return N. +#define HMArgCheck(...) _HMArgCheck(A, ##__VA_ARGS__, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, 0) +#define _HMArgCheck(A, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, OBJ, ...) OBJ + +// Each argument will be passed to the MACRO, the MACRO must be this form: MACRO(arg). Inspired by https://stackoverflow.com/questions/3136686/is-the-c99-preprocessor-turing-complete/10526117#10526117 +#define HMForeach(MACRO, ...) HMConcat(_HMForeach, HMArgCheck(__VA_ARGS__)) (MACRO, ##__VA_ARGS__) +#define _HMForeach() HMForeach +#define _HMForeach0(MACRO) +#define _HMForeachN(MACRO, A, ...) MACRO(A) HMDefer(_HMForeach)() (MACRO, ##__VA_ARGS__) + +#define HMEmpty() +#define HMDefer(ID) ID HMEmpty() + +// For more scans +#define HMExpand(...) _HMExpand1(_HMExpand1(_HMExpand1(__VA_ARGS__))) +#define _HMExpand1(...) _HMExpand2(_HMExpand2(_HMExpand2(__VA_ARGS__))) +#define _HMExpand2(...) _HMExpand3(_HMExpand3(_HMExpand3(__VA_ARGS__))) +#define _HMExpand3(...) __VA_ARGS__ + + +#endif // HMLog_h diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" new file mode 100644 index 00000000..60604f9e --- /dev/null +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -0,0 +1,14 @@ + + +## 已浏览 + +* 1、[iOS插件化架构探索](https://mp.weixin.qq.com/s/QJ9YHX-Uy6lDIhJe_5wPGw) +* 2、 +* 3、 +* 4、 +* 5、 +* 6、 +* 7、 +* 8、 +* 9、 +* 10、 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 2b727d18..d68114d1 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -3,12 +3,12 @@ ## 面试知识点 * 1、 [为什么iOS更新UI操作必须在主线程?](https://778477.github.io/2017/06/19/2017-06-19-为什么iOS更新UI操作必须在主线程/) -* 2、Swift和OC的方法调用流程区别? +* 2、[Swift和OC的方法调用流程区别]() * 3、[iOS性能优化实践:头条抖音如何实现OOM崩溃率下降50%+](https://mp.weixin.qq.com/s/4-4M9E8NziAgshlwB7Sc6g) * 4、[GCD](https://looseyi.github.io/post/notes/01-gcd/) * 5、[runloop](https://blog.ibireme.com/2015/05/18/runloop/) * 6、[Weak的实现原理]() -* 6、[Block() -* 6、[AutoreleasePool]() -* 6、[编译过程]() -* 6、[启动过程]() +* 7、[Block() +* 8、[AutoreleasePool]() +* 9、[编译过程]() +* 10、[启动过程]() diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index a989b897..d76570c3 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -1,5 +1,5 @@ -## 高质量技术博客集合 +## 高质量技术博客 * 1、[WeRead团队博客](https://wereadteam.github.io/) * 2、[美团技术团队](https://tech.meituan.com/) @@ -71,6 +71,8 @@ * 69、[土土Edmond木](https://looseyi.github.io) * 70、[iOSer逆向](https://iosre.com) * 71、[GoldHouse-for-iOS](https://github.com/BiBoyang/GoldHouse-for-iOS) +* 72、[折腾范儿の味精](http://awhisper.github.io) + ## 高质量微信公众号 @@ -93,6 +95,8 @@ * 17、[淘系技术](公众号:AlibabaMTT) * 18、[我是程序员小贱](公众号:Lanj1995Q) * 19、[腾讯技术工程](公众号:Tencent_TEG) +* 20、[搜狐技术产品](公众号:sohu-tech) +* 21、[百度APP技术](公众号:gh_59f5931152fe) ## 书籍 From fd2574748d800c5772d2e48f0dfb91903be6dca4 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 5 Nov 2020 22:42:48 +0800 Subject: [PATCH 279/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index fd9ef70b..90bcf8b9 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -137,6 +137,7 @@ * 5、[js-native 通信的 6 种方式](https://mp.weixin.qq.com/s/_Xo6O3NoE1z9AIMJm_uSsA) * 6、[美团外卖客户端容器化架构的演进](https://mp.weixin.qq.com/s/kW5wu7GM7pMRRvN-dQvE2g) * 7、[SYWebViewBridge](https://mp.weixin.qq.com/s/JDCyWg1AYemxbnFbvY5E9w) +* 8、[JSPatch-实现原理详解](https://github.com/bang590/JSPatch/wiki/JSPatch-实现原理详解) ## 七、Shell脚本 From b1f2b9dd457364a7cb0392b92c8e2a63fec0ea33 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 6 Nov 2020 14:45:36 +0800 Subject: [PATCH 280/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 2 +- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 60604f9e..95b36c35 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -3,7 +3,7 @@ ## 已浏览 * 1、[iOS插件化架构探索](https://mp.weixin.qq.com/s/QJ9YHX-Uy6lDIhJe_5wPGw) -* 2、 +* 2、[WKWebview秒开实践分享及问题解决方案](https://juejin.im/post/6887161842406260744) * 3、 * 4、 * 5、 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 90bcf8b9..623e4b0a 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -138,6 +138,7 @@ * 6、[美团外卖客户端容器化架构的演进](https://mp.weixin.qq.com/s/kW5wu7GM7pMRRvN-dQvE2g) * 7、[SYWebViewBridge](https://mp.weixin.qq.com/s/JDCyWg1AYemxbnFbvY5E9w) * 8、[JSPatch-实现原理详解](https://github.com/bang590/JSPatch/wiki/JSPatch-实现原理详解) +* 9、[WKWebview秒开实践分享及问题解决方案](https://juejin.im/post/6887161842406260744) ## 七、Shell脚本 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index d68114d1..82d20c72 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -12,3 +12,5 @@ * 8、[AutoreleasePool]() * 9、[编译过程]() * 10、[启动过程]() +* 11、[http1.0->1.1->2.2分别升级了什么……](https://www.cnblogs.com/riwang/p/12370785.html) +* 12、[就是这个HTTP1.1这个什么身份认证](https://blog.csdn.net/zhongshanxian/article/details/81294829) From 2b7598355f3ccd1345af0a1a6ebb821f89fa0a4c Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 6 Nov 2020 23:52:01 +0800 Subject: [PATCH 281/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/APM/APMMonitor/SLSystemAppInfo.h | 2 +- .../WorkIssues/APM/APMMonitor/SLSystemAppInfo.m | 2 +- .../\345\267\262\346\265\217\350\247\210.md" | 2 +- .../WorkIssues/\347\254\224\350\256\260.md" | 4 ++-- .../\351\235\242\350\257\225\351\242\230.md" | 15 ++++++++++----- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h index 83334dca..cbb31b7f 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.h @@ -42,7 +42,7 @@ NS_ASSUME_NONNULL_BEGIN + (NSString *)systemName; ///获取用户手机别名 用户定义的名称 通用-关于本机-名称 wsl的iphone + (NSString *)userPhoneName; -///设备唯一标识的字母数字字符串 C5668446-C443-4898-A213-209AECE3626C +///设备唯一标识的字母数字字符串 但如果用户重新安装,那么这个 UUID 就会发生变化。 C5668446-C443-4898-A213-209AECE3626C + (NSString *)uuidString; ///是否是iPhoneX系列/刘海屏 + (BOOL)isIPhoneXSeries; diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m index 2094a5b6..974e58fc 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLSystemAppInfo.m @@ -150,7 +150,7 @@ + (NSString *)userPhoneName { NSString* userPhoneName = [[UIDevice currentDevice] name]; return userPhoneName; } -///设备唯一标识的字母数字字符串 C5668446-C443-4898-A213-209AECE3626C +///设备唯一标识的字母数字字符串,但如果用户重新安装,那么这个 UUID 就会发生变化。 C5668446-C443-4898-A213-209AECE3626C + (NSString *)uuidString { NSString *UUIDString = [[UIDevice currentDevice] identifierForVendor].UUIDString; return UUIDString; diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 95b36c35..9a23ee02 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -4,7 +4,7 @@ * 1、[iOS插件化架构探索](https://mp.weixin.qq.com/s/QJ9YHX-Uy6lDIhJe_5wPGw) * 2、[WKWebview秒开实践分享及问题解决方案](https://juejin.im/post/6887161842406260744) -* 3、 +* 3、[iOS基础](https://juejin.im/user/4371313963043661/posts) * 4、 * 5、 * 6、 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 623e4b0a..8ed9804a 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -79,8 +79,8 @@ > [iOS Rendering 渲染全解析(长文干货)](https://juejin.im/post/6844904162765832206) > [再谈 iOS App Crash 防护](https://mp.weixin.qq.com/s/l5S_g1PBCiwm4KDtqNFb-A) > [iOS 网络优化: 使你的 App 网络交互更流畅](https://mp.weixin.qq.com/s/YLvpYBwaz8L6fnmzL78Mfg) -> [GoldHouse-for-iOS](https://github.com/BiBoyang/GoldHouse-for-iOS) - +> [GoldHouse-for-iOS](https://github.com/BiBoyang/GoldHouse-for-iOS) +> [卡顿率降低50%!京东商城APP卡顿监控及优化实践](https://mp.weixin.qq.com/s/aJeAUAjcKOMvznDMGj2UUA) ## 二、数据结构与算法 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 82d20c72..ad4c8e8e 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -1,6 +1,6 @@ -## 面试知识点 +## 面试题 * 1、 [为什么iOS更新UI操作必须在主线程?](https://778477.github.io/2017/06/19/2017-06-19-为什么iOS更新UI操作必须在主线程/) * 2、[Swift和OC的方法调用流程区别]() @@ -10,7 +10,12 @@ * 6、[Weak的实现原理]() * 7、[Block() * 8、[AutoreleasePool]() -* 9、[编译过程]() -* 10、[启动过程]() -* 11、[http1.0->1.1->2.2分别升级了什么……](https://www.cnblogs.com/riwang/p/12370785.html) -* 12、[就是这个HTTP1.1这个什么身份认证](https://blog.csdn.net/zhongshanxian/article/details/81294829) +* 9、[编译过程](https://juejin.im/post/6844904040841641998) +* 10、[启动过程](https://juejin.im/post/6844904041873408013) +* 11、[http1.0->1.1->2.2->3区别](https://www.cnblogs.com/riwang/p/12370785.html) +* 12、[HTTP1.1身份认证-摘要认证](https://blog.csdn.net/zhongshanxian/article/details/81294829) +* 13、[聊聊DNS劫持](https://www.jianshu.com/p/63a94cb46cd2) +* 14、[如何保障客户端与服务器交互中的数据安全](https://netsecurity.51cto.com/art/202002/610473.htm) +* 15、[设计一个线程池](https://www.jianshu.com/p/5bb4123e415c)、[iOS 任务调度器:为 CPU和内存减负](https://www.jianshu.com/p/f2a610c77d26) +* 16、[线程怎么保活](https://www.jianshu.com/p/2ffa6678f83d) +* 17、[内存满了之后如何处理](https://juejin.im/post/6844903550187733000) From 1c968456b622e5987000b2735df0ac56a123f788 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sun, 8 Nov 2020 16:37:57 +0800 Subject: [PATCH 282/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\347\254\224\350\256\260.md" | 8 +++++- .../\351\235\242\350\257\225\351\242\230.md" | 28 ++++++++++++++----- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 8ed9804a..3140b470 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -105,7 +105,8 @@ * 13、[iOS 基础](https://juejin.im/user/940837683069549/posts) * 14、[深入理解RunLoop](https://blog.ibireme.com/2015/05/18/runloop/) * 15、[BoyangBlog](https://github.com/BiBoyang/BoyangBlog.git) -*16、[阿里、字节:一套高效的iOS面试题](https://juejin.im/post/6844904064937902094) +* 16、[阿里、字节:一套高效的iOS面试题](https://juejin.im/post/6844904064937902094) +* 17、[《招聘一个靠谱的 iOS》](https://github.com/ChenYilong/iOSInterviewQuestions) ## 四、逆向与安全 @@ -169,6 +170,11 @@ * 2、[波儿菜](https://juejin.im/user/2735240659351112) * 3、[写给自己看系列之WebViewJavascriptBridge源码分析](https://juejin.im/post/6844904097192247303) * 4、[JSBridge 实现原理解析](https://github.com/mcuking/blog/issues/39) +* 5、[MLeaksFinder]() +* 6、[JSPatch]() +* 7、[Fishook]() +* 8、[Aspect]() + ## 其它 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index ad4c8e8e..2db9598c 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -2,6 +2,9 @@ ## 面试题 + +### iOS + * 1、 [为什么iOS更新UI操作必须在主线程?](https://778477.github.io/2017/06/19/2017-06-19-为什么iOS更新UI操作必须在主线程/) * 2、[Swift和OC的方法调用流程区别]() * 3、[iOS性能优化实践:头条抖音如何实现OOM崩溃率下降50%+](https://mp.weixin.qq.com/s/4-4M9E8NziAgshlwB7Sc6g) @@ -12,10 +15,21 @@ * 8、[AutoreleasePool]() * 9、[编译过程](https://juejin.im/post/6844904040841641998) * 10、[启动过程](https://juejin.im/post/6844904041873408013) -* 11、[http1.0->1.1->2.2->3区别](https://www.cnblogs.com/riwang/p/12370785.html) -* 12、[HTTP1.1身份认证-摘要认证](https://blog.csdn.net/zhongshanxian/article/details/81294829) -* 13、[聊聊DNS劫持](https://www.jianshu.com/p/63a94cb46cd2) -* 14、[如何保障客户端与服务器交互中的数据安全](https://netsecurity.51cto.com/art/202002/610473.htm) -* 15、[设计一个线程池](https://www.jianshu.com/p/5bb4123e415c)、[iOS 任务调度器:为 CPU和内存减负](https://www.jianshu.com/p/f2a610c77d26) -* 16、[线程怎么保活](https://www.jianshu.com/p/2ffa6678f83d) -* 17、[内存满了之后如何处理](https://juejin.im/post/6844903550187733000) +* 11、[设计一个线程池](https://www.jianshu.com/p/5bb4123e415c)、[iOS 任务调度器:为 CPU和内存减负](https://www.jianshu.com/p/f2a610c77d26) +* 12、[线程怎么保活](https://www.jianshu.com/p/2ffa6678f83d) +* 13、[内存满了之后如何处理](https://juejin.im/post/6844903550187733000) +* 14、[如何使用 Runtime 给现有的类添加 weak 属性](https://github.com/ChenYilong/iOSInterviewQuestions) +* 15、[加载一个图片经历那些过程](https://www.jianshu.com/p/72dd074728d8) + + +### 网络 + +* 1、[http1.0->1.1->2.2->3区别](https://www.cnblogs.com/riwang/p/12370785.html) +* 2、[HTTP1.1身份认证-摘要认证](https://blog.csdn.net/zhongshanxian/article/details/81294829) +* 3、[聊聊DNS劫持](https://www.jianshu.com/p/63a94cb46cd2) +* 4、[如何保障客户端与服务器交互中的数据安全](https://netsecurity.51cto.com/art/202002/610473.htm) + + +### 算法 + + From 9a8b0234746f94fa4ebf47038a83587f7ce60b58 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 9 Nov 2020 00:19:41 +0800 Subject: [PATCH 283/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/Crash/SLCrashViewController.m | 2 +- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 2 +- .../DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 6 ++++-- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 9 +++++++-- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m index 8df2f28e..daee8442 100644 --- a/iOS_Tips/DarkMode/Crash/SLCrashViewController.m +++ b/iOS_Tips/DarkMode/Crash/SLCrashViewController.m @@ -119,7 +119,7 @@ - (void)crashHandlerDidOutputCrashError:(SLCrashError *)crashError { //调试模式时,强制抛出异常,提醒开发者代码有问题 #if DEBUG - @throw crashError.exception; +// @throw crashError.exception; #endif } diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 9a23ee02..8f3240db 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -5,7 +5,7 @@ * 1、[iOS插件化架构探索](https://mp.weixin.qq.com/s/QJ9YHX-Uy6lDIhJe_5wPGw) * 2、[WKWebview秒开实践分享及问题解决方案](https://juejin.im/post/6887161842406260744) * 3、[iOS基础](https://juejin.im/user/4371313963043661/posts) -* 4、 +* 4、[【性能优化】今日头条iOS客户端启动速度优化](https://www.jianshu.com/p/7096478ccbe7) * 5、 * 6、 * 7、 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 3140b470..78e70fc1 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -19,7 +19,7 @@ * 1.4、启动时间优化 -> 合并减少动态库和类、二进制重排/减少缺页中断、load 的方法处理和耗时监听、异步延时加载、业务流程优化、rootViewController的加载 +> 合并减少动态库和类、尽量不要用C++虚函数(创建虚函数表有开销),、二进制重排/减少缺页中断、load 的方法处理和耗时监听、异步延时加载、业务流程优化、rootViewController的加载 * 1.5、编译时间优化 @@ -80,7 +80,9 @@ > [再谈 iOS App Crash 防护](https://mp.weixin.qq.com/s/l5S_g1PBCiwm4KDtqNFb-A) > [iOS 网络优化: 使你的 App 网络交互更流畅](https://mp.weixin.qq.com/s/YLvpYBwaz8L6fnmzL78Mfg) > [GoldHouse-for-iOS](https://github.com/BiBoyang/GoldHouse-for-iOS) -> [卡顿率降低50%!京东商城APP卡顿监控及优化实践](https://mp.weixin.qq.com/s/aJeAUAjcKOMvznDMGj2UUA) +> [卡顿率降低50%!京东商城APP卡顿监控及优化实践](https://mp.weixin.qq.com/s/aJeAUAjcKOMvznDMGj2UUA) +> [【性能优化】今日头条iOS客户端启动速度优化](https://www.jianshu.com/p/7096478ccbe7) + ## 二、数据结构与算法 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 2db9598c..a7987fd8 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -20,7 +20,10 @@ * 13、[内存满了之后如何处理](https://juejin.im/post/6844903550187733000) * 14、[如何使用 Runtime 给现有的类添加 weak 属性](https://github.com/ChenYilong/iOSInterviewQuestions) * 15、[加载一个图片经历那些过程](https://www.jianshu.com/p/72dd074728d8) - +* 16、[Performselector方法里到底干了啥](https://www.jianshu.com/p/ac14e03d9345) +* 17、[C++虚函数我们一般哪里有用到啊,还有它开销了什么东西?为啥减少使用能优化启动速度?](https://www.dazhuanlan.com/2019/12/09/5dedcdb02c287/) +* 18、[内存缓存优化](https://www.jianshu.com/p/f7376a321c2e) +* 19、[autoreleasepool什么时候释放](https://www.jianshu.com/p/50bdd8438857) ### 网络 @@ -32,4 +35,6 @@ ### 算法 - +* 1、[最大子序和](https://leetcode-cn.com/problems/maximum-subarray/) +* 2、[最大子矩阵](https://leetcode-cn.com/problems/max-submatrix-lcci/) +* 3、[乘积最大子数组](https://leetcode-cn.com/problems/maximum-product-subarray/) From e31963adf9205b5f5b61cd355db90daad9518864 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 9 Nov 2020 18:21:43 +0800 Subject: [PATCH 284/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\345\267\262\346\265\217\350\247\210.md" | 4 ++-- .../\351\235\242\350\257\225\351\242\230.md" | 16 +++++++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 8f3240db..46ac9a4b 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -6,8 +6,8 @@ * 2、[WKWebview秒开实践分享及问题解决方案](https://juejin.im/post/6887161842406260744) * 3、[iOS基础](https://juejin.im/user/4371313963043661/posts) * 4、[【性能优化】今日头条iOS客户端启动速度优化](https://www.jianshu.com/p/7096478ccbe7) -* 5、 -* 6、 +* 5、 [iOS为什么必须在主线程操作UI?](https://juejin.im/post/6844903763011076110) +* 6、[iOS Rendering 渲染全解析(长文干货)](https://juejin.im/post/6844904162765832206#heading-18) * 7、 * 8、 * 9、 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index a7987fd8..91a9a629 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -5,7 +5,7 @@ ### iOS -* 1、 [为什么iOS更新UI操作必须在主线程?](https://778477.github.io/2017/06/19/2017-06-19-为什么iOS更新UI操作必须在主线程/) +* 1、 [iOS为什么必须在主线程操作UI?](https://778477.github.io/2017/06/19/2017-06-19-为什么iOS更新UI操作必须在主线程/) * 2、[Swift和OC的方法调用流程区别]() * 3、[iOS性能优化实践:头条抖音如何实现OOM崩溃率下降50%+](https://mp.weixin.qq.com/s/4-4M9E8NziAgshlwB7Sc6g) * 4、[GCD](https://looseyi.github.io/post/notes/01-gcd/) @@ -24,6 +24,15 @@ * 17、[C++虚函数我们一般哪里有用到啊,还有它开销了什么东西?为啥减少使用能优化启动速度?](https://www.dazhuanlan.com/2019/12/09/5dedcdb02c287/) * 18、[内存缓存优化](https://www.jianshu.com/p/f7376a321c2e) * 19、[autoreleasepool什么时候释放](https://www.jianshu.com/p/50bdd8438857) +* 20、[响应链机制]() +* 21、[instrment的Time profilter实现原理原理]() +* 22、[多线程之栅栏函数](https://zhuanlan.zhihu.com/p/142368783) +* 23、[iOS 图像渲染过程、离屏渲染](https://juejin.im/post/6844904162765832206#heading-18) + + + + + ### 网络 @@ -33,6 +42,11 @@ * 4、[如何保障客户端与服务器交互中的数据安全](https://netsecurity.51cto.com/art/202002/610473.htm) + + + + + ### 算法 * 1、[最大子序和](https://leetcode-cn.com/problems/maximum-subarray/) From a64be60de73e9ec8255023974d8b0b89dcc95535 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 10 Nov 2020 00:38:45 +0800 Subject: [PATCH 285/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\345\267\262\346\265\217\350\247\210.md" | 8 ++++---- .../\351\235\242\350\257\225\351\242\230.md" | 15 +++++++++------ ...12\200\346\234\257\345\215\232\345\256\242.md" | 1 + 3 files changed, 14 insertions(+), 10 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 46ac9a4b..36fb715b 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -8,7 +8,7 @@ * 4、[【性能优化】今日头条iOS客户端启动速度优化](https://www.jianshu.com/p/7096478ccbe7) * 5、 [iOS为什么必须在主线程操作UI?](https://juejin.im/post/6844903763011076110) * 6、[iOS Rendering 渲染全解析(长文干货)](https://juejin.im/post/6844904162765832206#heading-18) -* 7、 -* 8、 -* 9、 -* 10、 +* 7、[iOS面试指南(2020年6月)参考答案](https://mp.weixin.qq.com/s/n8d0WSQs0n0SlmxqdUU-jg) +* 8、[关于iOS离屏渲染的深入研究](https://zhuanlan.zhihu.com/p/72653360) +* 9、[如何通过静态分析提高iOS代码质量](https://juejin.im/post/6844904164552605709#heading-10) +* 10、[OC项目转Swift指南](https://juejin.im/post/6844904078166720520) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 91a9a629..00d7c63f 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -6,7 +6,7 @@ ### iOS * 1、 [iOS为什么必须在主线程操作UI?](https://778477.github.io/2017/06/19/2017-06-19-为什么iOS更新UI操作必须在主线程/) -* 2、[Swift和OC的方法调用流程区别]() +* 2、[Swift和OC的方法调用流程区别](https://kemchenj.github.io/2017-01-09/) * 3、[iOS性能优化实践:头条抖音如何实现OOM崩溃率下降50%+](https://mp.weixin.qq.com/s/4-4M9E8NziAgshlwB7Sc6g) * 4、[GCD](https://looseyi.github.io/post/notes/01-gcd/) * 5、[runloop](https://blog.ibireme.com/2015/05/18/runloop/) @@ -28,6 +28,10 @@ * 21、[instrment的Time profilter实现原理原理]() * 22、[多线程之栅栏函数](https://zhuanlan.zhihu.com/p/142368783) * 23、[iOS 图像渲染过程、离屏渲染](https://juejin.im/post/6844904162765832206#heading-18) +* 24、[iOS 架构模式--浅析MVC, MVP, MVVM 和 VIPER]() +* 25、[iOS面试备战-多线程](https://juejin.im/post/6854573211011514382) +* 26、[设计模式]() +* 26、[组件化]() @@ -40,11 +44,7 @@ * 2、[HTTP1.1身份认证-摘要认证](https://blog.csdn.net/zhongshanxian/article/details/81294829) * 3、[聊聊DNS劫持](https://www.jianshu.com/p/63a94cb46cd2) * 4、[如何保障客户端与服务器交互中的数据安全](https://netsecurity.51cto.com/art/202002/610473.htm) - - - - - +* 5、[iOS面试备战-网络篇](https://juejin.im/post/6844904202523639822#comment) ### 算法 @@ -52,3 +52,6 @@ * 1、[最大子序和](https://leetcode-cn.com/problems/maximum-subarray/) * 2、[最大子矩阵](https://leetcode-cn.com/problems/max-submatrix-lcci/) * 3、[乘积最大子数组](https://leetcode-cn.com/problems/maximum-product-subarray/) +* 4、[爬楼梯]() +* 5、[快速排序]() +* 6、[整数反转]() diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index d76570c3..48802b3b 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -72,6 +72,7 @@ * 70、[iOSer逆向](https://iosre.com) * 71、[GoldHouse-for-iOS](https://github.com/BiBoyang/GoldHouse-for-iOS) * 72、[折腾范儿の味精](http://awhisper.github.io) +* 73、[zhangferry](https://juejin.im/user/2242659450368119) ## 高质量微信公众号 From 2fd4648e5300449ffdac556f60fd36f2b794b84e Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 10 Nov 2020 00:39:04 +0800 Subject: [PATCH 286/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 00d7c63f..30429f41 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -31,7 +31,7 @@ * 24、[iOS 架构模式--浅析MVC, MVP, MVVM 和 VIPER]() * 25、[iOS面试备战-多线程](https://juejin.im/post/6854573211011514382) * 26、[设计模式]() -* 26、[组件化]() +* 27、[组件化]() From 556fd58a9c88e14126d4b1870dbc3d51cd6f2542 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 10 Nov 2020 19:00:01 +0800 Subject: [PATCH 287/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 2 ++ .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 36fb715b..7fb81102 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -12,3 +12,5 @@ * 8、[关于iOS离屏渲染的深入研究](https://zhuanlan.zhihu.com/p/72653360) * 9、[如何通过静态分析提高iOS代码质量](https://juejin.im/post/6844904164552605709#heading-10) * 10、[OC项目转Swift指南](https://juejin.im/post/6844904078166720520) +* 11、[iOS蓝牙知识快速入门(详尽版)](https://juejin.im/post/6844903824847536135) +* 12、[译】更好的了解Xcode构建系统](https://juejin.im/post/6844904200887861262) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 30429f41..2c6aefa0 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -28,7 +28,7 @@ * 21、[instrment的Time profilter实现原理原理]() * 22、[多线程之栅栏函数](https://zhuanlan.zhihu.com/p/142368783) * 23、[iOS 图像渲染过程、离屏渲染](https://juejin.im/post/6844904162765832206#heading-18) -* 24、[iOS 架构模式--浅析MVC, MVP, MVVM 和 VIPER]() +* 24、[iOS 架构模式--浅析MVC, MVP, MVVM 和 VIPER](https://zhangferry.com/2019/11/22/ios_architecture_patterns/) * 25、[iOS面试备战-多线程](https://juejin.im/post/6854573211011514382) * 26、[设计模式]() * 27、[组件化]() From 246f047e620ea3573b7666619e3dd8397eaac7d8 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 10 Nov 2020 19:26:18 +0800 Subject: [PATCH 288/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 78e70fc1..3605e9af 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -109,6 +109,7 @@ * 15、[BoyangBlog](https://github.com/BiBoyang/BoyangBlog.git) * 16、[阿里、字节:一套高效的iOS面试题](https://juejin.im/post/6844904064937902094) * 17、[《招聘一个靠谱的 iOS》](https://github.com/ChenYilong/iOSInterviewQuestions) +* 18、[聚焦于iOS开发面试题和开发笔记](https://github.com/DevDragonLi/iOSInterviewsAndDevNotes) ## 四、逆向与安全 From b5f9485231baa77b53507c71ebf9a6706e098514 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 10 Nov 2020 21:02:36 +0800 Subject: [PATCH 289/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 2c6aefa0..3074fa97 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -32,6 +32,7 @@ * 25、[iOS面试备战-多线程](https://juejin.im/post/6854573211011514382) * 26、[设计模式]() * 27、[组件化]() +* 28、[md5实现原理](https://www.jianshu.com/p/82729c87ef68) From c7730435d9266f0f1acec61113855df071a704c0 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 10 Nov 2020 23:56:33 +0800 Subject: [PATCH 290/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 1 + .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 7fb81102..569e6e81 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -14,3 +14,4 @@ * 10、[OC项目转Swift指南](https://juejin.im/post/6844904078166720520) * 11、[iOS蓝牙知识快速入门(详尽版)](https://juejin.im/post/6844903824847536135) * 12、[译】更好的了解Xcode构建系统](https://juejin.im/post/6844904200887861262) +* 13、[iOS组件化方案的几种实现](https://www.jianshu.com/p/2a7e2aa0748b) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 3074fa97..5b1cb5e8 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -31,8 +31,9 @@ * 24、[iOS 架构模式--浅析MVC, MVP, MVVM 和 VIPER](https://zhangferry.com/2019/11/22/ios_architecture_patterns/) * 25、[iOS面试备战-多线程](https://juejin.im/post/6854573211011514382) * 26、[设计模式]() -* 27、[组件化]() -* 28、[md5实现原理](https://www.jianshu.com/p/82729c87ef68) +* 27、[组件化](https://www.jianshu.com/p/40060fa2a564) +* 28、[组件化采坑](https://juejin.im/post/6844903731738345479) +* 29、[md5实现原理](https://www.jianshu.com/p/82729c87ef68) From 460f894b7299f81ea59323a64176f3c729e4237e Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 11 Nov 2020 00:16:36 +0800 Subject: [PATCH 291/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 2 ++ 1 file changed, 2 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 569e6e81..a3c70be8 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -15,3 +15,5 @@ * 11、[iOS蓝牙知识快速入门(详尽版)](https://juejin.im/post/6844903824847536135) * 12、[译】更好的了解Xcode构建系统](https://juejin.im/post/6844904200887861262) * 13、[iOS组件化方案的几种实现](https://www.jianshu.com/p/2a7e2aa0748b) +* 14、[分析MVC, MVP, MVVM 和 VIPER](https://blog.csdn.net/weixin_40200876/article/details/87635190) + From d87b83bae52f5176a6427826febf4b01ba5367cd Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 11 Nov 2020 01:22:23 +0800 Subject: [PATCH 292/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index a3c70be8..2b4515cf 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -16,4 +16,5 @@ * 12、[译】更好的了解Xcode构建系统](https://juejin.im/post/6844904200887861262) * 13、[iOS组件化方案的几种实现](https://www.jianshu.com/p/2a7e2aa0748b) * 14、[分析MVC, MVP, MVVM 和 VIPER](https://blog.csdn.net/weixin_40200876/article/details/87635190) +* 15、[RAC相关](https://www.jianshu.com/p/cd4031fbf8ff) From c22f8244df9349bd5ac1b4a013c5bed3613c6757 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 11 Nov 2020 01:25:22 +0800 Subject: [PATCH 293/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 2b4515cf..601b47d7 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -17,4 +17,4 @@ * 13、[iOS组件化方案的几种实现](https://www.jianshu.com/p/2a7e2aa0748b) * 14、[分析MVC, MVP, MVVM 和 VIPER](https://blog.csdn.net/weixin_40200876/article/details/87635190) * 15、[RAC相关](https://www.jianshu.com/p/cd4031fbf8ff) - +* 16、[synchronized的内部实现原理](https://blog.csdn.net/qq_28551705/article/details/86094764) From 1264b9ecd9adb94b283ccfb64ef1fa47f1f90974 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 11 Nov 2020 01:46:05 +0800 Subject: [PATCH 294/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 601b47d7..315da025 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -17,4 +17,4 @@ * 13、[iOS组件化方案的几种实现](https://www.jianshu.com/p/2a7e2aa0748b) * 14、[分析MVC, MVP, MVVM 和 VIPER](https://blog.csdn.net/weixin_40200876/article/details/87635190) * 15、[RAC相关](https://www.jianshu.com/p/cd4031fbf8ff) -* 16、[synchronized的内部实现原理](https://blog.csdn.net/qq_28551705/article/details/86094764) +* 16、[synchronized的内部实现原理](https://www.jianshu.com/p/d93c5d3f5e7d) From efacdb6080d5e14e53fbe816babcd029f2e02973 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 11 Nov 2020 02:06:53 +0800 Subject: [PATCH 295/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 315da025..82be2968 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -17,4 +17,4 @@ * 13、[iOS组件化方案的几种实现](https://www.jianshu.com/p/2a7e2aa0748b) * 14、[分析MVC, MVP, MVVM 和 VIPER](https://blog.csdn.net/weixin_40200876/article/details/87635190) * 15、[RAC相关](https://www.jianshu.com/p/cd4031fbf8ff) -* 16、[synchronized的内部实现原理](https://www.jianshu.com/p/d93c5d3f5e7d) +* 16、[synchronized的内部实现原理](http://yulingtianxia.com/blog/2015/11/01/More-than-you-want-to-know-about-synchronized/) From 1e9174a1cf4c55ea7bf9280d9783250674285850 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 12 Nov 2020 13:02:59 +0800 Subject: [PATCH 296/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 4 ++++ "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 4 +--- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 82be2968..fe0ecc9d 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -18,3 +18,7 @@ * 14、[分析MVC, MVP, MVVM 和 VIPER](https://blog.csdn.net/weixin_40200876/article/details/87635190) * 15、[RAC相关](https://www.jianshu.com/p/cd4031fbf8ff) * 16、[synchronized的内部实现原理](http://yulingtianxia.com/blog/2015/11/01/More-than-you-want-to-know-about-synchronized/) +* 17、[轻量级低风险 iOS 热更新方案](https://mp.weixin.qq.com/s/2re_s3NmOvE9RXlbGQqGDA) +* 18、[iOS大解密:玄之又玄的KVO](https://mp.weixin.qq.com/s/0Yfb-FYorH5GZ3ZB6bMCUQ) +* 19、[iOS AOP框架Aspects实现原理]() +* 20、[FBRetainCycleDetector不能扫描__block变量的问题分析和解决方案](https://developer.aliyun.com/article/66857) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 3605e9af..c6fd25ac 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -143,6 +143,7 @@ * 7、[SYWebViewBridge](https://mp.weixin.qq.com/s/JDCyWg1AYemxbnFbvY5E9w) * 8、[JSPatch-实现原理详解](https://github.com/bang590/JSPatch/wiki/JSPatch-实现原理详解) * 9、[WKWebview秒开实践分享及问题解决方案](https://juejin.im/post/6887161842406260744) +*10、[轻量级低风险 iOS 热更新方案](https://mp.weixin.qq.com/s/2re_s3NmOvE9RXlbGQqGDA) ## 七、Shell脚本 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 5b1cb5e8..7b89cd55 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -30,7 +30,7 @@ * 23、[iOS 图像渲染过程、离屏渲染](https://juejin.im/post/6844904162765832206#heading-18) * 24、[iOS 架构模式--浅析MVC, MVP, MVVM 和 VIPER](https://zhangferry.com/2019/11/22/ios_architecture_patterns/) * 25、[iOS面试备战-多线程](https://juejin.im/post/6854573211011514382) -* 26、[设计模式]() +* 26、[设计模式](https://www.jianshu.com/p/e5c69c7b8c00) * 27、[组件化](https://www.jianshu.com/p/40060fa2a564) * 28、[组件化采坑](https://juejin.im/post/6844903731738345479) * 29、[md5实现原理](https://www.jianshu.com/p/82729c87ef68) @@ -38,8 +38,6 @@ - - ### 网络 * 1、[http1.0->1.1->2.2->3区别](https://www.cnblogs.com/riwang/p/12370785.html) From 2d8a099d2026c7bef4457b3c67f30fe1ce432f89 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 13 Nov 2020 00:57:34 +0800 Subject: [PATCH 297/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 2 ++ .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 1 + 2 files changed, 3 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index fe0ecc9d..0a50471e 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -22,3 +22,5 @@ * 18、[iOS大解密:玄之又玄的KVO](https://mp.weixin.qq.com/s/0Yfb-FYorH5GZ3ZB6bMCUQ) * 19、[iOS AOP框架Aspects实现原理]() * 20、[FBRetainCycleDetector不能扫描__block变量的问题分析和解决方案](https://developer.aliyun.com/article/66857) +* 21、[iOS 任务调度器:为 CPU 和内存减负](https://www.jianshu.com/p/f2a610c77d26) +* 22、[iOS学习之深入理解程序编译过程](https://juejin.im/post/6844903535050489869) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 7b89cd55..0f2ce472 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -34,6 +34,7 @@ * 27、[组件化](https://www.jianshu.com/p/40060fa2a564) * 28、[组件化采坑](https://juejin.im/post/6844903731738345479) * 29、[md5实现原理](https://www.jianshu.com/p/82729c87ef68) +* 30、[]() From 72fad6ea42935ebfc654c9e3ad188a1ec0a3acd8 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 13 Nov 2020 01:10:08 +0800 Subject: [PATCH 298/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 2 ++ 1 file changed, 2 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 0f2ce472..28ac5cb0 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -56,3 +56,5 @@ * 4、[爬楼梯]() * 5、[快速排序]() * 6、[整数反转]() +* 7、[链表反转]() +* 8、[链表是否循环]() From 3531da10fca78d343b32015f0ae8a3a4f7a7c55e Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 13 Nov 2020 01:21:01 +0800 Subject: [PATCH 299/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 28ac5cb0..73eb9c34 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -34,7 +34,8 @@ * 27、[组件化](https://www.jianshu.com/p/40060fa2a564) * 28、[组件化采坑](https://juejin.im/post/6844903731738345479) * 29、[md5实现原理](https://www.jianshu.com/p/82729c87ef68) -* 30、[]() +* 30、[NSTimer不准时]() +* 31、[WKWebVie与JS通信的几种方式]() From 537eccc89376a2f37979b8ac2d197b3a4eca1f8c Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sat, 14 Nov 2020 15:49:38 +0800 Subject: [PATCH 300/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\345\267\262\346\265\217\350\247\210.md" | 2 +- .../\351\235\242\350\257\225\351\242\230.md" | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 0a50471e..4052a2df 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -20,7 +20,7 @@ * 16、[synchronized的内部实现原理](http://yulingtianxia.com/blog/2015/11/01/More-than-you-want-to-know-about-synchronized/) * 17、[轻量级低风险 iOS 热更新方案](https://mp.weixin.qq.com/s/2re_s3NmOvE9RXlbGQqGDA) * 18、[iOS大解密:玄之又玄的KVO](https://mp.weixin.qq.com/s/0Yfb-FYorH5GZ3ZB6bMCUQ) -* 19、[iOS AOP框架Aspects实现原理]() +* 19、[iOS AOP框架Aspects实现原理](https://www.jianshu.com/p/2345cc034d6b) * 20、[FBRetainCycleDetector不能扫描__block变量的问题分析和解决方案](https://developer.aliyun.com/article/66857) * 21、[iOS 任务调度器:为 CPU 和内存减负](https://www.jianshu.com/p/f2a610c77d26) * 22、[iOS学习之深入理解程序编译过程](https://juejin.im/post/6844903535050489869) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 73eb9c34..1c00ab87 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -14,7 +14,7 @@ * 7、[Block() * 8、[AutoreleasePool]() * 9、[编译过程](https://juejin.im/post/6844904040841641998) -* 10、[启动过程](https://juejin.im/post/6844904041873408013) +* 10、[启动过程](https://www.jianshu.com/p/7096478ccbe7) * 11、[设计一个线程池](https://www.jianshu.com/p/5bb4123e415c)、[iOS 任务调度器:为 CPU和内存减负](https://www.jianshu.com/p/f2a610c77d26) * 12、[线程怎么保活](https://www.jianshu.com/p/2ffa6678f83d) * 13、[内存满了之后如何处理](https://juejin.im/post/6844903550187733000) @@ -36,8 +36,16 @@ * 29、[md5实现原理](https://www.jianshu.com/p/82729c87ef68) * 30、[NSTimer不准时]() * 31、[WKWebVie与JS通信的几种方式]() - - +* 32、[什么是泛型?Swift的字符串string与OC的NSString差别?对于Swift协议的理解?]() +* 33、[APP启动时长监控]() +* 34、[https相关]() +* 35、[设计一个网络框架]() +* 36、[网络最大并发数]() +* 37、[分类和扩展区别]() +* 38、[load和initializet]() +* 39、[view渲染过程]() +* 40、[layoutSubviews什么时候执行](https://www.jianshu.com/p/a2acc4c7dc4b) +* 41、[iOS-UIView异步绘制](https://www.jianshu.com/p/1c1b3f7cf087) ### 网络 From ec55a2f83a56e2e7a51ed14d7ebbf86b52f6677d Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sun, 15 Nov 2020 01:00:42 +0800 Subject: [PATCH 301/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 2 ++ .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 4052a2df..3ae626db 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -24,3 +24,5 @@ * 20、[FBRetainCycleDetector不能扫描__block变量的问题分析和解决方案](https://developer.aliyun.com/article/66857) * 21、[iOS 任务调度器:为 CPU 和内存减负](https://www.jianshu.com/p/f2a610c77d26) * 22、[iOS学习之深入理解程序编译过程](https://juejin.im/post/6844903535050489869) +* 23、[计算机那些事(8)——图形图像渲染原理](http://chuquan.me/2018/08/26/graphics-rending-principle-gpu/) +* 24、[iOS 图像渲染过程解析iOS 图像渲染过程解析](https://www.jianshu.com/p/6b9a5f16644b) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 1c00ab87..fc4d238a 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -43,9 +43,11 @@ * 36、[网络最大并发数]() * 37、[分类和扩展区别]() * 38、[load和initializet]() -* 39、[view渲染过程]() +* 39、[UIView的绘制过程](https://www.jianshu.com/p/a81d48e0e44a) * 40、[layoutSubviews什么时候执行](https://www.jianshu.com/p/a2acc4c7dc4b) * 41、[iOS-UIView异步绘制](https://www.jianshu.com/p/1c1b3f7cf087) +* 42、[静态库和动态库的区别?怎么判断一个库是动态库还是静态库]() +* 43、[AutoLayout的原理]() ### 网络 From c53314fbb28e22d3a5494fada1033a9a92e6425d Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sun, 15 Nov 2020 01:01:04 +0800 Subject: [PATCH 302/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 3ae626db..c5b0b812 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -25,4 +25,4 @@ * 21、[iOS 任务调度器:为 CPU 和内存减负](https://www.jianshu.com/p/f2a610c77d26) * 22、[iOS学习之深入理解程序编译过程](https://juejin.im/post/6844903535050489869) * 23、[计算机那些事(8)——图形图像渲染原理](http://chuquan.me/2018/08/26/graphics-rending-principle-gpu/) -* 24、[iOS 图像渲染过程解析iOS 图像渲染过程解析](https://www.jianshu.com/p/6b9a5f16644b) +* 24、[iOS 图像渲染过程解析](https://www.jianshu.com/p/6b9a5f16644b) From 24b7f2020ea20853b800f976e6a2decf4d2c54d9 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sun, 15 Nov 2020 01:06:54 +0800 Subject: [PATCH 303/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index fc4d238a..5c8cafd0 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -34,7 +34,7 @@ * 27、[组件化](https://www.jianshu.com/p/40060fa2a564) * 28、[组件化采坑](https://juejin.im/post/6844903731738345479) * 29、[md5实现原理](https://www.jianshu.com/p/82729c87ef68) -* 30、[NSTimer不准时]() +* 30、[NSTimer不准时](https://www.jianshu.com/p/d5845842b7d3) * 31、[WKWebVie与JS通信的几种方式]() * 32、[什么是泛型?Swift的字符串string与OC的NSString差别?对于Swift协议的理解?]() * 33、[APP启动时长监控]() From da23a376fe64cac3b98a536e19ab394e78d5d02b Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sun, 15 Nov 2020 23:08:18 +0800 Subject: [PATCH 304/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\345\267\262\346\265\217\350\247\210.md" | 1 + .../\351\235\242\350\257\225\351\242\230.md" | 11 +++++++---- iOS_Tips/Podfile | 1 + 3 files changed, 9 insertions(+), 4 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index c5b0b812..f0a5917d 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -26,3 +26,4 @@ * 22、[iOS学习之深入理解程序编译过程](https://juejin.im/post/6844903535050489869) * 23、[计算机那些事(8)——图形图像渲染原理](http://chuquan.me/2018/08/26/graphics-rending-principle-gpu/) * 24、[iOS 图像渲染过程解析](https://www.jianshu.com/p/6b9a5f16644b) +* 25、[iOS面试题-Swift篇](https://blog.csdn.net/olsQ93038o99S/article/details/107031322?utm_medium=distribute.pc_relevant.none-task-blog-title-6&spm=1001.2101.3001.4242) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 5c8cafd0..df46e301 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -41,13 +41,14 @@ * 34、[https相关]() * 35、[设计一个网络框架]() * 36、[网络最大并发数]() -* 37、[分类和扩展区别]() -* 38、[load和initializet]() +* 37、[分类和扩展区别](https://www.jianshu.com/p/ba35a975af9a) +* 38、[load和initializet](https://www.jianshu.com/p/c52d0b6ee5e9) * 39、[UIView的绘制过程](https://www.jianshu.com/p/a81d48e0e44a) * 40、[layoutSubviews什么时候执行](https://www.jianshu.com/p/a2acc4c7dc4b) * 41、[iOS-UIView异步绘制](https://www.jianshu.com/p/1c1b3f7cf087) -* 42、[静态库和动态库的区别?怎么判断一个库是动态库还是静态库]() -* 43、[AutoLayout的原理]() +* 42、[静态库和动态库的区别?怎么判断一个库是动态库还是静态库](https://www.jianshu.com/p/5069778e421a) +* 43、[AutoLayout的原理](https://www.jianshu.com/p/c6541ff0bdafv) +* 44、[iOS的Category添加 weak 属性](https://blog.csdn.net/devday/article/details/71130115) ### 网络 @@ -57,6 +58,8 @@ * 3、[聊聊DNS劫持](https://www.jianshu.com/p/63a94cb46cd2) * 4、[如何保障客户端与服务器交互中的数据安全](https://netsecurity.51cto.com/art/202002/610473.htm) * 5、[iOS面试备战-网络篇](https://juejin.im/post/6844904202523639822#comment) +* 5、[在浏览器输入url后发生了什么](https://www.jianshu.com/p/7eea6fbc5fcd) +* 6、[TCP三次握手、四次挥手、https加密原理]() ### 算法 diff --git a/iOS_Tips/Podfile b/iOS_Tips/Podfile index 8d5c5100..75bcda8a 100644 --- a/iOS_Tips/Podfile +++ b/iOS_Tips/Podfile @@ -2,6 +2,7 @@ source 'https://github.com/CocoaPods/Specs.git' #source 'https://gitee.com/mirrors/CocoaPods-Specs.git' platform :ios,’10.0’ target "DarkMode" do + pod 'GPUImage' #pod 'MLeaksFinder' pod 'MBProgressHUD' From 9f2a1a2a6d8d5727a16ce6f1bb9e32ad96c8da12 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sun, 15 Nov 2020 23:46:56 +0800 Subject: [PATCH 305/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 2 +- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index c6fd25ac..b74ef9f1 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -27,7 +27,7 @@ * 1.6、网络优化 -> +> 合并多个请求、304缓存 * 1.7、健壮性/稳定性 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index df46e301..498474b7 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -58,8 +58,9 @@ * 3、[聊聊DNS劫持](https://www.jianshu.com/p/63a94cb46cd2) * 4、[如何保障客户端与服务器交互中的数据安全](https://netsecurity.51cto.com/art/202002/610473.htm) * 5、[iOS面试备战-网络篇](https://juejin.im/post/6844904202523639822#comment) -* 5、[在浏览器输入url后发生了什么](https://www.jianshu.com/p/7eea6fbc5fcd) -* 6、[TCP三次握手、四次挥手、https加密原理]() +* 6、[在浏览器输入url后发生了什么](https://www.jianshu.com/p/7eea6fbc5fcd) +* 7、[TCP三次握手、四次挥手、https加密原理]() +* 8、[为什么TCP4次挥手时等待为2MSL?](https://www.zhihu.com/question/67013338) ### 算法 From 1bbaa2689261b32d728f5e867721a9e75587228b Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 16 Nov 2020 23:54:35 +0800 Subject: [PATCH 306/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\351\235\242\350\257\225\351\242\230.md" | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 498474b7..d689435f 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -73,3 +73,13 @@ * 6、[整数反转]() * 7、[链表反转]() * 8、[链表是否循环]() +* 9、[两个有序数组合并]() +* 10、[删除链表的倒数第N个节点](https://leetcode-cn.com/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof/) +* 11、[一个纯数字的字符串,调整顺序使之奇偶排列 “17485” ———>”14785 “]() +* 12、[实现一个LRU算法 不使用数组]() +* 13、[两个view的第一个公共父视图]() +* 14、[两个有序数组的中位数](https://leetcode-cn.com/problems/median-of-two-sorted-arrays/) +* 15、[字符串的全排列](https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof//) +* 16、[二叉树的层级打印 计算层高](https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-lcof/) +* 17、[用字符串实现大数加法]() +* 18、[二叉树 红黑树 二叉树的应用,以及数据库的数据结构以及优化]() From d67774c4f76a56d54e6417cf362f73d1339efe79 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 17 Nov 2020 00:12:17 +0800 Subject: [PATCH 307/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index d689435f..4ddc6df2 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -49,7 +49,8 @@ * 42、[静态库和动态库的区别?怎么判断一个库是动态库还是静态库](https://www.jianshu.com/p/5069778e421a) * 43、[AutoLayout的原理](https://www.jianshu.com/p/c6541ff0bdafv) * 44、[iOS的Category添加 weak 属性](https://blog.csdn.net/devday/article/details/71130115) - +* 45、[runloop]() +* 46、[runtime]() ### 网络 @@ -61,7 +62,7 @@ * 6、[在浏览器输入url后发生了什么](https://www.jianshu.com/p/7eea6fbc5fcd) * 7、[TCP三次握手、四次挥手、https加密原理]() * 8、[为什么TCP4次挥手时等待为2MSL?](https://www.zhihu.com/question/67013338) - +* 9、[DNS的搜索过程]() ### 算法 @@ -83,3 +84,4 @@ * 16、[二叉树的层级打印 计算层高](https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-lcof/) * 17、[用字符串实现大数加法]() * 18、[二叉树 红黑树 二叉树的应用,以及数据库的数据结构以及优化]() +* 19、[找出无序数组中所有3个数字加起来是0 的数字(先排序,再双指针)]() From 24370e20cccd5d869ef4247d4ccfece115441113 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 17 Nov 2020 15:06:05 +0800 Subject: [PATCH 308/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 4ddc6df2..7588af6e 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -49,8 +49,8 @@ * 42、[静态库和动态库的区别?怎么判断一个库是动态库还是静态库](https://www.jianshu.com/p/5069778e421a) * 43、[AutoLayout的原理](https://www.jianshu.com/p/c6541ff0bdafv) * 44、[iOS的Category添加 weak 属性](https://blog.csdn.net/devday/article/details/71130115) -* 45、[runloop]() -* 46、[runtime]() +* 45、[runloop](https://www.jianshu.com/p/fcb271f69038) +* 46、[runtime](https://www.jianshu.com/p/6ebda3cd8052) ### 网络 From 8ec974950bba855d1228876f0d8883ca1df84393 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 19 Nov 2020 12:47:49 +0800 Subject: [PATCH 309/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 2 ++ "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 4 ++-- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 1 + ...07\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index f0a5917d..f6441a45 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -27,3 +27,5 @@ * 23、[计算机那些事(8)——图形图像渲染原理](http://chuquan.me/2018/08/26/graphics-rending-principle-gpu/) * 24、[iOS 图像渲染过程解析](https://www.jianshu.com/p/6b9a5f16644b) * 25、[iOS面试题-Swift篇](https://blog.csdn.net/olsQ93038o99S/article/details/107031322?utm_medium=distribute.pc_relevant.none-task-blog-title-6&spm=1001.2101.3001.4242) +* 26、[解决「HTTPDNS + HTTPS」的证书校验问题](https://kangzubin.com/httpdns-https/) +* 27、[从SIL看Swift函数派发机制](https://mp.weixin.qq.com/s/KvwFyc1X_anTt-DTw86u7Q) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index b74ef9f1..b27751c9 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -81,8 +81,8 @@ > [iOS 网络优化: 使你的 App 网络交互更流畅](https://mp.weixin.qq.com/s/YLvpYBwaz8L6fnmzL78Mfg) > [GoldHouse-for-iOS](https://github.com/BiBoyang/GoldHouse-for-iOS) > [卡顿率降低50%!京东商城APP卡顿监控及优化实践](https://mp.weixin.qq.com/s/aJeAUAjcKOMvznDMGj2UUA) -> [【性能优化】今日头条iOS客户端启动速度优化](https://www.jianshu.com/p/7096478ccbe7) - +> [【性能优化】今日头条iOS客户端启动速度优化](https://www.jianshu.com/p/7096478ccbe7) +> [iOS 崩溃排查入门:总览](https://ai-chan.top/2020/10/02/iOS-crash/) ## 二、数据结构与算法 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 7588af6e..c264b303 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -51,6 +51,7 @@ * 44、[iOS的Category添加 weak 属性](https://blog.csdn.net/devday/article/details/71130115) * 45、[runloop](https://www.jianshu.com/p/fcb271f69038) * 46、[runtime](https://www.jianshu.com/p/6ebda3cd8052) +* 47、[WKWebView 那些坑](https://zhuanlan.zhihu.com/p/24990222) ### 网络 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 48802b3b..f14c1e95 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -73,6 +73,7 @@ * 71、[GoldHouse-for-iOS](https://github.com/BiBoyang/GoldHouse-for-iOS) * 72、[折腾范儿の味精](http://awhisper.github.io) * 73、[zhangferry](https://juejin.im/user/2242659450368119) +* 74、[酷酷的哀殿](https://ai-chan.top/) ## 高质量微信公众号 From 47033e5095f88c5d876c4952eb055015cb83b10a Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 19 Nov 2020 12:55:38 +0800 Subject: [PATCH 310/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index c264b303..c71fd195 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -49,9 +49,11 @@ * 42、[静态库和动态库的区别?怎么判断一个库是动态库还是静态库](https://www.jianshu.com/p/5069778e421a) * 43、[AutoLayout的原理](https://www.jianshu.com/p/c6541ff0bdafv) * 44、[iOS的Category添加 weak 属性](https://blog.csdn.net/devday/article/details/71130115) -* 45、[runloop](https://www.jianshu.com/p/fcb271f69038) -* 46、[runtime](https://www.jianshu.com/p/6ebda3cd8052) +* 45、[Runloop](https://www.jianshu.com/p/fcb271f69038) +* 46、[Runtime](https://www.jianshu.com/p/6ebda3cd8052) * 47、[WKWebView 那些坑](https://zhuanlan.zhihu.com/p/24990222) +* 48、[NSString为用Copy和Strong有什么区别]() +* 49、[isKindOf和isMemberOf的区别,底层实现]() ### 网络 From 757ea4a5d8f0d7285ebf4d0aaf14c05c523f2891 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 19 Nov 2020 14:06:09 +0800 Subject: [PATCH 311/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index c71fd195..9a6d9778 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -53,7 +53,8 @@ * 46、[Runtime](https://www.jianshu.com/p/6ebda3cd8052) * 47、[WKWebView 那些坑](https://zhuanlan.zhihu.com/p/24990222) * 48、[NSString为用Copy和Strong有什么区别]() -* 49、[isKindOf和isMemberOf的区别,底层实现]() +* 49、[isKindOf和isMemberOf的区别,底层实现](https://www.jianshu.com/p/abad3809c7c1) +* 50、[多线程-现有10个上传任务,最大并发数是3,每完成一个任务要告诉用户此时剩余的任务数]() ### 网络 From 34f8a6d2615f1dfca8f1a471ba2362d5552d0c02 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 20 Nov 2020 15:04:51 +0800 Subject: [PATCH 312/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 9a6d9778..7013fb9e 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -89,3 +89,4 @@ * 17、[用字符串实现大数加法]() * 18、[二叉树 红黑树 二叉树的应用,以及数据库的数据结构以及优化]() * 19、[找出无序数组中所有3个数字加起来是0 的数字(先排序,再双指针)]() +* 20、[最长回文子串]() From df48464446a3204e538ce9324c3c353e10397e5d Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sun, 22 Nov 2020 22:49:32 +0800 Subject: [PATCH 313/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\345\267\262\346\265\217\350\247\210.md" | 1 + .../\351\235\242\350\257\225\351\242\230.md" | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index f6441a45..e944a2cd 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -29,3 +29,4 @@ * 25、[iOS面试题-Swift篇](https://blog.csdn.net/olsQ93038o99S/article/details/107031322?utm_medium=distribute.pc_relevant.none-task-blog-title-6&spm=1001.2101.3001.4242) * 26、[解决「HTTPDNS + HTTPS」的证书校验问题](https://kangzubin.com/httpdns-https/) * 27、[从SIL看Swift函数派发机制](https://mp.weixin.qq.com/s/KvwFyc1X_anTt-DTw86u7Q) +* 28、[iOS 锁的简单实现与总结](https://www.jianshu.com/p/a33959324cc7?from=singlemessage) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 7013fb9e..bf9c75d0 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -10,9 +10,9 @@ * 3、[iOS性能优化实践:头条抖音如何实现OOM崩溃率下降50%+](https://mp.weixin.qq.com/s/4-4M9E8NziAgshlwB7Sc6g) * 4、[GCD](https://looseyi.github.io/post/notes/01-gcd/) * 5、[runloop](https://blog.ibireme.com/2015/05/18/runloop/) -* 6、[Weak的实现原理]() -* 7、[Block() -* 8、[AutoreleasePool]() +* 6、[Weak的实现原理](https://www.jianshu.com/p/f331bd5ce8f8) +* 7、[Block](https://www.jianshu.com/p/93813c293266) +* 8、[AutoreleasePool](https://www.jianshu.com/p/8a396da9dd48) * 9、[编译过程](https://juejin.im/post/6844904040841641998) * 10、[启动过程](https://www.jianshu.com/p/7096478ccbe7) * 11、[设计一个线程池](https://www.jianshu.com/p/5bb4123e415c)、[iOS 任务调度器:为 CPU和内存减负](https://www.jianshu.com/p/f2a610c77d26) @@ -55,6 +55,11 @@ * 48、[NSString为用Copy和Strong有什么区别]() * 49、[isKindOf和isMemberOf的区别,底层实现](https://www.jianshu.com/p/abad3809c7c1) * 50、[多线程-现有10个上传任务,最大并发数是3,每完成一个任务要告诉用户此时剩余的任务数]() +* 51、[自己实现isEqual方法(hash算法](https://www.jianshu.com/p/915356e280fc) +* 52、[透彻理解block中weakSelf和strongSelf](https://www.jianshu.com/p/ae4f84e289b9) +* 53、[ios实现读写锁](https://blog.csdn.net/u014600626/article/details/102884794) +* 54、[UIView Animation的Block谁持有](http://saitjr.com/ios/ios-from-memory-leak-to-uiview-animation.html) + ### 网络 @@ -90,3 +95,4 @@ * 18、[二叉树 红黑树 二叉树的应用,以及数据库的数据结构以及优化]() * 19、[找出无序数组中所有3个数字加起来是0 的数字(先排序,再双指针)]() * 20、[最长回文子串]() +* 21、[找出无序数组中所有3个数字加起来是0 的数字]() From 3b72c4cbfbc28568ebbe8da46e613cca062a000c Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 23 Nov 2020 15:17:06 +0800 Subject: [PATCH 314/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\345\267\262\346\265\217\350\247\210.md" | 1 + .../\351\235\242\350\257\225\351\242\230.md" | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index e944a2cd..d099512f 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -30,3 +30,4 @@ * 26、[解决「HTTPDNS + HTTPS」的证书校验问题](https://kangzubin.com/httpdns-https/) * 27、[从SIL看Swift函数派发机制](https://mp.weixin.qq.com/s/KvwFyc1X_anTt-DTw86u7Q) * 28、[iOS 锁的简单实现与总结](https://www.jianshu.com/p/a33959324cc7?from=singlemessage) +* 29、[引用计数带来的一次讨论](https://www.jianshu.com/p/e3690f3e4675) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index bf9c75d0..84345a24 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -12,7 +12,7 @@ * 5、[runloop](https://blog.ibireme.com/2015/05/18/runloop/) * 6、[Weak的实现原理](https://www.jianshu.com/p/f331bd5ce8f8) * 7、[Block](https://www.jianshu.com/p/93813c293266) -* 8、[AutoreleasePool](https://www.jianshu.com/p/8a396da9dd48) +* 8、[AutoreleasePool](https://www.jianshu.com/p/32265cbb2a26) * 9、[编译过程](https://juejin.im/post/6844904040841641998) * 10、[启动过程](https://www.jianshu.com/p/7096478ccbe7) * 11、[设计一个线程池](https://www.jianshu.com/p/5bb4123e415c)、[iOS 任务调度器:为 CPU和内存减负](https://www.jianshu.com/p/f2a610c77d26) @@ -59,6 +59,14 @@ * 52、[透彻理解block中weakSelf和strongSelf](https://www.jianshu.com/p/ae4f84e289b9) * 53、[ios实现读写锁](https://blog.csdn.net/u014600626/article/details/102884794) * 54、[UIView Animation的Block谁持有](http://saitjr.com/ios/ios-from-memory-leak-to-uiview-animation.html) +* 55、[watchdog 机制](https://juejin.cn/post/6844903683021340679) +* 56、[什么是依赖注入?](https://www.jianshu.com/p/0d72a945f2dd) +* 57、[ARC的原理,引用计数是怎么管理的,weak 关键字的原理](https://www.jianshu.com/p/e3690f3e4675) +* 58、[autoReleasePool的原理 autoReleasePool 的哨兵、自己创建的 @autoReleasePool是怎样运行的,什么对象是autoRelease的](https://www.jianshu.com/p/77eb9e0bcd70) +* 59、[RunLoop与AutoReleasepool的关系学习](https://www.jianshu.com/p/ae8a310457d7) +* 60、[子线程默认不会开启 Runloop,那出现 Autorelease 对象如何处理?不手动处 理会内存泄漏吗?](https://zhuanlan.zhihu.com/p/26796146) +* 61、[Atomic为什么不安全,怎么实现一个安全的存取](https://www.jianshu.com/p/f7411c90a68a)、[iOS中如何设计多线程的读写安全](https://tech.souyunku.com/?p=31631) +* 62、[什么是@synchronized](https://blog.csdn.net/qq_28551705/article/details/86094764) ### 网络 From 8f742a238ac4a8d434137c770e65d73e2aa9e3f0 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 23 Nov 2020 23:00:17 +0800 Subject: [PATCH 315/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index d099512f..81facc4e 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -31,3 +31,4 @@ * 27、[从SIL看Swift函数派发机制](https://mp.weixin.qq.com/s/KvwFyc1X_anTt-DTw86u7Q) * 28、[iOS 锁的简单实现与总结](https://www.jianshu.com/p/a33959324cc7?from=singlemessage) * 29、[引用计数带来的一次讨论](https://www.jianshu.com/p/e3690f3e4675) +* 30、[小程序「同层渲染」那些事(keng)?](https://juejin.cn/post/6881502813105422349) From 6fdad80b14b4339c80413760bbeeb538701c0fc5 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 23 Nov 2020 23:02:49 +0800 Subject: [PATCH 316/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 2 ++ 1 file changed, 2 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 84345a24..e6242e86 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -80,6 +80,8 @@ * 7、[TCP三次握手、四次挥手、https加密原理]() * 8、[为什么TCP4次挥手时等待为2MSL?](https://www.zhihu.com/question/67013338) * 9、[DNS的搜索过程]() +* 10、[tcp,为什么4次断开,tcp的拥塞机制,为什么这么设计]() +* 11、[TCP/UDP]() ### 算法 From 87ee46658d47c22291ebf0bd72ae2d843f9c8572 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 23 Nov 2020 23:39:09 +0800 Subject: [PATCH 317/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index e6242e86..1fdb7236 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -24,7 +24,7 @@ * 17、[C++虚函数我们一般哪里有用到啊,还有它开销了什么东西?为啥减少使用能优化启动速度?](https://www.dazhuanlan.com/2019/12/09/5dedcdb02c287/) * 18、[内存缓存优化](https://www.jianshu.com/p/f7376a321c2e) * 19、[autoreleasepool什么时候释放](https://www.jianshu.com/p/50bdd8438857) -* 20、[响应链机制]() +* 20、[响应链机制](https://www.jianshu.com/p/2e074db792ba) * 21、[instrment的Time profilter实现原理原理]() * 22、[多线程之栅栏函数](https://zhuanlan.zhihu.com/p/142368783) * 23、[iOS 图像渲染过程、离屏渲染](https://juejin.im/post/6844904162765832206#heading-18) From 552eba24c520d80a8e68cf438ec960511e04bb80 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 24 Nov 2020 10:02:27 +0800 Subject: [PATCH 318/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 3 +++ "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + 2 files changed, 4 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 81facc4e..0f808633 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -32,3 +32,6 @@ * 28、[iOS 锁的简单实现与总结](https://www.jianshu.com/p/a33959324cc7?from=singlemessage) * 29、[引用计数带来的一次讨论](https://www.jianshu.com/p/e3690f3e4675) * 30、[小程序「同层渲染」那些事(keng)?](https://juejin.cn/post/6881502813105422349) +* 31、[深入理解JavaScriptCore](https://mp.weixin.qq.com/s/H5wBNAm93uPJDvCQCg0_cg9) +* 32、[iOS WKWebView 同步返回值给 JS](https://mp.weixin.qq.com/s/kKdNG40qbMHigwZIsJRyQQ) +* 33、[Hybrid 实战:如何完整下载一个 wap 页面](https://mp.weixin.qq.com/s/rR4lT0iPSStoHk2Kar8i9A) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index b27751c9..62576ee2 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -178,6 +178,7 @@ * 6、[JSPatch]() * 7、[Fishook]() * 8、[Aspect]() +* 9、[YYCache 源码解析(一):使用方法,架构与内存缓存的设计](https://mp.weixin.qq.com/s/tTAKHNiCVJ64738VIA__ZA) ## 其它 From af5a77f5a3d7877d2b734acbc389cfc81a008da4 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 24 Nov 2020 21:14:05 +0800 Subject: [PATCH 319/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 1 + .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 2 ++ ...\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 3 files changed, 4 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 0f808633..650a6b14 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -35,3 +35,4 @@ * 31、[深入理解JavaScriptCore](https://mp.weixin.qq.com/s/H5wBNAm93uPJDvCQCg0_cg9) * 32、[iOS WKWebView 同步返回值给 JS](https://mp.weixin.qq.com/s/kKdNG40qbMHigwZIsJRyQQ) * 33、[Hybrid 实战:如何完整下载一个 wap 页面](https://mp.weixin.qq.com/s/rR4lT0iPSStoHk2Kar8i9A) +* 34、[UIView 动画降帧探究](https://mp.weixin.qq.com/s/EcVrrT1M4mI4f4d2b3qV0Q) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 1fdb7236..aac1cc7d 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -67,6 +67,8 @@ * 60、[子线程默认不会开启 Runloop,那出现 Autorelease 对象如何处理?不手动处 理会内存泄漏吗?](https://zhuanlan.zhihu.com/p/26796146) * 61、[Atomic为什么不安全,怎么实现一个安全的存取](https://www.jianshu.com/p/f7411c90a68a)、[iOS中如何设计多线程的读写安全](https://tech.souyunku.com/?p=31631) * 62、[什么是@synchronized](https://blog.csdn.net/qq_28551705/article/details/86094764) +* 63、[线程和进程的区别](https://www.jianshu.com/p/68b274548069) +* 64、[对于大图片加载引起的oom问题,怎么处理]() ### 网络 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index f14c1e95..39dcb0e5 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -74,6 +74,7 @@ * 72、[折腾范儿の味精](http://awhisper.github.io) * 73、[zhangferry](https://juejin.im/user/2242659450368119) * 74、[酷酷的哀殿](https://ai-chan.top/) +* 75、[陈满iOS](https://juejin.cn/user/3245414055161870) ## 高质量微信公众号 From c8e646c73c8bc801a17f8668a702ab640b8f8ccf Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 25 Nov 2020 09:56:34 +0800 Subject: [PATCH 320/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index aac1cc7d..ab1db6ba 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -38,7 +38,7 @@ * 31、[WKWebVie与JS通信的几种方式]() * 32、[什么是泛型?Swift的字符串string与OC的NSString差别?对于Swift协议的理解?]() * 33、[APP启动时长监控]() -* 34、[https相关]() +* 34、[https相关](https://mp.weixin.qq.com/s/LV3cFpQtMUntMg6zn-01pQ) * 35、[设计一个网络框架]() * 36、[网络最大并发数]() * 37、[分类和扩展区别](https://www.jianshu.com/p/ba35a975af9a) @@ -84,6 +84,7 @@ * 9、[DNS的搜索过程]() * 10、[tcp,为什么4次断开,tcp的拥塞机制,为什么这么设计]() * 11、[TCP/UDP]() +* 12、[图解 | 什么是HTTP简史](https://mp.weixin.qq.com/s/LV3cFpQtMUntMg6zn-01pQ) ### 算法 From 71b2839c1671090895b8dc6105c6c525d702bed8 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 25 Nov 2020 18:04:29 +0800 Subject: [PATCH 321/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index ab1db6ba..f56652d7 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -85,6 +85,7 @@ * 10、[tcp,为什么4次断开,tcp的拥塞机制,为什么这么设计]() * 11、[TCP/UDP]() * 12、[图解 | 什么是HTTP简史](https://mp.weixin.qq.com/s/LV3cFpQtMUntMg6zn-01pQ) +* 13、[Charles抓包原理]() ### 算法 From c6649207a6e247612a67d72a18fa49d755e0adf0 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 25 Nov 2020 19:58:10 +0800 Subject: [PATCH 322/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 1 + .../DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 1 + 2 files changed, 2 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 650a6b14..076f87c3 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -36,3 +36,4 @@ * 32、[iOS WKWebView 同步返回值给 JS](https://mp.weixin.qq.com/s/kKdNG40qbMHigwZIsJRyQQ) * 33、[Hybrid 实战:如何完整下载一个 wap 页面](https://mp.weixin.qq.com/s/rR4lT0iPSStoHk2Kar8i9A) * 34、[UIView 动画降帧探究](https://mp.weixin.qq.com/s/EcVrrT1M4mI4f4d2b3qV0Q) +* 35、[iOS AOP 方案的对比与思考](https://juejin.cn/post/6898192050512986126) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index f56652d7..fc0f21c7 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -69,6 +69,7 @@ * 62、[什么是@synchronized](https://blog.csdn.net/qq_28551705/article/details/86094764) * 63、[线程和进程的区别](https://www.jianshu.com/p/68b274548069) * 64、[对于大图片加载引起的oom问题,怎么处理]() +* 65、[Crash函数信息符号化]() ### 网络 From ab43d8dbc7468b3fc15729c65cfe83afc11472e5 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 25 Nov 2020 20:38:56 +0800 Subject: [PATCH 323/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index fc0f21c7..6dc18e27 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -70,6 +70,7 @@ * 63、[线程和进程的区别](https://www.jianshu.com/p/68b274548069) * 64、[对于大图片加载引起的oom问题,怎么处理]() * 65、[Crash函数信息符号化]() +* 66、[IPA包签名原理]() ### 网络 From f8af7e084cabdabcbf0f4cc2b12e13f528c5e7a4 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 25 Nov 2020 23:53:08 +0800 Subject: [PATCH 324/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 3 +++ .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 6 ++++++ 2 files changed, 9 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 076f87c3..6da6cbc7 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -37,3 +37,6 @@ * 33、[Hybrid 实战:如何完整下载一个 wap 页面](https://mp.weixin.qq.com/s/rR4lT0iPSStoHk2Kar8i9A) * 34、[UIView 动画降帧探究](https://mp.weixin.qq.com/s/EcVrrT1M4mI4f4d2b3qV0Q) * 35、[iOS AOP 方案的对比与思考](https://juejin.cn/post/6898192050512986126) +* 36、[如何对 iOS 启动阶段耗时进行分析](https://www.jianshu.com/p/c0c4f19d317f) +* 37、[UIView 的渲染过程](https://www.jianshu.com/p/365cf516dbcb) +* 38、[IOS UIView开始深入 绘制像素到屏幕上](https://www.cnblogs.com/alunchen/p/5614355.html) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 6dc18e27..f77113e8 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -71,6 +71,12 @@ * 64、[对于大图片加载引起的oom问题,怎么处理]() * 65、[Crash函数信息符号化]() * 66、[IPA包签名原理]() +* 67、[load的详细过程]() +* 68、[卡顿监测原理]() +* 69、[组件化过程中的坑]() +* 70、[Mach-O文件]() +* 71、[深入理解Tagged Pointer](https://www.jianshu.com/p/c9089494fb6c) +* 72、[iOS 的渲染机制以及 UIView 的自动布局流程](https://www.dazhuanlan.com/2020/01/31/5e33cdfb28a2a/) ### 网络 From 4872b79c73c6a41df6650ff6b90b781222862cc0 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 26 Nov 2020 00:17:18 +0800 Subject: [PATCH 325/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index f77113e8..f41f8b46 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -77,6 +77,7 @@ * 70、[Mach-O文件]() * 71、[深入理解Tagged Pointer](https://www.jianshu.com/p/c9089494fb6c) * 72、[iOS 的渲染机制以及 UIView 的自动布局流程](https://www.dazhuanlan.com/2020/01/31/5e33cdfb28a2a/) +* 73、[MD5、AES、RSA等加密原理]() ### 网络 From ead1905e6a0714b10fc2ddcd32d78d511656bfd9 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 26 Nov 2020 13:59:22 +0800 Subject: [PATCH 326/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.h | 2 +- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 3 +++ .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.h b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.h index d34e3c57..335530cc 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.h +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.h @@ -8,7 +8,7 @@ #import -///监测+load方法耗时 引自: https://www.jianshu.com/p/c14987eee107 +///监测+load方法耗时 引自: https://www.jianshu.com/p/c14987eee107、https://www.cnblogs.com/feng9exe/p/12487662.html @interface SLAPMLoadTime : NSObject @end diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 6da6cbc7..ac3e6053 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -40,3 +40,6 @@ * 36、[如何对 iOS 启动阶段耗时进行分析](https://www.jianshu.com/p/c0c4f19d317f) * 37、[UIView 的渲染过程](https://www.jianshu.com/p/365cf516dbcb) * 38、[IOS UIView开始深入 绘制像素到屏幕上](https://www.cnblogs.com/alunchen/p/5614355.html) +* 39、[iOS深思篇 | 启动时间的度量和优化](https://www.cnblogs.com/feng9exe/p/12487662.html) +* 40、[Hook load方法耗时](https://github.com/tripleCC/Laboratory/tree/master/HookLoadMethods) +* 41、[__attribute__ 机制使用](https://www.jianshu.com/p/e2dfccc32c80) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index f41f8b46..577870d5 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -78,6 +78,8 @@ * 71、[深入理解Tagged Pointer](https://www.jianshu.com/p/c9089494fb6c) * 72、[iOS 的渲染机制以及 UIView 的自动布局流程](https://www.dazhuanlan.com/2020/01/31/5e33cdfb28a2a/) * 73、[MD5、AES、RSA等加密原理]() +* 74、[pod install和pod update的区别]() +* 75、[跨平台框架原理]() ### 网络 From a245ceaf8e5283297fed6bc23ede403ec4cd91a2 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 26 Nov 2020 16:52:44 +0800 Subject: [PATCH 327/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 6 ++++++ .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index ac3e6053..eda45c12 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -43,3 +43,9 @@ * 39、[iOS深思篇 | 启动时间的度量和优化](https://www.cnblogs.com/feng9exe/p/12487662.html) * 40、[Hook load方法耗时](https://github.com/tripleCC/Laboratory/tree/master/HookLoadMethods) * 41、[__attribute__ 机制使用](https://www.jianshu.com/p/e2dfccc32c80) +* 42、[iOS中 性能优化之浅谈load与initialize](https://blog.csdn.net/Lea__DongYang/article/details/79702537) +* 43、[#iOS性能优化](https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&__biz=MzI2NTAxMzg2MA==&scene=1&album_id=1569172435344637952&count=3#wechat_redirect) +* 44、[监控所有的OC方法耗时](https://juejin.cn/post/6844903875804135431) +* 45、[深入剖析iOS动态链接库](https://www.jianshu.com/p/1de663f64c05) +* 46、[【IOS开发高级系列】dyld专题](https://www.jianshu.com/p/5f337da8fbef) + diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 577870d5..840fa9ea 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -71,7 +71,7 @@ * 64、[对于大图片加载引起的oom问题,怎么处理]() * 65、[Crash函数信息符号化]() * 66、[IPA包签名原理]() -* 67、[load的详细过程]() +* 67、[load的详细过程](https://blog.csdn.net/Lea__DongYang/article/details/79702537) * 68、[卡顿监测原理]() * 69、[组件化过程中的坑]() * 70、[Mach-O文件]() From 3fd60cecd82e736b371d47f7895e8fd1ca086b01 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 26 Nov 2020 23:31:43 +0800 Subject: [PATCH 328/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 3 ++- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index eda45c12..acf8fc5a 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -48,4 +48,5 @@ * 44、[监控所有的OC方法耗时](https://juejin.cn/post/6844903875804135431) * 45、[深入剖析iOS动态链接库](https://www.jianshu.com/p/1de663f64c05) * 46、[【IOS开发高级系列】dyld专题](https://www.jianshu.com/p/5f337da8fbef) - +* 47、[iOS图片加载速度极限优化—FastImageCache解析](https://note.youdao.com/ynoteshare1/index.html?id=c66e46ed804849833a3189952afcf2c0&type=note) +* 48、[深入iOS系统底层之程序映像](https://www.jianshu.com/p/3b83193ff851) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 840fa9ea..a61e3b50 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -68,17 +68,17 @@ * 61、[Atomic为什么不安全,怎么实现一个安全的存取](https://www.jianshu.com/p/f7411c90a68a)、[iOS中如何设计多线程的读写安全](https://tech.souyunku.com/?p=31631) * 62、[什么是@synchronized](https://blog.csdn.net/qq_28551705/article/details/86094764) * 63、[线程和进程的区别](https://www.jianshu.com/p/68b274548069) -* 64、[对于大图片加载引起的oom问题,怎么处理]() -* 65、[Crash函数信息符号化]() +* 64、[对于大图片加载引起的oom问题,怎么处理](https://www.jianshu.com/p/52e3535dd37c) +* 65、[Crash堆栈和符号的对应解析符号化]() * 66、[IPA包签名原理]() * 67、[load的详细过程](https://blog.csdn.net/Lea__DongYang/article/details/79702537) * 68、[卡顿监测原理]() * 69、[组件化过程中的坑]() -* 70、[Mach-O文件]() +* 70、[Mach-O文件](https://www.jianshu.com/p/7c87e115492d)、[深入iOS系统底层之程序映像](https://www.jianshu.com/p/3b83193ff851) * 71、[深入理解Tagged Pointer](https://www.jianshu.com/p/c9089494fb6c) * 72、[iOS 的渲染机制以及 UIView 的自动布局流程](https://www.dazhuanlan.com/2020/01/31/5e33cdfb28a2a/) * 73、[MD5、AES、RSA等加密原理]() -* 74、[pod install和pod update的区别]() +* 74、[pod install和pod update的区别](https://blog.csdn.net/jhope/article/details/81535586) * 75、[跨平台框架原理]() From aaf977d10efde6c9c889dc87a7d56e589f7ca20a Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 26 Nov 2020 23:56:39 +0800 Subject: [PATCH 329/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 62576ee2..dce2971a 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -121,6 +121,7 @@ * 6、[iOS LLVM-Clang 浅谈](https://www.jianshu.com/p/7ceca351a045) * 7、[iOSer逆向](https://iosre.com) * 8、[fishhook 原理探究](https://mp.weixin.qq.com/s/uP3PASr7IoOMCQ-yy4RanA) +* 9、[Mach-O文件](https://www.jianshu.com/p/7c87e115492d)、[深入iOS系统底层之程序映像](https://www.jianshu.com/p/3b83193ff851) ## 五、音视频 From e8680f5e49878aff3094672e04ef36c0b570b587 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 27 Nov 2020 00:12:37 +0800 Subject: [PATCH 330/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.m | 1 + 1 file changed, 1 insertion(+) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.m index 0d6c373e..af387741 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.m @@ -36,6 +36,7 @@ + (void)load { const char* path = _dyld_get_image_name((unsigned)iImg); NSString *imagePath = [NSString stringWithUTF8String:path]; +// NSLog(@"映像 %@",imagePath); NSBundle* mainBundle = [NSBundle mainBundle]; NSString* bundlePath = [mainBundle bundlePath]; From 9c092a916b6973896c12d7ce8a05fa0dee16b702 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 27 Nov 2020 00:23:13 +0800 Subject: [PATCH 331/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.m index af387741..1f9ea3cd 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.m @@ -30,6 +30,8 @@ + (void)load { CFAbsoluteTime time1 =CFAbsoluteTimeGetCurrent(); +// [深入iOS系统底层之程序映像](https://www.jianshu.com/p/3b83193ff851) + int imageCount = (int)_dyld_image_count(); for(int iImg = 0; iImg < imageCount; iImg++) { From cb8bdf0481a9ff200feee5fd25134d84e6c1ea21 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 27 Nov 2020 00:42:10 +0800 Subject: [PATCH 332/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 2 ++ "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index acf8fc5a..7fc2a54b 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -50,3 +50,5 @@ * 46、[【IOS开发高级系列】dyld专题](https://www.jianshu.com/p/5f337da8fbef) * 47、[iOS图片加载速度极限优化—FastImageCache解析](https://note.youdao.com/ynoteshare1/index.html?id=c66e46ed804849833a3189952afcf2c0&type=note) * 48、[深入iOS系统底层之程序映像](https://www.jianshu.com/p/3b83193ff851) +* 49、[深入iOS系统底层之crash解决方法](https://www.jianshu.com/p/cf0945f9c1f8) + diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index dce2971a..1049b610 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -122,6 +122,7 @@ * 7、[iOSer逆向](https://iosre.com) * 8、[fishhook 原理探究](https://mp.weixin.qq.com/s/uP3PASr7IoOMCQ-yy4RanA) * 9、[Mach-O文件](https://www.jianshu.com/p/7c87e115492d)、[深入iOS系统底层之程序映像](https://www.jianshu.com/p/3b83193ff851) +* 10、[深入iOS底层系列](https://www.jianshu.com/nb/21164557) ## 五、音视频 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index a61e3b50..31195e45 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -69,7 +69,7 @@ * 62、[什么是@synchronized](https://blog.csdn.net/qq_28551705/article/details/86094764) * 63、[线程和进程的区别](https://www.jianshu.com/p/68b274548069) * 64、[对于大图片加载引起的oom问题,怎么处理](https://www.jianshu.com/p/52e3535dd37c) -* 65、[Crash堆栈和符号的对应解析符号化]() +* 65、[Crash堆栈和符号的对应解析符号化](https://www.jianshu.com/p/cf0945f9c1f8) * 66、[IPA包签名原理]() * 67、[load的详细过程](https://blog.csdn.net/Lea__DongYang/article/details/79702537) * 68、[卡顿监测原理]() From cfd8d1b92ba634cc697f0081837319bbec4d88d0 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 27 Nov 2020 13:52:37 +0800 Subject: [PATCH 333/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 2 +- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 7fc2a54b..d88cf625 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -51,4 +51,4 @@ * 47、[iOS图片加载速度极限优化—FastImageCache解析](https://note.youdao.com/ynoteshare1/index.html?id=c66e46ed804849833a3189952afcf2c0&type=note) * 48、[深入iOS系统底层之程序映像](https://www.jianshu.com/p/3b83193ff851) * 49、[深入iOS系统底层之crash解决方法](https://www.jianshu.com/p/cf0945f9c1f8) - +* 50、[深入iOS系统底层之CPU寄存器](https://www.jianshu.com/p/6d7a57794122) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 31195e45..2928abeb 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -69,7 +69,7 @@ * 62、[什么是@synchronized](https://blog.csdn.net/qq_28551705/article/details/86094764) * 63、[线程和进程的区别](https://www.jianshu.com/p/68b274548069) * 64、[对于大图片加载引起的oom问题,怎么处理](https://www.jianshu.com/p/52e3535dd37c) -* 65、[Crash堆栈和符号的对应解析符号化](https://www.jianshu.com/p/cf0945f9c1f8) +* 65、[Crash堆栈和符号的对应解析符号化](https://www.jianshu.com/p/29051908c74b) * 66、[IPA包签名原理]() * 67、[load的详细过程](https://blog.csdn.net/Lea__DongYang/article/details/79702537) * 68、[卡顿监测原理]() From 51930afc842e3e48c4595912b39089aaaa89cf4f Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 27 Nov 2020 23:10:51 +0800 Subject: [PATCH 334/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 7 +++++++ "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 2 +- ...217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 3 +++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index d88cf625..74e8339e 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -52,3 +52,10 @@ * 48、[深入iOS系统底层之程序映像](https://www.jianshu.com/p/3b83193ff851) * 49、[深入iOS系统底层之crash解决方法](https://www.jianshu.com/p/cf0945f9c1f8) * 50、[深入iOS系统底层之CPU寄存器](https://www.jianshu.com/p/6d7a57794122) +* 51、[漫谈iOS Crash收集框架](http://www.cocoachina.com/articles/12301) +* 52、[iOS crash log手动解析](https://www.jianshu.com/p/98038765743b) +* 53、[iOS Crash分析必备:符号化系统库方法](https://www.jianshu.com/p/f9eeeecff8d8) +* 54、[使用symbolicatecrash解析了一个crash log](https://www.jianshu.com/p/0a1c029e910f) +* 55、[如何符号化Objective-C调用栈](https://www.jianshu.com/p/3e5097a9be46) +* 56、[移动端监控体系之技术原理剖析](https://www.jianshu.com/p/8123fc17fe0e) +* 57、[iOS无埋点数据SDK实践之路](https://www.jianshu.com/p/69ce01e15042) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 1049b610..dfbd95e3 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -169,6 +169,7 @@ * 1、[IOS设计模式探索(大话设计模式)](https://github.com/huang303513/Design-Pattern-For-iOS.git) * 2、[面向对象设计的设计原则和设计模式](https://github.com/knightsj/object-oriented-design) +* 3、[iOS VIPER架构实践(一):从MVC到MVVM到VIPER](https://juejin.cn/post/6844903491941433351) ## 十一、优秀三方源码解析 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 2928abeb..5471d32a 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -72,7 +72,7 @@ * 65、[Crash堆栈和符号的对应解析符号化](https://www.jianshu.com/p/29051908c74b) * 66、[IPA包签名原理]() * 67、[load的详细过程](https://blog.csdn.net/Lea__DongYang/article/details/79702537) -* 68、[卡顿监测原理]() +* 68、[卡顿监测原理](https://www.jianshu.com/p/8123fc17fe0e) * 69、[组件化过程中的坑]() * 70、[Mach-O文件](https://www.jianshu.com/p/7c87e115492d)、[深入iOS系统底层之程序映像](https://www.jianshu.com/p/3b83193ff851) * 71、[深入理解Tagged Pointer](https://www.jianshu.com/p/c9089494fb6c) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 39dcb0e5..871ca218 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -75,6 +75,9 @@ * 73、[zhangferry](https://juejin.im/user/2242659450368119) * 74、[酷酷的哀殿](https://ai-chan.top/) * 75、[陈满iOS](https://juejin.cn/user/3245414055161870) +* 76、[黑超熊猫zuik](https://juejin.cn/user/2594503170727399) +* 77、[卖萌凉](https://www.jianshu.com/u/5e309e5486c6) + ## 高质量微信公众号 From 77e854a70987750ba140055d0b329811396230c2 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sat, 28 Nov 2020 00:49:29 +0800 Subject: [PATCH 335/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.m | 1 + .../DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 1 + 2 files changed, 2 insertions(+) diff --git a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.m b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.m index 1f9ea3cd..020953ec 100644 --- a/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.m +++ b/iOS_Tips/DarkMode/WorkIssues/APM/APMMonitor/SLAPMLoadTime.m @@ -96,6 +96,7 @@ + (void)LDAPM_Load { }; [_loadInfoArray addObject:infoDic]; + NSLog(@"loadTime %@",infoDic.description); } @end diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 74e8339e..6881b4d7 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -59,3 +59,4 @@ * 55、[如何符号化Objective-C调用栈](https://www.jianshu.com/p/3e5097a9be46) * 56、[移动端监控体系之技术原理剖析](https://www.jianshu.com/p/8123fc17fe0e) * 57、[iOS无埋点数据SDK实践之路](https://www.jianshu.com/p/69ce01e15042) +* 58、[APM系列(二):电量消耗速率监控](https://kyson.cn/index.php/archives/150/) From d1250d39d2e9f3ecdaa23a9340861d9c145a5acb Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sat, 28 Nov 2020 19:29:55 +0800 Subject: [PATCH 336/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 5471d32a..6063b935 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -70,14 +70,14 @@ * 63、[线程和进程的区别](https://www.jianshu.com/p/68b274548069) * 64、[对于大图片加载引起的oom问题,怎么处理](https://www.jianshu.com/p/52e3535dd37c) * 65、[Crash堆栈和符号的对应解析符号化](https://www.jianshu.com/p/29051908c74b) -* 66、[IPA包签名原理]() +* 66、[IPA包签名原理](https://juejin.cn/post/6844903744233013262) * 67、[load的详细过程](https://blog.csdn.net/Lea__DongYang/article/details/79702537) * 68、[卡顿监测原理](https://www.jianshu.com/p/8123fc17fe0e) -* 69、[组件化过程中的坑]() +* 69、[组件化过程中的坑](https://www.jianshu.com/p/a869650dd3b6) * 70、[Mach-O文件](https://www.jianshu.com/p/7c87e115492d)、[深入iOS系统底层之程序映像](https://www.jianshu.com/p/3b83193ff851) * 71、[深入理解Tagged Pointer](https://www.jianshu.com/p/c9089494fb6c) * 72、[iOS 的渲染机制以及 UIView 的自动布局流程](https://www.dazhuanlan.com/2020/01/31/5e33cdfb28a2a/) -* 73、[MD5、AES、RSA等加密原理]() +* 73、[MD5(哈希/摘要算法)、AES和DES(对称加密)、RSA(非对称加密)](https://blog.csdn.net/seoyundu/article/details/88112861) * 74、[pod install和pod update的区别](https://blog.csdn.net/jhope/article/details/81535586) * 75、[跨平台框架原理]() @@ -96,7 +96,7 @@ * 10、[tcp,为什么4次断开,tcp的拥塞机制,为什么这么设计]() * 11、[TCP/UDP]() * 12、[图解 | 什么是HTTP简史](https://mp.weixin.qq.com/s/LV3cFpQtMUntMg6zn-01pQ) -* 13、[Charles抓包原理]() +* 13、[Charles抓包原理](https://www.jianshu.com/p/f6f6a21e17c0) ### 算法 From 21c68e759be6d51435983bed12446f3f984e1b6f Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sun, 29 Nov 2020 18:10:28 +0800 Subject: [PATCH 337/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 6063b935..54b08aec 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -90,11 +90,11 @@ * 4、[如何保障客户端与服务器交互中的数据安全](https://netsecurity.51cto.com/art/202002/610473.htm) * 5、[iOS面试备战-网络篇](https://juejin.im/post/6844904202523639822#comment) * 6、[在浏览器输入url后发生了什么](https://www.jianshu.com/p/7eea6fbc5fcd) -* 7、[TCP三次握手、四次挥手、https加密原理]() +* 7、[TCP三次握手、四次挥手、https加密原理](https://www.cnblogs.com/imstudy/p/10669631.html) * 8、[为什么TCP4次挥手时等待为2MSL?](https://www.zhihu.com/question/67013338) -* 9、[DNS的搜索过程]() +* 9、[DNS的搜索过程](https://juejin.cn/post/6844904165370544141) * 10、[tcp,为什么4次断开,tcp的拥塞机制,为什么这么设计]() -* 11、[TCP/UDP]() +* 11、[TCP/UDP](https://juejin.cn/post/6844903889146216456) * 12、[图解 | 什么是HTTP简史](https://mp.weixin.qq.com/s/LV3cFpQtMUntMg6zn-01pQ) * 13、[Charles抓包原理](https://www.jianshu.com/p/f6f6a21e17c0) From 1e4a3cac4d67a66380793c76a3db08278aa9719f Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sun, 29 Nov 2020 20:26:13 +0800 Subject: [PATCH 338/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 1 + .../DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 3 ++- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 8 ++++++-- ...17\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 4 files changed, 10 insertions(+), 3 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 6881b4d7..2b27d421 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -60,3 +60,4 @@ * 56、[移动端监控体系之技术原理剖析](https://www.jianshu.com/p/8123fc17fe0e) * 57、[iOS无埋点数据SDK实践之路](https://www.jianshu.com/p/69ce01e15042) * 58、[APM系列(二):电量消耗速率监控](https://kyson.cn/index.php/archives/150/) +* 59、[有赞webview加速平台探索与建设(一)](https://tech.youzan.com/youzan-webview-goldwing-one/) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index dfbd95e3..a5f79819 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -145,7 +145,8 @@ * 7、[SYWebViewBridge](https://mp.weixin.qq.com/s/JDCyWg1AYemxbnFbvY5E9w) * 8、[JSPatch-实现原理详解](https://github.com/bang590/JSPatch/wiki/JSPatch-实现原理详解) * 9、[WKWebview秒开实践分享及问题解决方案](https://juejin.im/post/6887161842406260744) -*10、[轻量级低风险 iOS 热更新方案](https://mp.weixin.qq.com/s/2re_s3NmOvE9RXlbGQqGDA) +* 10、[轻量级低风险 iOS 热更新方案](https://mp.weixin.qq.com/s/2re_s3NmOvE9RXlbGQqGDA) +* 11、[有赞webview加速平台探索与建设(一)](https://tech.youzan.com/youzan-webview-goldwing-one/) ## 七、Shell脚本 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 54b08aec..fac8ae5d 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -80,7 +80,9 @@ * 73、[MD5(哈希/摘要算法)、AES和DES(对称加密)、RSA(非对称加密)](https://blog.csdn.net/seoyundu/article/details/88112861) * 74、[pod install和pod update的区别](https://blog.csdn.net/jhope/article/details/81535586) * 75、[跨平台框架原理]() - +* 76、[NSString的内部原理、taggedPointString](https://www.jianshu.com/p/627815e1996b) +* 77、[Mian函数启动前的流程,是谁加载的动态库(dyld),runtime在何时加载](https://www.jianshu.com/p/5efe327ac7ea) +* 78、[解释一下段⻚式的内存管理,段⻚式虚拟内存的含义是什么,怎么进行换⻚]() ### 网络 @@ -92,11 +94,12 @@ * 6、[在浏览器输入url后发生了什么](https://www.jianshu.com/p/7eea6fbc5fcd) * 7、[TCP三次握手、四次挥手、https加密原理](https://www.cnblogs.com/imstudy/p/10669631.html) * 8、[为什么TCP4次挥手时等待为2MSL?](https://www.zhihu.com/question/67013338) -* 9、[DNS的搜索过程](https://juejin.cn/post/6844904165370544141) +* 9、[DNS的搜索过程](https://juejin.cn/post/6884183177926033416) * 10、[tcp,为什么4次断开,tcp的拥塞机制,为什么这么设计]() * 11、[TCP/UDP](https://juejin.cn/post/6844903889146216456) * 12、[图解 | 什么是HTTP简史](https://mp.weixin.qq.com/s/LV3cFpQtMUntMg6zn-01pQ) * 13、[Charles抓包原理](https://www.jianshu.com/p/f6f6a21e17c0) +* 14、[DNS的查找过程,什么是DNS劫持](https://juejin.cn/post/6884183177926033416) ### 算法 @@ -121,3 +124,4 @@ * 19、[找出无序数组中所有3个数字加起来是0 的数字(先排序,再双指针)]() * 20、[最长回文子串]() * 21、[找出无序数组中所有3个数字加起来是0 的数字]() +* 22、[找出两个有序数组的中位数]() diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 871ca218..4420c680 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -77,6 +77,7 @@ * 75、[陈满iOS](https://juejin.cn/user/3245414055161870) * 76、[黑超熊猫zuik](https://juejin.cn/user/2594503170727399) * 77、[卖萌凉](https://www.jianshu.com/u/5e309e5486c6) +* 78、[有赞技术团队](https://tech.youzan.com) From 05c5963671baa5f09a0b5811b500ab3f323317fa Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 30 Nov 2020 00:09:00 +0800 Subject: [PATCH 339/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SLBinaryResetViewController.h" | 2 +- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 4 ++++ .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 4 ++-- ...07\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.h" "b/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.h" index 21458aeb..23c47e97 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.h" +++ "b/iOS_Tips/DarkMode/WorkIssues/\344\272\214\350\277\233\345\210\266\351\207\215\346\216\222/SLBinaryResetViewController.h" @@ -10,7 +10,7 @@ NS_ASSUME_NONNULL_BEGIN -//参考:https://juejin.im/post/5e97c3c751882573b86f9d00#heading-17 +//参考:https://juejin.cn/post/6844904130406793224 // https://github.com/rhythmkay/PGOAnalyzer ///二进制重排优化启动时间 @interface SLBinaryResetViewController : SLViewController diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index a5f79819..dd70147e 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -123,6 +123,7 @@ * 8、[fishhook 原理探究](https://mp.weixin.qq.com/s/uP3PASr7IoOMCQ-yy4RanA) * 9、[Mach-O文件](https://www.jianshu.com/p/7c87e115492d)、[深入iOS系统底层之程序映像](https://www.jianshu.com/p/3b83193ff851) * 10、[深入iOS底层系列](https://www.jianshu.com/nb/21164557) +* 11、[iOS App 安全加固方案调研](https://mp.weixin.qq.com/s?__biz=MzI2NzI4MTEwNA==&mid=2247485642&idx=1&sn=dce8e7581d94c8d8d2b79366f6223161&chksm=ea807f75ddf7f663daf6776b0f5a98aeea2e735e08c3a5268fd00f45b5a893d0e8dbac03b0f8&mpshare=1&scene=23&srcid=%23rd) ## 五、音视频 @@ -147,6 +148,8 @@ * 9、[WKWebview秒开实践分享及问题解决方案](https://juejin.im/post/6887161842406260744) * 10、[轻量级低风险 iOS 热更新方案](https://mp.weixin.qq.com/s/2re_s3NmOvE9RXlbGQqGDA) * 11、[有赞webview加速平台探索与建设(一)](https://tech.youzan.com/youzan-webview-goldwing-one/) +* 12、[ReactNative iOS 框架源码解析](https://juejin.cn/post/6844904190385487886) +* 13、[写一个易于维护使用方便性能可靠的Hybrid框架](https://juejin.cn/post/6844903733583675406) ## 七、Shell脚本 @@ -171,6 +174,7 @@ * 1、[IOS设计模式探索(大话设计模式)](https://github.com/huang303513/Design-Pattern-For-iOS.git) * 2、[面向对象设计的设计原则和设计模式](https://github.com/knightsj/object-oriented-design) * 3、[iOS VIPER架构实践(一):从MVC到MVVM到VIPER](https://juejin.cn/post/6844903491941433351) +* 4、[浅谈 MVC、MVP 和 MVVM 架构模式](https://draveness.me/mvx/) ## 十一、优秀三方源码解析 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index fac8ae5d..bf4feec7 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -82,7 +82,8 @@ * 75、[跨平台框架原理]() * 76、[NSString的内部原理、taggedPointString](https://www.jianshu.com/p/627815e1996b) * 77、[Mian函数启动前的流程,是谁加载的动态库(dyld),runtime在何时加载](https://www.jianshu.com/p/5efe327ac7ea) -* 78、[解释一下段⻚式的内存管理,段⻚式虚拟内存的含义是什么,怎么进行换⻚]() +* 78、[解释一下段⻚式的内存管理,段⻚式虚拟内存的含义是什么,怎么进行换⻚](https://blog.csdn.net/low5252/article/details/106075945) +* 79、[KVO存在哪些⻛险](https://www.cnblogs.com/wengzilin/p/4346775.html) ### 网络 @@ -124,4 +125,3 @@ * 19、[找出无序数组中所有3个数字加起来是0 的数字(先排序,再双指针)]() * 20、[最长回文子串]() * 21、[找出无序数组中所有3个数字加起来是0 的数字]() -* 22、[找出两个有序数组的中位数]() diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 4420c680..1cfcbba4 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -78,7 +78,7 @@ * 76、[黑超熊猫zuik](https://juejin.cn/user/2594503170727399) * 77、[卖萌凉](https://www.jianshu.com/u/5e309e5486c6) * 78、[有赞技术团队](https://tech.youzan.com) - +* 79、[Lewis](https://juejin.cn/user/3913917125896477) ## 高质量微信公众号 From 60e9a4a36eb630ac1646ca1f9630481f50e74fc2 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Mon, 30 Nov 2020 16:18:57 +0800 Subject: [PATCH 340/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index bf4feec7..4521a1de 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -84,6 +84,7 @@ * 77、[Mian函数启动前的流程,是谁加载的动态库(dyld),runtime在何时加载](https://www.jianshu.com/p/5efe327ac7ea) * 78、[解释一下段⻚式的内存管理,段⻚式虚拟内存的含义是什么,怎么进行换⻚](https://blog.csdn.net/low5252/article/details/106075945) * 79、[KVO存在哪些⻛险](https://www.cnblogs.com/wengzilin/p/4346775.html) +* 80、[大批量数据写入数据库怎么做](分表并发写入) ### 网络 From 49cb4e53c13435391169d62d8a13843a142585ce Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 1 Dec 2020 21:32:36 +0800 Subject: [PATCH 341/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\351\235\242\350\257\225\351\242\230.md" | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 4521a1de..5701c311 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -85,6 +85,14 @@ * 78、[解释一下段⻚式的内存管理,段⻚式虚拟内存的含义是什么,怎么进行换⻚](https://blog.csdn.net/low5252/article/details/106075945) * 79、[KVO存在哪些⻛险](https://www.cnblogs.com/wengzilin/p/4346775.html) * 80、[大批量数据写入数据库怎么做](分表并发写入) +* 81、[从点击屏幕开始,runloop怎么进行工作的](https://www.colabug.com/2017/1225/2102566/) +* 82、[编译过程](https://blog.csdn.net/vincentiss/article/details/54617915) +* 83、[MVVM]() +* 84、[iOS内存管理(MRC、ARC)深入浅出](https://www.jianshu.com/p/4f49c5c81021) +* 85、[APNS](https://www.jianshu.com/p/032bfc949917) +* 86、[AFN的二次封装]() +* 87、[聊聊CoreData、FMDB](https://www.jianshu.com/p/5a085a4fe2d7) + ### 网络 @@ -102,6 +110,9 @@ * 12、[图解 | 什么是HTTP简史](https://mp.weixin.qq.com/s/LV3cFpQtMUntMg6zn-01pQ) * 13、[Charles抓包原理](https://www.jianshu.com/p/f6f6a21e17c0) * 14、[DNS的查找过程,什么是DNS劫持](https://juejin.cn/post/6884183177926033416) +* 15、[Get和Post](https://juejin.cn/post/6844904004707696648) +* 16、[http的响应状态码](https://juejin.cn/post/6844903940832641037) +* 17、[https抓包过程](https://www.jianshu.com/p/7a88617ce80b) ### 算法 @@ -126,3 +137,4 @@ * 19、[找出无序数组中所有3个数字加起来是0 的数字(先排序,再双指针)]() * 20、[最长回文子串]() * 21、[找出无序数组中所有3个数字加起来是0 的数字]() +* 22、[8000W个字符串,每个长度在100以内,要求找到频率最高的前1000个]() From 720432c6530882e2e58270c60b99b0d1c0f2c9ed Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Tue, 1 Dec 2020 23:36:58 +0800 Subject: [PATCH 342/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 1 + "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index 2b27d421..a0f5f05b 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -61,3 +61,4 @@ * 57、[iOS无埋点数据SDK实践之路](https://www.jianshu.com/p/69ce01e15042) * 58、[APM系列(二):电量消耗速率监控](https://kyson.cn/index.php/archives/150/) * 59、[有赞webview加速平台探索与建设(一)](https://tech.youzan.com/youzan-webview-goldwing-one/) +* 60、[iOS 网络基础和网络优化](https://juejin.cn/post/6868945803856052231) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index dd70147e..8c306346 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -175,6 +175,7 @@ * 2、[面向对象设计的设计原则和设计模式](https://github.com/knightsj/object-oriented-design) * 3、[iOS VIPER架构实践(一):从MVC到MVVM到VIPER](https://juejin.cn/post/6844903491941433351) * 4、[浅谈 MVC、MVP 和 MVVM 架构模式](https://draveness.me/mvx/) +* 5、[iOS MVC、MVVM、MVP架构模式浅浅析](https://juejin.cn/post/6844903798591193095) ## 十一、优秀三方源码解析 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 5701c311..6f755274 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -92,6 +92,7 @@ * 85、[APNS](https://www.jianshu.com/p/032bfc949917) * 86、[AFN的二次封装]() * 87、[聊聊CoreData、FMDB](https://www.jianshu.com/p/5a085a4fe2d7) +* 88、[多线程相关]() ### 网络 @@ -137,4 +138,4 @@ * 19、[找出无序数组中所有3个数字加起来是0 的数字(先排序,再双指针)]() * 20、[最长回文子串]() * 21、[找出无序数组中所有3个数字加起来是0 的数字]() -* 22、[8000W个字符串,每个长度在100以内,要求找到频率最高的前1000个]() +* 22、[8000W个字符串,每个长度在100以内,要求找到频率最高的前1000个](https://leetcode-cn.com/problems/top-k-frequent-elements) From 70fc29ecf2811f2392c5aa534853ef27b633f3b6 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 2 Dec 2020 09:16:37 +0800 Subject: [PATCH 343/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 6f755274..5c0fcfd6 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -92,7 +92,7 @@ * 85、[APNS](https://www.jianshu.com/p/032bfc949917) * 86、[AFN的二次封装]() * 87、[聊聊CoreData、FMDB](https://www.jianshu.com/p/5a085a4fe2d7) -* 88、[多线程相关]() +* 88、[多线程相关](https://www.cnblogs.com/orang123/p/12434774.html) ### 网络 From 48e37bdefe179ff984313bde7fedb594b017171d Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 2 Dec 2020 11:31:05 +0800 Subject: [PATCH 344/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 2 ++ 1 file changed, 2 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 5c0fcfd6..249fce33 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -93,6 +93,8 @@ * 86、[AFN的二次封装]() * 87、[聊聊CoreData、FMDB](https://www.jianshu.com/p/5a085a4fe2d7) * 88、[多线程相关](https://www.cnblogs.com/orang123/p/12434774.html) +* 89、[http的header有什么字段?]() +* 90、[TimeProfile的详细使用]() ### 网络 From 43cc7226ba9c0dd27637538bffe408eda20d027f Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 4 Dec 2020 19:44:56 +0800 Subject: [PATCH 345/356] =?UTF-8?q?cell=E5=A4=8D=E7=94=A8=E9=87=8D?= =?UTF-8?q?=E7=BD=AE=E7=9A=84=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/DarkMode/WKWebView/WebNative/SLReusableManager.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/iOS_Tips/DarkMode/WKWebView/WebNative/SLReusableManager.m b/iOS_Tips/DarkMode/WKWebView/WebNative/SLReusableManager.m index 269c3082..a2a5805a 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebNative/SLReusableManager.m +++ b/iOS_Tips/DarkMode/WKWebView/WebNative/SLReusableManager.m @@ -225,6 +225,7 @@ - (void)willDisappearCellWithDirection:(BOOL)top { self.willDisplayIndexTop = self.willDisplayIndexTop+1; NSLog(@"上 第 %ld 个cell消失",self.willDisplayIndexTop); SLReusableCell *cell = self.visibleCells.firstObject; + cell.layer.contents = nil; NSHashTable * hashTable= self.reusablePool[cell.cellID]; [hashTable addObject:cell]; [self.visibleCells removeObjectAtIndex:0]; @@ -236,6 +237,7 @@ - (void)willDisappearCellWithDirection:(BOOL)top { self.willDisplayIndexBottom = self.willDisplayIndexBottom-1; NSLog(@"下 第 %ld 个cell消失",self.willDisplayIndexBottom); SLReusableCell *cell = self.visibleCells.lastObject; + cell.layer.contents = nil; NSHashTable * hashTable= self.reusablePool[cell.cellID]; [hashTable addObject:cell]; [self.visibleCells removeLastObject]; From f05f55efe05993b7c79d0e0147e63740394e7375 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sat, 5 Dec 2020 22:37:14 +0800 Subject: [PATCH 346/356] =?UTF-8?q?ios14YYAnimatedImageView=E5=9B=BE?= =?UTF-8?q?=E7=89=87=E6=98=BE=E7=A4=BA=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS_Tips/.DS_Store | Bin 10244 -> 10244 bytes iOS_Tips/DarkMode.xcodeproj/project.pbxproj | 14 ++++++++ .../YYAnimatedImageView+iOS14.h | 18 ++++++++++ .../YYAnimatedImageView+iOS14.m | 33 ++++++++++++++++++ .../WKWebView/WebNative/SLReusableManager.m | 20 ++++++++--- .../WebNative/SLWebNativeViewController.m | 2 +- 6 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 iOS_Tips/DarkMode/ThirdLibary/YYAnimatedImageViewCategory/YYAnimatedImageView+iOS14.h create mode 100644 iOS_Tips/DarkMode/ThirdLibary/YYAnimatedImageViewCategory/YYAnimatedImageView+iOS14.m diff --git a/iOS_Tips/.DS_Store b/iOS_Tips/.DS_Store index eb789d1cbce05a223d2409d53c0fa2f23ef865b4..36605046a663f0ab207dd332d7e7f883e089cd94 100644 GIT binary patch delta 151 zcmZn(XbG6$&nUGqU^hRb)Z{=xkV&;6?~Z-BQRGic>zc<11AS(ynuLhwV9EQf{BUY qWC1~Wrh|tj8w$!x9tKLo^_K+~<>ln(r31wnHx|BU-psD>mmL7}dMGIX delta 65 zcmZn(XbG6$&nU4mU^hRb#N + +@implementation YYAnimatedImageView (iOS14) ++(void)load { + // 获取系统的方法 + Method displayLayerMethod = class_getInstanceMethod(self, @selector(displayLayer:)); + // 获取更新的方法 + Method displayLayerNewMethod = class_getInstanceMethod(self, @selector(displayLayerNew:)); + // 方法交换 + method_exchangeImplementations(displayLayerMethod, displayLayerNewMethod); +} +-(void)displayLayerNew:(CALayer *)layer { + Ivar imageIvar = class_getInstanceVariable([self class], "_curFrame"); + UIImage *image = object_getIvar(self, imageIvar); + if (image) { + layer.contents = (__bridge id)image.CGImage; + } + else { + if (@available(iOS 14.0, *)) { + [super displayLayer:layer]; + } + } +} +@end diff --git a/iOS_Tips/DarkMode/WKWebView/WebNative/SLReusableManager.m b/iOS_Tips/DarkMode/WKWebView/WebNative/SLReusableManager.m index a2a5805a..f9f26458 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebNative/SLReusableManager.m +++ b/iOS_Tips/DarkMode/WKWebView/WebNative/SLReusableManager.m @@ -28,7 +28,7 @@ @interface SLReusableManager () @property (nonatomic, strong) NSMutableArray *visibleCells; ///记录最后一次的偏移量,用来判断滑动方向 @property (nonatomic, assign) CGFloat lastContentOffsetY; -///顶部即将展示的索引1 +///顶部即将展示的索引 @property (nonatomic, assign) NSInteger willDisplayIndexTop; ///底部即将展示的索引 @property (nonatomic, assign) NSInteger willDisplayIndexBottom; @@ -216,7 +216,7 @@ - (void)willDisplayCellWithDirection:(BOOL)top { } } } -//即将消失的cell,在消失时放入缓冲池里 top:YES上/NO下 +//即将消失的cell,在消失时放入缓冲池里,并且重置视图cell的内容 top:YES上/NO下 - (void)willDisappearCellWithDirection:(BOOL)top { if(top) { if (self.willDisplayIndexTop+1 >= self.frameArray.count) return; @@ -225,7 +225,13 @@ - (void)willDisappearCellWithDirection:(BOOL)top { self.willDisplayIndexTop = self.willDisplayIndexTop+1; NSLog(@"上 第 %ld 个cell消失",self.willDisplayIndexTop); SLReusableCell *cell = self.visibleCells.firstObject; - cell.layer.contents = nil; + + //进入缓冲池后,要清空重置cell上的内容,防止下一个取出时显示之前的内容,我这里重置时用了自己的默认logo,你可以自己重绘默认时的cell内容 + for (UIView *subView in cell.subviews) { + subView.layer.contents = (__bridge id)[UIImage imageNamed:@"wsl"].CGImage; + } + cell.layer.contents = (__bridge id)[UIImage imageNamed:@"wsl"].CGImage; + NSHashTable * hashTable= self.reusablePool[cell.cellID]; [hashTable addObject:cell]; [self.visibleCells removeObjectAtIndex:0]; @@ -237,7 +243,13 @@ - (void)willDisappearCellWithDirection:(BOOL)top { self.willDisplayIndexBottom = self.willDisplayIndexBottom-1; NSLog(@"下 第 %ld 个cell消失",self.willDisplayIndexBottom); SLReusableCell *cell = self.visibleCells.lastObject; - cell.layer.contents = nil; + + //进入缓冲池后,要清空重置cell上的内容,防止下一个取出时显示之前的内容,我这里重置时用了自己的默认logo,你可以自己重绘默认时的cell内容 + for (UIView *subView in cell.subviews) { + subView.layer.contents = (__bridge id)[UIImage imageNamed:@"wsl"].CGImage; + } + cell.layer.contents = (__bridge id)[UIImage imageNamed:@"wsl"].CGImage; + NSHashTable * hashTable= self.reusablePool[cell.cellID]; [hashTable addObject:cell]; [self.visibleCells removeLastObject]; diff --git a/iOS_Tips/DarkMode/WKWebView/WebNative/SLWebNativeViewController.m b/iOS_Tips/DarkMode/WKWebView/WebNative/SLWebNativeViewController.m index c6e2a2cd..89617fff 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebNative/SLWebNativeViewController.m +++ b/iOS_Tips/DarkMode/WKWebView/WebNative/SLWebNativeViewController.m @@ -8,7 +8,7 @@ #import "SLWebNativeViewController.h" #import -#import +#import "YYImage.h" #import #import "SLAvPlayer.h" #import From 93eda3189ad63ca13664109698c14a8f7d8785cf Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sat, 5 Dec 2020 22:37:51 +0800 Subject: [PATCH 347/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\347\254\224\350\256\260.md" | 1 + .../\351\235\242\350\257\225\351\242\230.md" | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 8c306346..3c126b9f 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -83,6 +83,7 @@ > [卡顿率降低50%!京东商城APP卡顿监控及优化实践](https://mp.weixin.qq.com/s/aJeAUAjcKOMvznDMGj2UUA) > [【性能优化】今日头条iOS客户端启动速度优化](https://www.jianshu.com/p/7096478ccbe7) > [iOS 崩溃排查入门:总览](https://ai-chan.top/2020/10/02/iOS-crash/) +> [卡顿率降低50%!京东商城APP卡顿监控及优化实践](https://mp.weixin.qq.com/s/aJeAUAjcKOMvznDMGj2UUA) ## 二、数据结构与算法 diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 249fce33..36573a2e 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -87,14 +87,22 @@ * 80、[大批量数据写入数据库怎么做](分表并发写入) * 81、[从点击屏幕开始,runloop怎么进行工作的](https://www.colabug.com/2017/1225/2102566/) * 82、[编译过程](https://blog.csdn.net/vincentiss/article/details/54617915) -* 83、[MVVM]() +* 83、[MVVM、MVC、MVP的区别]() * 84、[iOS内存管理(MRC、ARC)深入浅出](https://www.jianshu.com/p/4f49c5c81021) * 85、[APNS](https://www.jianshu.com/p/032bfc949917) * 86、[AFN的二次封装]() * 87、[聊聊CoreData、FMDB](https://www.jianshu.com/p/5a085a4fe2d7) * 88、[多线程相关](https://www.cnblogs.com/orang123/p/12434774.html) -* 89、[http的header有什么字段?]() +* 89、[http的header有什么字段?](https://blog.csdn.net/u013252047/article/details/80116742) * 90、[TimeProfile的详细使用]() +* 91、[卡顿的形成原因?什么是离屏渲染?]() +* 92、[Rac、SDWebImage、YYKit、AFN的原理]() +* 93、[Js与na交互的原理]() +* 94、[设计一个下载/断点续传框架]() +* 95、[NSCopy/NSCoder](https://blog.csdn.net/u014205968/article/details/78260402) +* 96、[进程间通信的几种方式](https://www.jianshu.com/p/c60f4f3cc3d2) +* 97、[引用计数为0时,内存会立即释放吗?内存是什么时候释放的?]() +* 98、[iOS 底层 - dealloc 的底层实现](https://www.jianshu.com/p/5aee2e571f6b) ### 网络 @@ -141,3 +149,4 @@ * 20、[最长回文子串]() * 21、[找出无序数组中所有3个数字加起来是0 的数字]() * 22、[8000W个字符串,每个长度在100以内,要求找到频率最高的前1000个](https://leetcode-cn.com/problems/top-k-frequent-elements) +* 23、[利用栈结构实现队列结构](https://www.cnblogs.com/lisen10/p/10892546.html) From b58f2314c18ca83fee52ac760fa93749b29be63a Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sun, 6 Dec 2020 16:09:35 +0800 Subject: [PATCH 348/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WKWebView/WebNative/SLReusableManager.m | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/iOS_Tips/DarkMode/WKWebView/WebNative/SLReusableManager.m b/iOS_Tips/DarkMode/WKWebView/WebNative/SLReusableManager.m index f9f26458..5962dd7b 100644 --- a/iOS_Tips/DarkMode/WKWebView/WebNative/SLReusableManager.m +++ b/iOS_Tips/DarkMode/WKWebView/WebNative/SLReusableManager.m @@ -227,10 +227,10 @@ - (void)willDisappearCellWithDirection:(BOOL)top { SLReusableCell *cell = self.visibleCells.firstObject; //进入缓冲池后,要清空重置cell上的内容,防止下一个取出时显示之前的内容,我这里重置时用了自己的默认logo,你可以自己重绘默认时的cell内容 - for (UIView *subView in cell.subviews) { - subView.layer.contents = (__bridge id)[UIImage imageNamed:@"wsl"].CGImage; - } - cell.layer.contents = (__bridge id)[UIImage imageNamed:@"wsl"].CGImage; +// for (UIView *subView in cell.subviews) { +// subView.layer.contents = (__bridge id)[UIImage imageNamed:@"wsl"].CGImage; +// } +// cell.layer.contents = (__bridge id)[UIImage imageNamed:@"wsl"].CGImage; NSHashTable * hashTable= self.reusablePool[cell.cellID]; [hashTable addObject:cell]; @@ -245,10 +245,10 @@ - (void)willDisappearCellWithDirection:(BOOL)top { SLReusableCell *cell = self.visibleCells.lastObject; //进入缓冲池后,要清空重置cell上的内容,防止下一个取出时显示之前的内容,我这里重置时用了自己的默认logo,你可以自己重绘默认时的cell内容 - for (UIView *subView in cell.subviews) { - subView.layer.contents = (__bridge id)[UIImage imageNamed:@"wsl"].CGImage; - } - cell.layer.contents = (__bridge id)[UIImage imageNamed:@"wsl"].CGImage; +// for (UIView *subView in cell.subviews) { +// subView.layer.contents = (__bridge id)[UIImage imageNamed:@"wsl"].CGImage; +// } +// cell.layer.contents = (__bridge id)[UIImage imageNamed:@"wsl"].CGImage; NSHashTable * hashTable= self.reusablePool[cell.cellID]; [hashTable addObject:cell]; From 19f36e8ecd2cb2b71342a45c0e1946b59a17393b Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 10 Dec 2020 14:35:07 +0800 Subject: [PATCH 349/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 1 + .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 4 ++++ ...07\217\346\212\200\346\234\257\345\215\232\345\256\242.md" | 1 + 3 files changed, 6 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index a0f5f05b..f87bfb89 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -62,3 +62,4 @@ * 58、[APM系列(二):电量消耗速率监控](https://kyson.cn/index.php/archives/150/) * 59、[有赞webview加速平台探索与建设(一)](https://tech.youzan.com/youzan-webview-goldwing-one/) * 60、[iOS 网络基础和网络优化](https://juejin.cn/post/6868945803856052231) +* 61、[llvm 编译器高级用法:第三方库插桩](https://mp.weixin.qq.com/s/RKg8f6B2jSNuFEImtMnq2Q) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 36573a2e..ed4398dd 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -103,6 +103,9 @@ * 96、[进程间通信的几种方式](https://www.jianshu.com/p/c60f4f3cc3d2) * 97、[引用计数为0时,内存会立即释放吗?内存是什么时候释放的?]() * 98、[iOS 底层 - dealloc 的底层实现](https://www.jianshu.com/p/5aee2e571f6b) +* 99、[git merge/rebase](https://blog.csdn.net/kuangdacaikuang/article/details/79619828) +* 100、[响应链的应用]() +* 101、[GCD Block会捕获self吗?]() ### 网络 @@ -150,3 +153,4 @@ * 21、[找出无序数组中所有3个数字加起来是0 的数字]() * 22、[8000W个字符串,每个长度在100以内,要求找到频率最高的前1000个](https://leetcode-cn.com/problems/top-k-frequent-elements) * 23、[利用栈结构实现队列结构](https://www.cnblogs.com/lisen10/p/10892546.html) +* 24、[验证是否是对称二叉树](https://leetcode-cn.com/problems/dui-cheng-de-er-cha-shu-lcof/) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" index 1cfcbba4..b20f8a19 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\253\230\350\264\250\351\207\217\346\212\200\346\234\257\345\215\232\345\256\242.md" @@ -79,6 +79,7 @@ * 77、[卖萌凉](https://www.jianshu.com/u/5e309e5486c6) * 78、[有赞技术团队](https://tech.youzan.com) * 79、[Lewis](https://juejin.cn/user/3913917125896477) +* 80、[无夜之星辰 ](https://www.jianshu.com/u/4212f351f6b5) ## 高质量微信公众号 From 7acfa12e1cd1771f3b5aa2c2c670497627ebacda Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 10 Dec 2020 18:51:32 +0800 Subject: [PATCH 350/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 4 ++++ 1 file changed, 4 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index ed4398dd..25b2d91b 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -106,6 +106,8 @@ * 99、[git merge/rebase](https://blog.csdn.net/kuangdacaikuang/article/details/79619828) * 100、[响应链的应用]() * 101、[GCD Block会捕获self吗?]() +* 102、[Bounds和Frame的区别,改变Frame的Size会改变Bounds的size吗]() +* 103、[Swift和OC的区别?类和结构体的区别?]() ### 网络 @@ -154,3 +156,5 @@ * 22、[8000W个字符串,每个长度在100以内,要求找到频率最高的前1000个](https://leetcode-cn.com/problems/top-k-frequent-elements) * 23、[利用栈结构实现队列结构](https://www.cnblogs.com/lisen10/p/10892546.html) * 24、[验证是否是对称二叉树](https://leetcode-cn.com/problems/dui-cheng-de-er-cha-shu-lcof/) +* 25、[统计所有小于非负整数 n 的质数的数量](https://leetcode-cn.com/problems/count-primes/) +* 26、[硬币。给定数量不限的硬币,币值为25分、10分、5分和1分,编写代码计算n分有几种表示法。](https://leetcode-cn.com/problems/coin-lcci/) From a8022160de78a43a776ac04cd5432f753b9101e5 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 10 Dec 2020 19:25:12 +0800 Subject: [PATCH 351/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 2 ++ 1 file changed, 2 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 25b2d91b..ffd32ae6 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -108,6 +108,8 @@ * 101、[GCD Block会捕获self吗?]() * 102、[Bounds和Frame的区别,改变Frame的Size会改变Bounds的size吗]() * 103、[Swift和OC的区别?类和结构体的区别?]() +* 104、[pod install和pod pdate的区别]() + ### 网络 From 892a8984050898dc1bafe26a3d177486001d5151 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Fri, 11 Dec 2020 10:40:33 +0800 Subject: [PATCH 352/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index ffd32ae6..1e05dfb8 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -106,9 +106,9 @@ * 99、[git merge/rebase](https://blog.csdn.net/kuangdacaikuang/article/details/79619828) * 100、[响应链的应用]() * 101、[GCD Block会捕获self吗?]() -* 102、[Bounds和Frame的区别,改变Frame的Size会改变Bounds的size吗]() +* 102、[Bounds和Frame的区别,改变Frame的Size会改变Bounds的size吗](https://blog.csdn.net/weixin_33920401/article/details/88027725) * 103、[Swift和OC的区别?类和结构体的区别?]() -* 104、[pod install和pod pdate的区别]() +* 104、[pod install和pod pdate的区别](https://blog.csdn.net/u013538542/article/details/107932186) From b962c68ca0ae141bc3a3a2ec1c984221f73a3e40 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Sat, 12 Dec 2020 13:34:13 +0800 Subject: [PATCH 353/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\351\235\242\350\257\225\351\242\230.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" index 1e05dfb8..e0298525 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\351\235\242\350\257\225\351\242\230.md" @@ -109,7 +109,7 @@ * 102、[Bounds和Frame的区别,改变Frame的Size会改变Bounds的size吗](https://blog.csdn.net/weixin_33920401/article/details/88027725) * 103、[Swift和OC的区别?类和结构体的区别?]() * 104、[pod install和pod pdate的区别](https://blog.csdn.net/u013538542/article/details/107932186) - +* 105、[哈希冲突问题的解决办法]() ### 网络 From 17dbf8d92d122b671d9c36349184e0ec2fa3ac9a Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 17 Dec 2020 23:27:38 +0800 Subject: [PATCH 354/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 2 ++ 1 file changed, 2 insertions(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index f87bfb89..a66a717f 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -63,3 +63,5 @@ * 59、[有赞webview加速平台探索与建设(一)](https://tech.youzan.com/youzan-webview-goldwing-one/) * 60、[iOS 网络基础和网络优化](https://juejin.cn/post/6868945803856052231) * 61、[llvm 编译器高级用法:第三方库插桩](https://mp.weixin.qq.com/s/RKg8f6B2jSNuFEImtMnq2Q) +* 62、[iOS 性能监控:Runloop 卡顿监控的坑](https://mp.weixin.qq.com/s/vMRQ0VuHLxpaY9oCNd5G8w) +* 63、[iOS链接原理解析与应用实践](https://mp.weixin.qq.com/s/_3WXnDolNICs2euoJph44A) From 50128aa21d9e15cdefbd1f5df764438ab3e581d0 Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Wed, 30 Dec 2020 11:48:15 +0800 Subject: [PATCH 355/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" index a66a717f..1c9e121b 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\345\267\262\346\265\217\350\247\210.md" @@ -65,3 +65,4 @@ * 61、[llvm 编译器高级用法:第三方库插桩](https://mp.weixin.qq.com/s/RKg8f6B2jSNuFEImtMnq2Q) * 62、[iOS 性能监控:Runloop 卡顿监控的坑](https://mp.weixin.qq.com/s/vMRQ0VuHLxpaY9oCNd5G8w) * 63、[iOS链接原理解析与应用实践](https://mp.weixin.qq.com/s/_3WXnDolNICs2euoJph44A) +* 64、[iOS开发--我与面试官有个约会](https://juejin.cn/post/6908303868086452237) From fdbee7cf5e18a4a49a42002ab16a0ba108f02b9d Mon Sep 17 00:00:00 2001 From: wsl <15324956576@163.com> Date: Thu, 31 Dec 2020 14:59:59 +0800 Subject: [PATCH 356/356] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" index 3c126b9f..fb81affb 100644 --- "a/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" +++ "b/iOS_Tips/DarkMode/WorkIssues/\347\254\224\350\256\260.md" @@ -151,6 +151,7 @@ * 11、[有赞webview加速平台探索与建设(一)](https://tech.youzan.com/youzan-webview-goldwing-one/) * 12、[ReactNative iOS 框架源码解析](https://juejin.cn/post/6844904190385487886) * 13、[写一个易于维护使用方便性能可靠的Hybrid框架](https://juejin.cn/post/6844903733583675406) +* 14、[今日头条品质优化 - 图文详情页秒开实践](https://mp.weixin.qq.com/s/Xqr6rQBbx7XPoBESEFuXJw) ## 七、Shell脚本

03m0W9-p;;K2 zs*=rRiJj5t)z6&;Hh8d93CnW6S{ns`B?bY%3l@P>$sn)xy=V8x4GR2ME$}#+xrh80 z#1R^V(?>rh1$$iRpBYGe%~Ws$wOm~INGdgrY;llHk`i>GGUDAP`cJyYln?R9a|nkz zyzCS=E;KD*0&q+{@)d@qD?7m--;;2<6eG!CaHl;0#mi48$nYy)l=N?p8~s0Ls=nwa zD5-q2lK3h>3iwQ|=y^#PJ{k)Ro1smys92q;;00At+4Tog;J$3&YHnEJuD(H0Whnm@ zn#V2HN818KnDr;qzt^>|y%U;zXh#?1p-cGC0sCTGGx3ojF1!*X#}+59;ZC^ibv3$D zEQu1tY!b4v4B=0L;ZGK;fs+>`VUp*%#IA{^C?d0bvKwAqk1>W#~d!w4bG` zr9&{Nidf=hkR{~Q{seKm2(t(FJsrJ-B2?SCQni?*YnyWArUmM&a#`&A;-&X1h5r6M z1`dS7R&tRx)B)c0uUxY3KARzz5Fte#>TlpjRWGrb3}FYx`p8w2>r{5@@tX<7hC@he z82+9`@KieT6}GE#902d18zTfKJ`D|?!QhtsY_pzl9X312u>;GxkS6RwV)^-600u;t z?i#2mFn=5VRVT!CNd!PBAIYrI`iyA9e8(Pql(ort~3Y;zbNf(jXnw^`Fg ze9_yNKv7vR06@j5$skB;u52%0w#rdEOJ77C!Q3)8XLXLN1dLu==;-i^7 zAd~h5i}ReWlfle93OlXm9k${av<-hZp~`TC{Jd#T`{%{Ak ziMcv}(?B&N!2F<-6#n~en#(;1QNMr7t~jSR$lq>tbLa+i?3FOPmW5n2jt-P=8Oj^1 zWv|x^0OzAfze)593Jgyv8sc`PkeaUS88I&{e1M=g~LBQ42aH(@UI*X zRK1PnRs}7eMM8^O3gj`@dWB!x2{Le!Y$#l2v~dB~pL;dLCd3w@PaF4>(J7LHmqH41 z%O-XEGme_%KcppOi3>zLg1?F9S{IbJe@~`rL=SK>6`1=RKz9I{EMtFE^8had_EmEk zHS4FAK+pF8v;h&!&`kHYyaw&r!UIoa!eRuhJq7ko6tI<`wvCHbq!&caDu`b%kmDvL zMYper7Zl20938mQAP!gAc!%>iGJzKm=j|<$0z;fL*|kkqzCoVVAcFd0cjBa{!1Tl} zs0_&d8qD;Ml85OJV8SY~4`B7s7eOl4u{B5w`rFez1qMzYx!>kgTSp+<0HMiGn78i3 z`m9VEsr~Ipk;d{O2$o9HXLX!6y>t#pXGn$E)yrC1QbQ#g^`C#^BT^O%!3_<_n09XKdc%c*fYe@3eXnK33Kz~E&&DOE?0CQ^L)DRa$ zR$WC?P=7IhuMmD`0D&8enmBd{5*8>xE_d&&zqKHCGnKpOT(89Sj*B*Ke`Nt<{KbiQ zTN-89ZWi$G3Q=Jj4X~g~p|duby`ukaO!=Kaj^H&vt&FSEzzhB&PcuL)@S0JuzcZu5 z714rDldH;VZD|HzhC5F8O?Pu6v^UICI-dX z$&N!z2Ahw(@D^DMaqso^Cb_<^uoJRM|IKJx0NL-;9i+Rm=V22EL}~iEWRSrKo@0cQIs`Ph zt`vHA;`c((K}Y!lD?(Y#0Km4zbxd42A_nRaH0XKF{-BTs`ElkQN53VwCYlzbcRhF& z+|ldduM_@iofkyZZ4L{(G^F}d1v2{EjlPgUemR6*iu4IEcEC +6EY7dr56a7qsy zDNVa}!#ghJ=yI;?IR-lb7MH6rk}MG1_$mTyzj#eiZprj1hE9NZ{X~{Vv-3*)1Y}`g zFJo0o*wFxs6jB=GozTcic{8J?j+*^#A;4L=VQ;VPcgmJ81NGTtp1yk%2+47r5<1#+ zm`@58enOGVL6=pGS&dkQqEt~Ae-Vsl=a82GA$J-xkOdLEWWlRlA>xF%Uz0$vGW)Ac z7Cr6LNFTX)f^4-V1Iz|715C|ff14q37ETiH?-5vm+#3JoBycxqF3QnODJd})KEiT0K&Jc` z4b;Kl(F;eejSCB2tP{W88447FTr??z<${PcSP&SX-qX}+2?cwF$GzbeC3e5X` z7F)@{vz6~g>I(K77Jf4H0{Kcd=yWY>L2QScwQofYU5M;a678hpbg7u0796DZxU-<_ z)P$zV{E)v-ATVb(S_T>LhZ0`R_cg?e5G06riyQc4_;~{I#S#HH%cyNCa!9H{cZ9lRc;1SI*pTE*{O=PlGB{F`aWzhJ?Y{(V?)v*;P$2Y1ja zxB!p)zw)I(8*NIQ*RgOG2)Qt&f4Nl}A+bq01NdZW#?!ND(wF%3&F*mMp%od~+fyXa z7YztQQWY4`rTPH6_oBI`@K@t5w>L*P>e1$<3U97rToLT^m!CNr^+tQZ{462)dvS^&rXtY-j4G7m8mz@_+eJyHoy*a0x;oToGCnYeuolV+5d z)?YIK!JZcDc6+D23xI7YVO12_N*(KnXYPLx3TzmVDIVECk3FxB`NX&3%x`%WBej5nXk=dAG2~rb}zCE}OBPHP`~#Dl(S;LOM7j%8XIb*-+&F4f%f| z)$QkU_*H_M6Ie)ZOKqD~ znzvVD-V_p-*ymd)bm1%j=p*X0!25F#TNC_63^@^m&|emyE*AXrO~bDO#Q5e8Z<8=C z>?>@o8&gPH2Q7Js_*up(fDLMPeOKd!)a68Qvhz|;KP8}8g{3=aJr1mY>J!+=|bvnjE(&WqT*MWbM8>ET7`&Z z1W-Amvjoj?{fi&-{hv3`YXE@gdVoQBJfKij`HWP9D@wRts9Z2DR;efhqbV7w1iuC) zID*?>m|QkxvrW&2A1XsJ$0?x{$p|c%q;F<)wg$*8|4xUQvEuDimjD>P@J0=ONPJJR zFXLOeqmsaK>=`zw+ds`HbfnrzH9Gr_6DwSo0`Li_`M!#bVF+l;#8_ZG-{HKnpu(?3 zlZy2@mo_dGar|mvPkK^lKB=T-tRTp;%USiC-K3wA3zNuLI?OhCEr1IEzX(=j^43Kv zJaiLzHNIEds+SX?JPdSlgo^7YmdB5*^K7^~xp-pf%N)j+N#GZ;2k83;H@s;mr(oQe zWexyY=s23_YFrv?ONZYjru|eSa0XWal_kCiCEg9TsydY*#=F}rghA$gK>^t|UCCL5 zl}Vppa)!MywIKdV`2L;&kk%3R2q;F0ibhW`ql$Gc{ddSa<@3pH5=04X-$~7)XI-24 zqrIa)vZkS}lf&)h?Ymhd${^Fc*b7Y_q#Uschi(zG$ISt2N}lA>bGjI&WaJ>D2>+EY zc==fbvK_G>pRQPj=s3rVgoB`p&dY3aI0H8QELuGSK;z~iYe9s!+BjOk>Hzh>ync(n zJXosvok~$BVM!}c1&{vH5E(cHI}$pH3nvS60OC#lps*5bcHLmUzROljP-oEJ>2JK7 zH&uZE03ZNKL_t*Ej7*OzPzv7^O90!8Og#g*+D*3RpLUmtbcHN9QSLI%U71fC+Y5E8 zE+BH&)Z2?BWACO=M0_+?6nDF!VJ0nl%b}D0D;tLGv`s_72tMd_Ht`dstrR{aE8UH; zH{!zp=2)*27B^h_N!DSc=Qh}ClDlX}-(7>&6fK5`cZT*WSKD`G&?~^T!!AVPs6qGU zM*HK&g7YF+AM`Dt10h%hZ1~>}Fq&)*Sul|E?B@(W05*RT=sf_c_ZuG|s zvNuqh{M#!d7q)vN*WIN9zSDPn)Q^SdVhZxlSgBQ><=|S{#ebEeydWij_J7Wt$OPhL z;2;z`q)(%KpRexjR^CBv%2`hO!rbyNZYb7X$Ta1XQb^p+*&7e~4)pctkAD}SEYGaN zveuEF1;tVrldLG=5$Mct@>Cvjn1e>RLhHUQNddLLL6V;ias&J5wdo}A~z-vS%DO((DB0u@7L`53m2 z#=O^%ivue_7IY*xm;^r@qc2*}=Y;)4w*03&lJyq41akazlu+KNft$=|7E_M!3gzL? zUIVooFRJ_>5X3Whk^O}Mq!+=MCeq9cE4Wa-wdjIo@{UaWH^}{>xDUhaK8|vzuC@Cg zxm@<^mU)Ck3IVgoa22oIwcs!HS6`7U@I$fJ(F}Z!XnxUK$>&0Lwp-FSh_7a}JOXgM z;~xMspRaTeGH)+ZMOTc}YLPOlpJp4RSzO-!-XXuC7GJ?z4*TAVL-s-xUPoUZFQu)x zcx5jdj(DN@n}yZgeTIL7?}3jObBE8t@QT&Za0!8l^XpV9>qa-bUm$O`DX%ny*m$at zc$GwJ0Kr7Q7GXj35A4|5l_*4Ci2NozU3c2BWb6dX-h*lIYsQ65sx-XVH&`<}FO#9H z`~L>{)d5fgRr?^Y!dKBa7kb$+Qh5*xtgr!U$X?H+uW%N0_{2Y(0ixLnL$?O|8qjgG zKYcdKjwe&{nr!hSUu;endphAy_e6v#20?@lE4DMTNnj4ryWC%G6Z47hc8Pi8#Pz42 zp9OpB_ap#RK&!vgAuzix!YyXBD8{w!IT|%PkZ28B8v$&=(gG$HMD~ZM#1;d^ZUiny zpA01OSjcLujU&>wR%SSF5Ps7QwJ0cZVcBoq0f1T!+Fl68SQrB$NdeSxVLBuKoCF(- z%6HYhn#eCFsky)XYbrcMK|xG;lX*1m=e|z6 z5o>^C{ptYzdu9~2+|5)$p*n`dw+%o+1g|5G(K|3KB|^zipfrGdt(LVyX4w8_}cl*#`!%GoWvxuTmshr@lF!~g? z7Sy7;VHv7GyZOvh; z;?@*VS-|!u7CwmDrpg!!84%#tVvx3xe@3w2qJD+?TkaK8tYRaDXN5yaQhlN#GkC#X zS_mH&EOcmwFFlL7yW+z}J}&|h!`ZE?lH>NbpOl|Ti+t7mX5zq#D9*mgBPjyq9(t*Y z>m(~*aHI9S>mj4Q%WTJBZ$I2YIMB<`E^DEc^bHU=vPc$3>pU)77 z*^lLBdkE%84!HQ&t9|5w3jA>%@$5qnc7U&l_<6OWd+I%kpyVQ09ts`eyoC7yVOa=N z5d0$lo$^iosbibAu*DE$s^U#@7L4dQ*4M0z(W18M3>;Gc@xk;qV8dt%l$cd#uWh1NCF|LLUfqTr^DE@n@RJ(Egtjr@yh629vBaW>j}O#)W18@$xr=_Xku7rx zlI8GUrKp`$`8vyRRhLSwJvA5Gfd{Dnl^v z(E$md6o4v*q@N-X0fsNJ0I)4P#1~Zrq{9P$jlVv(F8(IeVk7I#L;}Ebi0ED(w3`?_ zI<{{TTWs&buHKhjIl=c5i@6VP#V!hFoj2Tz1rJSq4@{vqx!82Nw*UzG?ZX6W0`WkG zsQF6?7K!Ya1pv>q0)F^U6%2t8{RO&YsJL(57mus3+I_gOmEreVUZQ{Uz{WL!E{v%Q zz%nc3Nr1r%0X|+(Tc2b&4t-AZYChu1$=67GWfMOh+2|krNt&9S*(Rb&HND zsUGj6nL_cuoQ6*~OboM~Utc1@%g?UxadOzTuk5oiu%11SJu974#UHs47YZB=A_GId zrMUw3_tx`vajUiZr2#BG@be=)Mbt^8H2J5*5h28xdYuvfio)H8bzYkAcx_R0D%00z zGcIr^5yW4aHR9pL7ZLh`Q6U;1%lA@O*dmkw%Ct>l|5}12 z__)rAuQgjPKQ#AcZ*;rxW9`UIP7({(E@PI}CuIcVG+uV>ffH13dQMMF!V%MZ~RC4gyr@`T*%Ia7dgEQ9xCe>X1Wh`G_N|;(>we zc+b)U@ij%pKLOS->#qU}qOCW501>FD6<&5KK*pB}HNL3O;XiQNOk=69s17SIZIz$c z=6(xM)Yb)DtQDfLQ-*;1X{zBqs~icr2d+6UtMQl;ymw`OlAHwOSnbIJ_Hvjo+^91%B;(F;JIc z#(Lv%tb^14iTKwEE@?X?RXy|b5ImMch`LieX5)d3t%RYVZZU844_q4k;gvR;voR2C zVS(j{g0*dHY~2cV__4#YP5kWBw`UZ}q#mKCX7 zz#qQH@Rfj+bU}x)-H~KGvkQ9}&uv^l$YwXge+T8*sTN`~L-;k`310hL4Y`E0kML7AxN4zD=5;=rWMe7qsG zs057dz&^fEE7k#-WbJ6tA0N;qr+e(m*p?xCDx`V2F#;45%O`<%3Oh(*+%3eFOYARv zx*zd(VcEl!2i;*s(t#{7T{Bf_PZ3 zdub~W3*{t8x~=)%TjDs~v|ZIP-W>hWdaW%_GTpHSH#7b1e^p&APmJ_B43liX_$;;c z^!z66LuIs}fAkyigqXwdUTqG^vdrO`gorO8i+x&xq$A|_LVv!bNbs8l6;}|i3U2r( zRICc*29e%F^x~(}KL}N8H!WGf9InVS%!r+M7ByGygw{lX6IP*k z=x}-m6S@fgF8}V*n*AZuwQS9Es{92WT9S-NfaQz*b{%0O8c;WJIk|9iLm!I$S4<7A%Q36T6 zbFXNEDe@2mmp3ybl#f#Fths8!49`@8Xbl_bj^POky+rJ(9Z6{{}ztBH19AZ_-A839w}^BKR{P z13zY=f*lUOh9fr}-eYVcE79K#*@6Gx=|A>z0KR5r8SFP05B(pH-oyoI3_P-lkAWW% z(+;(kPJf?x4T}kz0%86A8~RuI2V`7u@+4mNWx;Z51BZW+B5&nw^bh!r{=@yTQQJg) zW%*H}{~8#;8Ykrq_z$qdYm({Es5%7v$J%5;`VowQ$1fPNBAa2q-12$KtNzVq|ltE;#dXl+WwT76SEepoOB3NZ(sEe_~ z;R!;NK3-!_hM)YHn&%pOU6940gAJ&O%fuM_JRlT-Of1I&12W{te4De%64ToGweog}sbv_EwKj07g;|u*q<`>~Ao}UgV%sGV$ zkR|;Q$iST2H!OnxNANMpnOn3#`nyD?00YmS20LX3y~#f)4PyBBwI=`WG7<8xhjhn) zZo<0!>mU)z@*@M5NeoZsB-wAhYz!Q)z)VjnmTb1bP*dJa97~93J9?8hqE;u}`LmY?Y2lNM!ogyjVQq{&u)Qis&cjF&4f_ z#1k$aW@R2Zp@wGZ+NNjhQj!w=&m^kD|DFCV_B@*GZsP<%$nb}3uMsBx{Ig0|Qg)Xg zgi*7n2>v(uuW`P3#=sXF9_sY}A^6$0#Fd%hXVozH7jb9j5RQn+56i!(nqxcRCfT1x ze-GyF0TGz~A=079I|HWZIpT~kwjnj z_{s*?s*Qx3xZJ4hHNI+}OqkHQzh9(#2f)3VlI}n$@t_Jz`Rh2?jz+=$fIpNlnb#0; zwpnEQg^2J7FfnfMV~R$^=T?Bps$wr`0)s9yv4MB^F`xv0__l!mviDLI9=o65kKVQdx5%gn)u6CCu+yl0IsEGMUlVeZA4r8v zCDc0+e4krT4yenIvOKsZ7mFD#>c>SW3{#X@w&X;J`hiZ!?@fHY$^R?;dlHu6mmB=Z z@~qXWwKxy~yLih1;Fsb%|)UTm)BEp=}`Mxw3!G zbKUZ|kmLRDD*YOs+Q*{sf#HvOXlO{3caN=fxmo1HBdm_DG{dhBzYfR@D=Zigz{30E zwBC)WjmyElL2I(2uFr_<#LcUD*}=;1&o1w6jHDq~`0cv45g88FtKTgM_{4SCV#=sO zpW)fz;Z)9xh2W30jQ{C?&LfsxeuDlAKzxFv7*Q>-1HOosGeTy)ko+u{e?#pdAeEFz zGW<#euk6V12mRII_ZK_v@CW^o%jil&KLju<=`mQOCdZ((5U|L9z#n`Gt0XQzau4V# z{GpYn_{oDhM^3(Yqd(-djFXhvyu*(fnC?}bobi9HMw~_1Ao&lv88Ck$o|DZEu*1%` z7TF(^`qDf6xWVu6eqn&(6UrI(Wo)w^lY5*h#w6r$P84&qwP+?EctD)_yl}{k(P<+U z;Qeo}&Kn0pG8|mgI>C;Mi$)13+gt;6+~C)*@OL3Q5zSw~9~s!0O^q6e9Mps`jk?~$ zTBJ;!Os~mC$%9nk=BH!i_3rX z&(tpTM~1)9UmN@(PR2MXD7?$R6iO0c$J&r5P^z>DAue>k8U?J$5(W9n>IfW4V+ zw6`SXH}C;|0Utm4MJd>a{>^+Yp0W+U68}C}^I)i$Kad4c`SbsVZZIJ_{MQo@O+N(i zbSyr=ZwEVyDvZvgTR{Pa|KoW5vZAVuJO4ly1oG$qG2n$@lUsP$>CgP)BsX&2e;o2( z4f5&N2elu5CD8d0{LBT+2eKfK{P~}tL}6xlZl<9k#q#qZvIpg7rvERZZP5Qi9R_xj z;Ey4U3l9G>`b(yN0rf-F<_1FW|H@Ql6au3TSYb!uV@MH;v~eNeAM1ZerfP@3kXl-s zXvWg=i)4wlwPV4mI_NIjogCWZgJtkf{XHA}1+YnS&MoCD{2}naZ}9(WxXetVZZ69) zupsM$Pq8^yg_W1KqFdGn<8S(p-wioJ!)pq;o7iVT+!_S`JL`k{u1(L;pld%i1r?-@RVlaOk zuuoP|B}6)ERxH9?80x!849%2W&I`$Su?qP+NSoksBD9GMpDRJgU8RyBQIA!N6>Mzp zwT_n0(@*qSozOias-c&tMy$y*4K-1(WWIOE(SN<{?daTm_i9N_Sbk z3$3~+GHM%2gZ~F;!pwb^pI5SUYshq74(+54*@1N`b*4zaI5xAHU;2Ve$16q@5-O&W zlJM|TLHyofmz?5eE+|kB+_Jb;xzUy%SsDHihDE~D_ht>1xynh$0xK) z4{Ed+>-arD=QhDtk|Oi_sugiD0=Jbd&K3AyB$vEV74uiFBW^Dzw!d})okqNx9@YfC zaYu+L{H?&N&KIY?vcnD?3jj|Hwc&?(GNty+yDw@P{!%lQ*s%qi%#j%48iYnC$hSrl zCr{1JRvb*Im9ZAaJ>TVnja0N>?QRUg-|{L^iwT%egSdMTam{CH&zpoW*|o_hvmo4O znEnoS9GV|5Su79H{aGS<>l4I|a`)PvT}9Yfu4ia&9Or}Z;$lY0SBiN_4q*MNCWZ$K z55w2dfMX*vNa#ZW?6~fT7hZ??8Yf9u&F=5dsjm&$pVMKfM@0xJgvDyZ75R7^Bzyev zi2iA66Aq)847O9uzm3ui2PTkd5nM5vOj3p|d@zW@;*d0iET0ZgG{%g z0!P>eAQIax70C>M-$WGoBGV1;;UJp`VbTieFsDLhEd~D z`ix2pEsf?YD_Bp(K(eI-!;@8Ok(h?PknG+#`sUF$oWnooEx;K1RB0(dmUy$9?0~Jf z`F}3M!IrqM|PBH+Us!TktZ_|t-~JQu~`gJS%q|TgsU5w_)5ZdrPw~U z{A?mJhe(aBOw@TURK zE@WjU_V5l4$tC@YBR|6(Dp8W%ISU&{NXsRm=qc=E#q^Y? zB*PE7h31<%QaA>B2<&s-0*n<3%(%0FvPng=Cfc-Xks%Ayzo?&2euTs4GOm#Pgi`Gm z(;b*rFcu9egcscF#8GBeKuB@vIj$EkUb5AmWOPe?jx9g7B+gmyXt4DO9M*!2001BW zNkl@v>z}MbUj8C6y*bFdpBfFiCYl2;y%cevk2ko}s^! zhDIhJKmHKDC0+sX2<>s(5toq-`&JUTA}4G%l}~fegd{@0qSQ$Q6b_tAEN$Rf&0h^vfz$jsjg>|4RW{8C+`eEq`-@tLk zB)p;%B~q+L-k?996q9ja4}J__oM2kBgfPvM1kyQXRX`30GGgZ*TU;%b1`6$9YHI@ztt-B(9&Y}V zhklyj4ipxlR>d4*`7im+h&OrY|Oe zxCrh(>XVf)77;yUZa&%QBU{o?n@?j>VLvcno9s;WRUE+oI>0cSBQ)aVXf%o!QwYij zO_al!MzuFqwi{KBl$dgwfx4o$SbRmp^B(Eny@eo5}M-|nry$cv| zQvJgI$<{$$P8bHRN-=Y6E6$v_p+R6q{tWn()tKHYtpD#mm~RIk|juUv3= zXew2kye4>boc!vGD)(tq|mo>j4GHYBIFFgn+taFPXtC9zmdpP%Mh0>)suQ2Tv4 z2j+tb48eGU{z@N;Pjxmzq3AQC#xxX%?I&08v=N_EA1>3!tsj3O#XB4yS;qknnjvXW z8MHr?-j#zbU^hUFloDlFwPHlBPN3ao7A%Z0mSDFArUNpX#FrNW0HbQ2?O(Te6h` z9E^tM1`OT5E`qK7!QG~#ma#o`-Jp&5nlAwZoUF`16SSQz81)+8(vJ?S%MoTST5z9V2{ zHx^0EB7lXEVkQcaqT?uV&GQmgQYqaET=*E#w6>+$iy$eH*CLj&$T8!j2~5AzxkDwO zbz0>1WuWEsXX<69B^?d~Ic53rDX~)4noe$$rr-F6%P@nlCc?*5IT6BR^_%$uS)pAdoByIfkOu zlLG%h%%1&4F;V!maOUjW!y+F(je+^ct0;i%Hz7}VKHf%H4oE?futyw0a6KwSDx^Fr zU4xc71pF-Dqp2>4CIB|%JBVKR0~H#WgBb^|pb+dpmNTJ*J*4MXmZZqKn7JjlDDhN1 zBv8O!2AY?RvE=lF#fe2Iu1um;hzHxFG7S*DDIpRfu0*J0dN%w}qyjDj&05MH{i;-; z5&PXm@K3_1_YAr&B!?k>`*8Z>2NtsFtrJ$sN`%Z5ZpLw5F{z8V7B;j{tnh-3egeSY z*Q2dpAP>G>jVUV#htFJj4#UE*sYgp3260eT;LlR+dvAKyqVR9|HrSp}F$p=0Oc|PlDpYyRxg7Rq%CiKeWR+3j1`mPWBR9CJ3 z&&{LCE&;_(8KS?Sy1%iyKl}-P;I6t|hB#hex#>d5F>+v}MYx?r);JZi&H8^Vf)o7> z0aSerUlun->NF^f23TAv1vg%p!IOc-=`tf8Dxh<-gV+Q||9xw-eS|mXJd80?Ci-SOCDIKN+4U zD>>6gT!-0Vi}B#&8B8(2Yy%`wril6*@MtYL4lBk;b9xuBjC?-wh%gik{z9F~s&sU+ zzs2uih<-><@zQrZGTZpYcGcnjw)_L+Ku6ms>xPRojvy13ZxwA-Z!=t*;%*pl*n0pc zXbdiy=x7~)4<+H~PI9^Pd2%Wc*9Tnz*`{J@3$_r&CrT*5$S=G)BK`?zD4>Ez)9SQh zm9*i=W+azGV zPHqZA`EUHI1!!A|J9QUuOY~d1BdEeyjMhr)6PpF$0|wz6;6-R3s#`#ac#s8241z5` zF5=OVWP)k}yGRbVEtaCkK-S45w^!h2vV)!)4KD!avmhnzU`CL^&?fV%nJ*rqq%7S6 zMBkFTD*B78{tQWSlDP4&9qNKHTEN>+VvwTROzq$-+s$ArbGA7!d-5%a&r;M-xGG9F zL;)mY$I8yd05})KNy`RmxgnY)cmO{5uN-)4!&RdT1(9Q9S~G9hVn%=!Xs{#V@GB}O z>`NjB`2jvq5nv9?AFn}=Z9tLZlSNo6;Pb0&K!r%w%}{`Z; z;m3ZZIqJ%6eUz?vG+pGF+4Uw>KOXEBOH?9C@zI#GjsM|;u}g6FDnK+X>B~wTF@z6M zQuAUeHc#<4=&4@RV(!5E3|qhGL1tW_IY&&Qt_vwaCpUYf8BSy=;x@>@7yDMEtAH8+ z-|Ugq59JubcoKkBw2HNO!G?ul&_!hGb*ls-a-nk>Wn>SH;{fDL!V~3VT~xo1i!t{^P?sgzcS%>!GAB1&fYs(cj{(O8gzYjV7NQE!pwG@0+-n zs3spAN?c>Q;z3sKN#9iz6nFD*a)uatFXfL3(9fO&h+YCRxn0lEs5IZft2x6tX_gpx zSQ^<3SEYLv7ANiiVgf*RMPuZqor2VhQVPQCiY#vBr76sXZckU9nG7OCE_{h51-^_` zD&!%~vdxg`LxEp&^Fk$11J>jK;Gw9qND*2b$v_<&H*6AH6a4W!fE86xl%v~0%~JH_ z0Fw#cp9-DqL3BUZM(-WDZ6#$AFXvj+54CopncYe;HF9vK4H!OOnH0s7mCPiDb{nKS z09y0_UNCR{bYS>O0eg|atCNwzlLjsKz~&BQD_|%TP^cHxG(Gml)ABRe!ERVG09{~8 z7+U_7X6wj>e$G2*e4oOti$m?)Pv| zw>bdqP18*VyTmJ3yb6$AY?XRLdlpU{4zlg|oL2?d)0O&;oq9=K6$)KBehTaxu7k-hw&vIPbCh?84Mrc9{CC{P*DPy z7VJtZ6RW3I#WR*LGg|UwY0=v_Ilzv{U`EoI`1|4&f(6K_LWoD*0qaZn zoQOR=0GbKHgK)72jDjAp%drTO5=n%I=CyN5;o5SIh(c~ebsVdn!*)evoVih;khcYA zV;7c$VJ_iI(OLFz0e=V&gSvQ4V`D8!iT)V1F#X864ww$+w?4j({tXUfnik+}xZB)7$X0-%e)2TlhBTG(JkPQHt z(Xc6uNMQ<^Mnql}SeIa;tiM{E+1MJ&@f-`mvMB9h!HxiXi2IyKX|p~r-5d!Ci^&$5 zwIDgRn1hKfSP(fdkryB`k<0a$2&{(oY`P=d1P#klJX{fuAQj;I&##9PkkWM14vyYR zfRA?N8uUp1%bimO5Zx5VSHersE%o?L&xS%p?$sr`6t;@E2cAL`eQb{uun2zdpfK&j ziu8T~Zc4+@mJ?5C79e^aU0IC_x{Q}(4Jm^}QNF%jIDoPIT`EoL8VO!u2Pn7>GZfZ8 zFQZ-rPpl&@z=J?y`4ggFiA@ftOat~DOpbs!K9~OF?Yt>A%l#s%godp45bNq{r5%1D z-t|_`B7$OfSn{J3c*W)Iii5;Lu9+{4y3h&o_0nO|!YLR}s-XuK97bIavQV~t5c91V zpleKRKg&CwSM1_gB#Os+vX#HmRvK$=tx6KcWbc$dZQO539+MGap!%~u2@E1$aR7xqg%mTOV}F^s1P47_2pX}erMsKXx_v*qFokUHuQn(QYlKc* zR4a;^OF$Mu{~W#l?!&r_A^i;eo}7}GpuWJ?BR+1-b!ucA>dQb!$~~hU6XHF5z95o= z9tMdmV9{|NoTmrMEhW_kuv2+9?nQHzy5Kf1NEPd>`5yaXTT z9lm!TR;a4^*1A2lZrWCQV?^LAV8#Dj_8&pkSRSxb%Y}j!G7|9Rq!*Ii@)J4p0zDqt zfUtQI%K&U8<&zLCNb}Ftt~0h8eqgtq4fP;Q7@e-nXn=%y@??Jwd8mZt;{{L3?#xW; z{xhH0huNjtM_eV7pjKzu9rk8 z8b8Ij--Iwg*c`D`KDxNt7KR`1tjWiluPV|~qFj9+F#e80MP^CB%sGW-y#5aOQhu=G z$w?&5nvl-85n&`)D*{HkRC^!LQzIDHIy<0xLjS{TcGTayqGbna5M4H$H3`?^0<7l>tU$au;WR zR%|z5s!a!YKa{={Xh8@rw;r*<67OB(CSbreQ=2#j^oxDL4Z(tfY~aOtv9h3bkGtsB zqSWCh@8A^6$%N#0BIdE5G^UUh3<;MEpv$SYZi?wqep*D&I~;sc_^27x(q7x+Df}6> zp{79iEr143|M|rXDK%7p(ih(AYP~#t)v2(sVL%-j-_MRQWYdrKlLxy(KfIZckAI&W8GsFMc9AV_u+%ijr+AX-f3N;}l;40BZ0ngff8d#^`D} z8X|(Tj~1v2w<=3rkzb#LOP%;@!v$*r{$TuqeN@gn){f-6J-u2KLdqrv{_+S(D=!T9 z3PQDI1CSiDG33?OHZ1sD>t$pI);oAR#I0Sa`GDj~(eAy0_kVB{-Rw%*4=xynz$D|7 zS6kq$0@8QkC^oxf>BXLgKq?d(foH6gcyfZaXmbVe#&$%dXc1Qq62s;I<^h0LlVo5L zs0H}kSSbjVT)^f2;<<-H8*UTz=tcg6YS8Li(rc2hs{`w}yj_8R*)6LY8&D3MxnZGM z{Jh6L!+e;pLJ4Ahv5((z>4#oXv(zdivma>(OX4gQtJD00pneJ`tl*azBH>#vXE z)wp9cjP`g2|H?WjH(bEXYdz8-*bac7TiJ{*y4aZ#;U~)=>+jfFZ=d)c34Zp$#jsrS zfO3#GjDHM2Q<#ery*jsYKcJ)^%mOQ62^lG-#dsn9|FvV}^YL;^&fW2;-(g`hq)DuI z8@!)q{58)jivKLn#W-I=ljuRQ6e6;A1X{Alva6Qf#{1WE0DEbK&L%5*%Z|$?YvBVP z-;6T~R0^o=u}$ApsW5b~;p4q!1K$2Pl&!{uWzP=zN7g8z%7vov(*tn%*FiDSSVJ40e$g z4jnjcXKfc3`nc|s*yBRO?z##sx_QzAjq2eYf8>W721uZvgTVW^0iD@yT7zHkDq`$r zibmA}|K~>e&IneG#+@&2tbkAmRwlH!JsLcdWnUzyE)4SG#7Z$}20_@4o;0J=5m=P+}z&SoX~9&C|065up<%9zrr`DI}bdP*&|s#?g>b^`aj!oH^hdyPQD^yJxE%AdJE z759)Ke;`HT$YM;(Qi6+v%uOtnk7&To#{m>WA2hQkc;Of`fo_1i2P(FGM=^yItc9Y6 z0UA>6u5rw_5p0(GoZ~}>w(IDg&l!&!Nw)U z&$GzR%u2o%X0}ho5InnpbO{I&$^Ahjmj7VvnXlZK zR4wlqI*5S=~Te`I{FzNt`2OU4bFBmv7P~?nXZIpJ!=<*C8%7U1%J24UkbTM11 z($}UA2j{u{BKpO_jrO8Y{39T4b$a(luTyzAX!~UFHYCyr*3x*rowG z(shX$SIMvZ$@{qkL=S@T0%X(!wGuqHOh{DDoKLMy2P}3e9mZe4If+I~H81?+z#@QP zNX5574jHymbl$@~9GI_$EX!FfIqdq+jQ{%m2EOi3LedgetD>I8^eT_nJFIkA`AZ}& z4AhhKUW3<`0MM%-%B&Y%W)HX};p)U6)~#%1(A8SZ_*Er(Vo^0w{4rS1o*3^4abVtJ z;|M@&vCS)|_=c*qeUTvB6^vjrcaRrlexAy*)hew#0q1!vw+tZ%!kdtx9T<5w*%JPOxu8{ed{|N$ zDFC?fYoxG>DOxfcy5dz9CtX=A`;l3yUk+rVkcW)Sp8N8mv0zCnPLBkRIeobzXmw!9 z|6+RDDW>#v-;yCSszay2RY}SoAl_vpFVk?bsvy6mfLDDBD+gK9m#&0ef=fwy6+~Q6 zX6L~&^~8G+(LwU`ambAF1K2e#kt6TVbXbb_N>2Jo`tLe-n*%B8>ZwA4Tx7kcm)>vaW0xDJ*^Dr30wwr zE@Z{Z6+{>z3;nI=hyLI7##G>td7eC8@;Moyz(5txOB951hC{nZb^yBVu3j@k>uv$;I%-B+Mfjn!nn?E*)PnN&2 zD5pOs1L`*nU9>GyUhHO@veD#>-Om>$mPA0>;!d75P9U|m1pu;P1 z-p%NXG11PSbch2kY$&g;He$pS#@ z1a}OV7H(8gq&G7-mHyh1THzNtQK&XG;-xbPbn_m-nHM)%2)^=o7~Og+O|s_5;Q$8Q z@&IHte+&?)JgM$=snhGAxw$j1GjJc9Td9!ITA0xyKpMX$le zF3$x0(9{)9l)}K@&cM`a-7OS96jmref^f2UzXadG7`aK43hjkMO0M*EPafkA@K+{@ zsp1E{UygIO+`zM*>)o;*NC8?u`X~`^QVCw`i(H~JeKoVwsIr|cKCF5~XPP$nOILK2 z8$1~xEJUY3+G{eWbCGud2|sh_`YrRl4!?o%Bl9rwEI%&b%h{5OMKp}l3!#>4g>LZZ zwd}b$$NcvxAx;ZHeDQ|!8{~9omknLKzB}++Cs7RhDQO=fX+>p_T(O*kF7b88nJANC zFJ`Uc%+#e6-vjW>bIZtMbxT*(iy>-diO|?|D|<(U_aVi|EVV2`2UY!Dqpx^cN2{LT zWy((iw~~RW9$^aEGnWBh*_BzS_ZVBRrCu}Ay##dl;{ZSracM$Vq6=UXkSp+bSfrTS z2&mPmdkKggSe*OH4y1K5tm-^od;C*-;k5z2?#&d^uNS|v0kVuLGRbiYEd_HaDF*U+ zQ_$nUxT}+}fG+jiaOQ26@@EC1tMGdP>q!u(3bUAvH5(DLYcGamdsyP%FN5XyN*$R(W49sW?@;5p_Y+aON4&=dZE*RF>m<98`h>bP<--T>w! zbSu(ZN7JZEnE{kvZfGHhO9TSADup*gS3J??R`A46n+S?LC=2u~atybkQ54mlZ5Vy* zv}vP4(8*Q{vK+E*+IB0!hL#2FH_fDKLo8(ATy1A+CGD@+^505d>6Qyb8b$_+g~oE~ zET$BC5hHadPUTcM(G2?2SSFH5OuY%~0u4JqF{TC#_h_tDg8=W+@O?CB2BQ|A<@>!o z+VgzEIw)`~)s;!h#M3Vmc%KcJAa4iJ8nH`o|t;m&3|TstBs zK$FPNzN$?sJO$WFTYnVmLP%KD+(_k;qTvtzA^;nZMcBUNDwQRHxbl_n?eHT->;PC{ zd0&>2ws+FBg}+!*_jH<|AOifwS^#>F}5L=Nj#{8e-4weoQ1*fDx59<)^tV7}iV zp7AJq1`0Np$2m$JUtEPrb+HlN^PP<$a-NAI{IiL&fe%?$if`tSP2-4yUmXA)`rMdX zdSk=8`m6Yr^VcDlt7r+NhYv0Otk^z%FlJXrhhKN)Q1l&o000&CNklV+H{Nr9q>3Jvz_zqm3kKJrfLVil25v6{R#+X~ONIQI?bo4{VoOLUhQS3|c&&9l|G0N1Hmp-mkR}bBh@P`AA zCd!Sw7zKU6$A#VwYD0ws_B7UdEJ&eU@C*NW6^T14zHNvxid6R97n~5HaIZylXZpi@ zitt-z8k6w9#op)wo^iC!xEG=H6;(WA^5o+bySKaAz_Se$`AWXS5St@}1t}G~xo72s z%RIB(hJw;&mNOXdMx+goHfcNjk+h9BcKE5&&fxz?LS6_dzQM_Yy>S!rr$vk*Yo`LSi%>!=5J^%S0aA$PR{Q8z>ht34DuH zEfH2t&&yXjk~11|K-kkKz6a1+{5Zvp7H{z$e>p3OW50cRDzMlvo)Y>v4J3=bUigz_ za`+o9eLWlJO+xj}^18a~mAhY=A-d}Iim`{yod#%rmLz)Nw}_PctI^G|ASzOM0;MG< z3(F=b%!PjYu-1VU4Vj|vnG@X^uBs-?bsWaYBV(!&2@h~8NLmISKvvC8M93!6pPtjj}8P#b6eaWeW_rLSZ_%iCHC zrdAbI=+)vZtoZfcjKQC=s(@< zckAFWj3HAKrmOYD1-}E=-QX*f?h@1TjE>I-yUPr~Bw|q6XoH4AY39{Vc*F-=zH~)Y zlAl9#n6E5+ZW&c3YT8IazId{vjUljbY)c2AhLYLKkMe{++uR{o(ULPO?^av^j}mb0 zYH6u=0Ffy&KLmza3hrP}#VoN7WHirfgsjntgtG%|oz5~~jd`6ee4SSKL9loD`;WqV zCQL`tNGl?;ayew;w=xv(iU3^!YH5nAKNrUM{7?D<@%NnM6bzio-M6si{Htatn=lvT zSaa~EV zr$2x8J;V&A$S>o#N$kHTvyX6u=BFvy0z$$FL*OcAAX8Jnk5Y8Gdx+fH1U<0d%Ti zcoHGrpC0`W`fDPfa_)@*a59tu;42@Zb5xqihm0_A9@&6ei(gG4sG-&$aD8>g8>NPn zJo3{Nt5r>htpga{jKpXCGDkF#{FMXP5Q6k&E%KhsDNLr;3_?^r;xoz*FKOwfLSdDad_6 z!k#GbHvk(0=e_nGGMH;BQI+0dRpM`3inqxc-q*jT+iyjyZg}b{J%|Kb>PKnpJN$bN@KpY~c9*5W%g?N?YIac>HVzfUE+^dsR1Z z;SUE8N?Ulc3hpAck%DCt&_2Df&S)H3o1Y_K?7)0+H+vO_f|_PQa_YO~Kd7Xzs|>(4 zrJbN4qr>(^xwLX-=x$(?Yd?w*o;PJ#M{$ooEDK22_{L28C{Kx+i{P$ESP}L3054_9 zV`U#^!Tdq6nSLITz|RsjC=ZdAjY-`*wyvy~tTF>r*+w26(2(&}EIfba30j@qq%V9e z2rWK;XcQLh)O0db6sJH|U1LJI& zfwlO%OwoZ}AAB ze3SCKfJ!Pf#Hf@V`(bykq$?*YiPzmPSn9xC;L|~z-x&5ppi;5waHMv|0~(bpe@^9T z4P|Hg9|~kWI*}LMT%&Y3;P@?mmo-@@o2o6V`^l<*jYd8t+5nxOmhXB;a0wt*R~AbY z%n!GBWU33o&Q|tuvMqfuGOKR>^Aa4Wah05qDBV4&*J5$GQqK)IMt?BU!;yX#?)V3ph|5U$pEr23}IuS1p#Ja&%B`Y(wKHsFw~V6Bog)&qLm{T zqWeakWx9Shsc5W_e%;TljTyOH9_au#=y4_p?h=WdB5-^Ow^^E6>j3xbIAI6uyUqYu zMOS8`*ia?*Iy?mJ%7$to>3}5iVVIw}LS}nW#mE%7XXoTOO4=LHmYib3tV$0Pm>$K@ zcb-^wLd^f7mTZZbYPGE^{EN($EswR7CKG;!*B&zL*hH^5v9QRTSI3aakFVdH*>#oQ z8^0}BUEDx{S^|sm#LOnW@M zz+zpc$b*Im#gMVK?CriX%7Mk#VX#vntZC_L3q@lAp5XYb4<&I@GE_C zy;uH2_!;p=7?1>zcxdfo>xJ@p4YhqnK~h0kgTg9zVW(e5xXn3dqY3r zFRvP#4a_5-k3p+Wvb3~!CZk$rP0|ytsa!3*UC>p&Bs_(2vU_yKLTwP=@@4bQ^Y?=a zTe*!?jOj{pjHy_pLEV*K?kg&<8q!EyZH9L(tfbw6c{8t!XYDtbZ$d>BM&mCxeL6L} z$FC_52TMNm>Ok(9mMC=LEz=89-soVpul?Ui^dxZWFnKU|<9`t~CQp~N{>XZ|V}1`1 z1Aw3B-L}mc07R+yuqbVe)^~n!kjpqpAbTI>Gq4k&oCu=>VQM;?ilmzX>qp(^infK&1*`L`95_idT!O9Shsw_f&Sx z!$$Xg;5Cn~HR!jD&d8XXwxrD;d4i1(*zkdufFR@k=9h(^ zRmm6mzn$bc0JYa994|6=&;kW=Nr~V#4AsI;=RI~8grJujCgl#~AiCP1CY&6%z{@`E zExUJU7ZoD+3*$)d($UK0kOyL9*IQ^Gw6FJP@D?zf{-5)(=S}uyGo0m7FbOO`TphId z6G~pT;jUmaJZ`qwR@`yuEHeN&PaGp{*Z`StyMUHNgkaI z4MK{GvQKfni5Y@4@)6R8meRS40WDyBamY3lIm12vp3z+BMgNd_1fT^8gH#gO^gA`e zV|U8P{yXVw9KXiIFyMwUfHAwZd*`JAFn0pui6tqItMa{(!B4<$gB?%0lb{%aYge85 zs-L^?jQ%Df2LKccJy^!0XeYRKV)bK9n3T(td<7B-4cni22UpdsCHIl3j( za#t#9uHd!ezE^dRIX&HkS1Q=`7BHM=W9rieeUaRM+%xl%^Um~n+C>I&QRoV_4m*GV zAN2B*&k(Mb-(v4N68L374?;E8t2o+-5SC~Df7AGJG3g&vN4T0Bmm3HDJt_c9=bf21j~UXwdUbcDst}tFwMN4**Xg z-0v0a_#lbTWpP??8~*+D5U%)MKY?G6#;;&t&Rh$OZa03LKryC!dGMbHkKDL)*WF;S z^P&iV-E=$LuLj5C(&n>kw~`uQ!>Q57Xp*Bh8uB)2bd$MJON@U1(1C689B-pec z<(=!=Bp2x_uI28F*V8QxdKsO)RprB`mwfiO(}tzd1#%Z{p7~!;8F8Bj<>i}2{y2RN zd=HF)@5@R~18UQTo(IN&+ig1I4OD($82kt)VLo63=X4cg;53Yjs=1*s?kC!L`v80P zn#TjC?vDG)*hK&*ZkWM=(=lw|R|dv2Djxvh9|O<#=nt3y$8~C4<WFGfORr_i8eD3~i?Bj}3#uoVf zi2@(|NVl?Y{4au(y=|HtdwxOdFeayd+W}+@*F4OI?RMQ2L%*qmjI)jU+nR00x;xu7 ze|?!*o_1@|wl0~wi^hvE{WQG`BPIhp-P>rvzi|vDW0~zBBl~-)NX~p&mIG!oLk(;Y zsOo)@O~2E+?mjO3d+BT7ybPaBD?h`3n-=G^Y1yZp4fEu7uNs}xfDXI!mks?suG@t6 zxO<SB8Yle+;5G3czK0um1Y*+Gum&8SW}!@8S8i8pQC0CHjQZsyJL^(zeDMZQm(^> zK=5OMpCj%x?XBs-U&4P5_U|}4Xqjve{O7DTrbF_M{~z&t#yXT1&mTw1n6}=bxv&1NaC-uPue_ zz#tPlU$EjYr7yc@03P}o_L>h3$6VVPtBZ- zjGtEX00jS4e%RKZG&G1MM7zTvX2Lh||C|(I;`e_OzfG0Y;RtSrYCqH&zKQC~8L<2~ zyWS(^e-A%0{$H8l$cIVxu4&WL)SVv@Aq90LKR#e<`TtY=eOlG{=)fW~KKAi<(*Fao WV2kfaZkx{l0000?)OopJn)>(A4TlsMJn>Z$6lFW! zQI{O504|H_MLGIC#lG?5T8U~RIQkTRyP#s}%R=W$9A~=*Bj%sUF(FC0nBOOfzb(Wg zng31t;1Y>D190KMQ9Rt;kwgZ)*f&%RjL_34b{DeM3g-hO^u@ahvN?h=D{j1MlsQK%0q;%Ls? z#R(|l)qn_(!mQ0cq)Qfp1sIfm7JJ3V)Mgb|CI-V{AnS?y@Q=VSyAh7vhI(~Ko!Y~{ zkzynvxf8i*Gp)QZ2=VEId1Jr0IiKd&9`cez!rt%6)dl7eGt0ug$?vLPJeweP z{ySPfUxEHbd76c?$9#U*fdL(!RuTYOIWxafkQ33!NcheQ!UlW_?5tx;*7@Gh03-+Z zuqO}6a~@FO-cRB9P9oLAfrtP)GJw4Yo`8rK;|_t-gTz~3%6ERKm=46XEV_pv+*msX z`C{b&{qeiC-s;?dmW8@Fo)@vL-r?sG{OcMa)dEKYf@hhk)zm|eCt%l}_irSyuh|(q zKUL8H_O``e<5@xV0;J5KYfAPjBJ50N8<9clq(G7m2SF!d!?86h@*nhxg@q+;dx>-$wOvr87rK z<_L%j;kAz*Grr`qLgYnBa05Z-CpZyU)2x@&EZBSpObebLd_;&@Ra((BEBMR;e9!>K zOF{_2tN`RLNDO+X!Z$2W=f+o36fWLP|6FBDv?N>#lP%eta zXK{U47sM4^$Zr~Pc1$R=jKW>IhVs7SI9@DouqXdEGPNk#?HmhvijlPV&>)3Z5o}j$ zSapif$2B2cJR>wd-Q>efVmhLGhLUAoeLa zMlfJnGiXbJLrwzk1J=9ZL}U?qko8t1!{B|dVw<83B;idzXYBFO+qOMLU5I^00;aGDY z#TGoJosUt*j0L{0ZjdmPeUB#LM5->uL;o?Zm~>JjidCnO$Rr7eOcC5ZPs(vhMxT7n z{jn(`Bq=oInq8k>yH<|)TWU4l1~Yng2|R*d^u3sJ-*9DHPKu|_k&5XJotgIcLt=mN zA&d`JFDJFN#k4d*?e2>|=2$HOxHyo_1uDS=PI-dvlL z_$VwZqKdDRlJ8-W--8;ge_tU9e=~=yD=dGKc{-tgze5W2SaYy#Bty>h`hC@19=wLJJogI^Y9z9n{-M45I+L+E3r~DII zAj`59os48Q$W+TiXo2E8qPKL8>c&{BEK8Di*|BD8kT?$lCA+k=P34oQ5BKVFTKZO* z8~0urHJMH-P6zHi?-%pXsXA#(tX3HeORkDUhkXm z{iI{tj__L-te4bQvK}2DL8I&gRP8bJsG(2Bhr1ZX)6Cpy zR{AX!DAdCXd@O!}=&6>y2-e*(km5+c98Nz){JxovZ=Hm!)J2dm-(Pf%ZFsP$uEMQ z5L}gSm_7)cwNWvB1@kO!nm;MhZKzDINY4#c{dzvX>N{d9k^3xlM`#ty(5h(H!Mp`q zATchhYsM7@v3m1FG!i8?kBNqBjAPR-KG+_Cs?dgnSo>rY*MNwVPRhq1IQ`nNUpdZj z$DpiSge#`_3p0wJI-m?)hqr2sx72vi`8Vb!N_j!_CBb)Dci$7iN_8RWAB#5i;UIo+-u34Fc25QVfrIoo(bejeI`!(*K;EOT zJ5|xJX&B<1gVAy?Ap?aZw|cZ8cKR566wwN$BSWteJfy@nhc>_Ctwl%O ze4ax%jjfy+?eVQJ<7O~vTaXUO$9U$M#VVWEQwqCOp{ElwF{4r|d}{j+zT$Z4A36`B zC^24`lrzP%oWOl6W!*JhiU*v#CFm@EH@NI~>8SN7Mj6pMK7?24I)dw`!6js<+8@H& zU^XSAohS_zIdR4|8bEmx)%@ZX6gk`X{FCQ-Q51t;Sg-pUUyr4MOrs%mO7=$6&{)WX zB(@UGUYDFz1wJftXB*4zO(6kC6mC7r(+CZX8E_T_+%cwO#NgEevB;?!ew)!j8=z5Xoe}&Hg zK`6Z0hRJ;$NY>FJtFYvY{cBalgS$33IFe}W`BsSS*fOcpU5&PX?hgwn$C{BP%}uU1 z=-^GM@Ze?E;{sP<(HG7-Z=|9Vt!iLLaqoxNR)1j_ssDA1(Lw3YWT#9}P12;-vbfEw zz--fhe`#hcZ){?c!> zooNwt7q{uMchfGkQRy-}H7I9f*W|Z9-boMI0U90*|9b-@?3Y4Iu5uAiaE5Vm(O#T} z+K;6$93&j~&*1L(8~r0eV<*iW`=)cgV$FMY)PaWk+MkBn72SX}X(5>PAk5m2 z&qFUyhgCO!Qumk{WwwUkBWlS8g-{go9ptUxf9*_RFQ5Eya>^@&MB{t)ljEec=d5MzowMJ;$ z?k9?~Wsv0;+{r~3Ec}V{+pu?2tECZK=-}r%DArMP%cQ*vU0a5|IJiwOkb^q1f(@^x zPU=P&%n77jD`NLfKgr))Ht?JfP38+Vm3mDCC_J;Yg9?e~dX}+pjt`s}9q&+X^5qL- z0dJk0&7UX9gy( zbcZf5*$!L;l?X=&;WnSsW2izSce2X%Yw@i;tV0J)(OhfDHk=7}wIkKMoiMVAzT_Dl zV(stW@!40)clQssU6?%J^2}Q&DHtpNq*emKU?#_-fb>m$l-Xe$sZH-##O()VaA_VD zq|$N3r2M#6fHf09qB}cbGhctg=s*+mML3B7j$|jc%T3xBhatATfrlksMY$ZgDS;Mw z;ICIwz16#b71kR;*6=}r|2lykSqbc2S#kDdb0Y%QnVRakXt7Rb@F}l%5S5I9ng~D} zVBRvtN(J$AX^3ywghO2C?;3X(?AUO1m!SAmSi7r&}MAi#aLy?VRdX;nyg1S3`&$<2L;_nBpbD5 zJhE2)^86#u(foEEKc?d@n-F%4Q2&O{9b8tqc_i2oAgo@b(v2WI%I`=3H)vh{x`G6U zI^PZOh@EXR5Ph_c7Xo>X=dp_KX^d8%dc_nlO@}$_%s60 z*=P!bF&_J3sx7w-5r%UFq&TPI{pNGx$M1d#g)bj9k^cVty;MbPN064Vy(11z4RB1` ztV1~R>9CL+ociUt7_@Sl?4GIhL#+{JgJDGC>jj3WAHrv2d{^#ILj12+B%a;gMiU8j zYj}=#I@QC<{DX*L2F+!~ACv7|a$2j9myl8B3p#HKwLB!?(DQ5m;c zdF~uVAnxeVyjxkp3yNLeh-X0Y-%L3Fa5Z*50IqvFjpwjBCg!f0;K)8yvoQD(SB+MoC3fa;aJLTr z88~Hsl`vam6`ri5^x7!m=I0?_XbNsQ#_)V&#o-xS%!^_FSZVzL!txumShK0vixl2- z*2m&CK{#c)jt@#vVnSDa9G&UUfFiVMWEX$G7uMN{29)!IbhzMA*`sz8BS8C=CVsR)f5MT#P2y zkCgkXLt=0@kf$;ga$yMQ;L5iTGj ztS`P&GO5tB7q5EVu+z~p^?Ph%#N`)A!jK}I)a@y@pcJbPnS!S|znLDoJmQHC;Q1*A z;?H2&bHm;|H@{3zEg|WZ9&k>vm=7HA`OpT)$|>WUxuT=9}Q?Z)N-g>K##rE={x zIoiJkgj)k?FoHLBan&vZ9F(R{n^m&Qt`;a@RMK2%(8&JHDvQKi(q`B!yvSgkdYGI4((20@3a-hfc^Ip1Y)SjB+dZo%{7iT5eg zJH~owS$LKx`x$IEynQc|m}h#YGpzbb6hqz6aPTq0Arz^S@vm7_UQY7Knm2W554i`qM{JNT`v#xY|E8mMM? zv{`dFGXK&2@|-JH2}j`4l`cl8wAg)t;n(RrFv=^wUJR-kgy3ynwMHUY`MIFFU}Vm^ zFGHQtH8F4-;4Huoq8Q7{Z`zITuX0Q9R>|Z|M)_r4Y zC7qrE1kXYFs9(aJtgyPP`jlp0UTXo!3X- z0X>qXiBf>(+&BD|NWvX&ZRr3uk=-FQEc)J<`o-p=L=YYaN+)dH1F540V#R9J?o*?Vg9rUR$|>^n5Fwg|K;J$+>K+w@Mq0@jzj%cH{$#aG`R2?(+wyQ+zw ze^&ON9-h~Z?_x&`^p)he=iw6Vvs4aEkfZ7FZEqpcgrAUpI2X^Olo)$g`v2Hlr-tLmq( z_H;U|`AAV1K=*a{YeM-)TLutr53}$6>yLv$uBQ$Ql~x zzu%eRs_7);hi2uEVP*80h^N-|mTUg8Q~0fGTMrRI>9K5y)u^@)5Y%;=K&0l6DMzf0 z0E`h-zotSv@k+^2JcM3N_ZaRGr!Q1(U^8@jy$%7HnQK;BwaiLDM^tEj8OrNmCdb@B z>e1oM1gO?ZqxG|hm5v`1F<=3J4DrP`#@c+O)+L?O>M*kcrdqc9IR;@BzRd*Y!tGTd zVvurNALnAgXB``Dq2SMb+Lh6I+Jy^6YpH4+@O8-V**z0XR{Va#cdWyCE_J#2JDTFi z2TGSC#*rdl;axVmcuyK*Vl&;Q@pi3s#lC!`$o->9EnHen0+YiI?NOFOyjTWdmZ%|M z29u$7oK_PrY0GH=@1D}4GOlJrl9=k~aJ;LQdxLtw0_g^t=ko)gEG0q-IucNw zIu-|~-;<6hlbTQLM+{4evL}77JsjHDnogm|-U}{%F=ZlRbOU3Cl6+kk-*g&)tUfa+ znrihvrclcd5LzT^iV`x)Zce4m5x(JydjETyB6r$_M5L`DCL>@;D#e8{k&tMqu(Q84 z1W68d;G^>;Zrd$3%mQz{Fr=o1y(;=u?XymDQ?NpWkbQf``wsN)!@VPG;m=JJP&d~^ zu(Kf${E3|!HUUg`T(n_W%hqS-Og19!_lrR{=06X|lh3pVA2#um7$Im=O4JVlsT(TJJOEvqmY00j=J-B(zjdkF z+#Vku(H|{L5>go7r!eq=oF}a1oG$AeSwtZxOs9|+i9P)VO>vyM+tNGB$r zf7Xs|f9|kYM-qkrzF~%ftj^>#1ahaUdo#H8ul&PW!fh(e!DOPCh76Zem+`C}glVs6 zEF%&hVBKHlhu;C0lju`UeNa0aoGb2s`*wp*Z!xUenBM_{Wtsh2n#ONV(HoW6Z=~Kb z*yNXIJ~H1Gj1{1emHw|&@Y<~$#%aH8WpbZ7eThC%gbGPZVko+baNf(BWxTZ? zc0(S1G^Sek)6&3Kw^1Qsc-*%flB56=|@K$l)_a*euWmd(dFw zD@GfAY9sMASpE;ZkLc$x%XDf8iN_ZWTY(D7H}iN^=qbFY{xTkuMu+T9{x0`$cC?Gc zD&YYSfn$YBBqA+40=6~o_F9Q5j7*HKy%csN-4+Qxy}3ngih|I4B?JmFf2Kpqd-hR6 zc2#;Zu4IdCEJfE=bs%z|`cmL&NYN)@7iMH6K$~}L;31e;AZ!T4KcJj)1ih$_Q}j>? zl-eBr3R!mov50@UR9Uy%P=9XXeBVVh!SInx;zHfsB<-_>Ez%z>w0IGwd^;Jk4;>~m zU1zvx{qDXpIZfg^***$|r#zV^Xx*3LgqzF%ioJ~ViAV5YZ%GFbmDjFu#A{t)s&#$B z*Vwm0^*Xo52X>6Vr!?U}0}dqj+TvP&F8hZ#Ls9cO$}{ciUZq z>as~uF2DcO*24H_86bo*%a%Q>#(YNcQIy}|^U^!e7K73O3Et|NYBIYglntEtb0DOsz}2JOx@gh` zdXu?S6tpy?MR~4OeK5_FnP#B(4`fs_%miq|e=!{bUA8IP}+G$nl+pIoB@KXoQ zji;w+7cjqkJPoF(5qMU%YBppL>gJlKCR`e#Z2tY>VW8F<{8N2&+lE_F3nA4Q>ckj3 zs_Q$S#e3WK_1Evo`Fi zIN~%p%9O|`!EiS!3cfwM=4D2I*UWjbFqvoLNt<*jTRC1rzYE0g76##C*)VPiL3A}o zEJEL;D4JzUTivObOWPPwz1s@Z-F1IDn3S$`R;Yx2SFa&JR9%!=m|p*n9piu)8gRV1 zhT@50+;))UXwJh}rrvhBbZMzK8P|-6vI>UaC{mGK#0ClVyZ-A@IvU|jzIC1ku6JuT z$%AhP1*ZDI_)kRcsT4q8{kjj{Bn3wzJUv}0jii6Gc9A(e zLhX-za2NpazGw$&0Dfvf>j^%N$KP?926*w{7fXPyTKYw;V0HZsVcrDCJtgM1Xl-q0 z-W!6|mIMh&yw%WOB4=(6zit5sfquR-A_3mjD-0$r{w_HmP9xyY#=28jN6%`0&w2N% zfHaczlb^|al8a9LX>z4z)?S3s_XQgbTSP9g^&wRbF)CvaqT-s#@Jy4a-M;G)hFa+K zMx24V-hb;tjhY4=KzW!T_t}_vdTUIwu5b$r>34SsLFP+7LeIiq-1Hvx4xT_x;iT^+ z9@b#ULzyIPda6GJfkx0{6<_h}iX!`m)8EiMj%cZ%m#yvVmOnS4YhtvPcIeAvz z#91x;_9QFfK%(Uw-cZ*LKaM()TfI;_JiLyuSyXkkq!J7b0&keUuA|pW z^lB*jd|h0KZ!2RUv@ZWRH|n6DqZA5nFZmaZu7p0cg{+ISKUr5+JkL1IX6YfkR{L${>`V z2xJo&7KzaA&c|_#w6HFJ$hDaUZ-&u*jsR0J9~qL~{Jo!NTX$^8r6E{Xk*A&a0HRlWHRmuBe8;Bwe<1klo8IP?~q1%vLToTe@7vB9$k5qRvgobQN;{ zIp<3EhA?k3xmL=a6t`a~fh3{!apXHqCL*QVbaTzrr>hdM>_}F=jx@by!pY8bJ+_T? znhFs@WA{uzL3%(Eep1<^G*PR^Xy2QsIhOkX*+kP0?6#zh+<7@DB2|0mL?E~1WO;>1 zLXijGh@|j(2yeGW+Eq6xu;V?JFixqz+LWbemwx$8|JdEzyfurY_qnyuCRH)=%*kC4 zdZ=``&+|lh*r2poe5CHwYNj@cVX~d~R1;l<$*>%QF8@+w?f`r& z-zitT^}0mmhZ}}$NbDYLQC&${zuzrr4KKHTWI=WqwJ@Xo#keh|+x*dLWsdE709KMYo+va1~l)4&bFRv@{_Q}_Oz@vTf$jLJh)wq zwtJ?>;t9%@-M3uJxQBLm>Of{gD2r9oqv-XJ_QvYh??ua8V~rpW(G%14X~Oy;B;EAEI`Y&jl&x#eN(rWh z?ff*MRis-_cR=Rt|9F|{N)Jo;el&DX*u=tW^sYqN@^P!Ef!!f%DsM$pi&5w5(Mn{1 zLAf$*jL>%-EMzd3ek@=zDnm4lih!LKTa49eYBP7fGRFSu)WH~rO5pCWy~oyE-cz^G z?fWXcQ)4+8*5!leeOWj2;;YX)$-%z_h+`7MtT}7*Q2403WTJ@;77EGUcFe^xV`2L9vvW;61~v$6G zKd(Pzy&=4uP2{V5beJJDQf}q+s&B&ZmRsSm?>k3EJnmjxh5RVb=B;bRr%De54Tb3X z>}e00Tsiw21`d_cR!{H<6NPbeUbu(D5W!0Vr&o<0W{^i&2A3?SBRUsb>91A{{@jQx zgzUi`oduPyM*#x^8=Xh2{J%<7@2h$~ighTuchaaf2!xe&s+C8BeYGB58Q_etrMP3f zTDAT&Pa0d~!-o6o_z2kS?>6_Z9n(v18A~P!l`3_kO*;&aFV`Z|0zsYqq8gOcH_C^* zOoIELZ;O*{hl$V-W5mq0#p>+oOVLu-@7Fqz&-jqA*6yQ0i59bsBVZs9Br=2K1k$7P z3=sXvIYwnqYNpbE4^#>{l)e>sP1%$t^Pxi(_HVhBO|?{2!jj76X8(Z0d!iI*!=xBC zC&DeT<{*6?MuatNon41-$YgqvFp<3!Q~j69qBMTX`J}#gZs!&MH*`}p_`-N1*`2*M z++e6sOW};8%Vi`@&p$tIN+f8HEo$$kOD*{y*~}}y(&Mz_aUqi&ieg#n11HX_DKj9sF7})HwaY>g z9IJewVZq!&n%F%94LhM}V|SGySIZ6ouVd(Jk{0^$qn>U_(s?r4L;10vAO1a{X4%yA zgfwv5+i7|w!G$GC6j6LOw={{=A_=Nfq^2~?0W4!fS2I)Bi=?pKluIO5t}py3V$jGw zn>swy(Y~B*4*6Dvq4^t#8CSZ=r{|iwlE@Oz+=ZFiIK22*D*9ps1C33X(+)Kx(+Xh< zpzN4SUM=WNS2LX*EfzZ|59oNk-ol_aPX$V_ht+!k__#;84x7!#(OUXRT>OI>l5O0~ zuZ)GTd;kRN7-t|l-F#UW+f(&iA!n-dgIvW5JLtV|f|V=PYVF9>kFZCA{;lZN==S-$ zbsNACX7P7;IwgP69m(Jk9Y)JxVHdG{ZOzFg7f=9;Glhl@R| z+Vf`xwtQgxC=s4&N8%Y~yxf;rMl#W_^|$Hi4DQ%7$ZJ_D%Y2;P8ZMtQN&43}cKO)H zTFsE}PX@OQX9f3%ESI7naE?jFN-v}vQHRSS*Lt@%eNno!9958(^_`hOZvm;g+JR>} zS$QTevHC0lNd(*+asbecze&~$3qn$%?2Dck9V?x+4DC)+;O+O#=VFBxZ!z($~U*IJY2&PO!cFsKmE$6J4*OSd-|Q^))*a5?yRu5ItVpTzT&Rj!~?aV z+nX*~2&DPEj(}GVpzWm>r-nhyeD1>(;65b7Cxr2}R&XvJ&FE%8D6>uwv}| zp0+bW#oMXf`xZleH=ecEcCgF;l#-*&A72@Al>Ry6SHl|b9x={@${k-IarR@`wEx{O zj{we)Fd1lP7V9SSCA2>L+|ef~-jDBAf7mb(E}z-)SzU6qTYZDXx$9XL=JE)3V{@y^ zdvZ2*v2pWoCC(6dGeh}mkKMfx{pLjGf=ZHrQW*un5%<8zH|~)g%v1}^hc|CXE@xzV zc`=6%6K0BWm5A>b;o_)V1#%hyK$oMMq>kf*m-rIq2*GksSag6#t zR^}&Q=PJI>KFV6E2;5WyH`^QAS@VgGhQKhq3dUBi-kCD8P;Vp0lnsy^!X7X`x#c(j z#La8$;RwbNJAV86_;VlBvR{&W{Y5Y3g2k-NVm)$(iSqc(Vf+^i8XOm2dCfleOkN3h zZ3FC&^&z2ObZ^*Gz(WA4a$g=bcy@$Y1f1UVLg#-gqH5%5{s6B38;Gs*B2eze%$YO0 zd}73Y`-oG$*FZLCWT1CdmFxQDtDuw9pwXLg_9o(Y%ZfKL81@H9k*x=0bvokgjz`t_ z&RAs8wGV;hIwB+T0% zv)9jTi*e#Kwu7!FHblE2pvUM3;b3v(;A)Gql4a1vTSnSQeGBmbymMNfK;h8*5~~p9sCM;AJl;oOC!HDR`PA z$zIDgS)b^ow-4!pfZp6pQu&nqiFm|^BhfS`q4KLfTe(rBTpj@TP%U6XN+DtU3Mn+; zO%V}RAQcUn1cy+G$1%IB0JoeS0qy}OIj$LZIMyYaQ$+9pyS76KQn*q+149$Kln8WB z0inxDh1l^sNa?d9?B}rn2@m0%IR_jTADj5}L*)%s{>`fhv&4~b@GuMn!wTZ$8*!7D zzyqF0;G4g77g7~S)G84r2@%q=eD9|1TtC(0w?ZZ`+zswOcG%)8<2m=8n%ZL8pZaOobI#x_F!sVqJB**^QfCw#D0 z90vvv#(fJlIZYe_TAsfBg2lU~8B!z%O*ZNdX&zs_q``vjP411t`vBs`XrSbZJqsfT z`v&a6G>0`Al3TMel{*MgKiuO5+|V9hmIZi=Pwof7!vm1(k48JiJrcPJM92G@JSv3w zSemo=`AG2`p=()SRW@w5`{HN-((T@Hx8fx`E0dOF0_rcud3*oeCEr@fs?<1GYhj0I z8rJp)HV7CW0Yq4O^djNg8U8CcyXMOcfD@a6g5@$YcT=Hi3SbiL8uOB8NKLc-Ub_7{ zTCu|!Gr-S=?Lbq`jYPl&O7TR2~X?*#FMFkhePFO2oNKZcv>VD*7X zGT2W$lDY{Z7_{u>$D#mvJ`jJCNkQLov(5W?wkqp)oDzQXUvOxF`!k3fPhcmHM5d;oDb(bcvw!1C4=f=B|Qz;6fQRXXRG8gN#Zu` z^n#xsdF>&j&VQYbeTGtECv%v84nW-tg5zp0O990}Z@sGvbo*t*gz3$gE>`#og3YTA zu!XlUC8mgRk9+O?l78A|lLyPfSOH=wlbYsE<3xbSdQ&vw<~~;4z7Nd!%=RJJuWG@M z6xUgit5J~{jo?55`zR?4yQ_K~TSq?d^?WXK?#TYPI3@NA_Ui~r|L{TwFCTVIoVopVS(hy63}A+far8f*f(?k=igrV!iB6 zDNBKy+k|A@hJ;PJvaMqQm;r1j$)^6Wg7sVU+!XjD*#5QrC0IMN;a^4s*b1;YR;u2C zr+|Y!Lwnc<;RmyZj&lc*-(l>dSZ*xE<`irjqVdPV1P4;wm@L?jh8qHI#~Noq3P$CN z#M307xy{5Am|j(bWNQJVyz%?0MAXL}FyrCHTfB#^xLUg4By>{t(|aR+B}m~v8)bAU z|7i8&LtGT=F+43T{(5;?Kb2f#+pC0{acw)eQ0z7UBmu+>?3-->! z+`q~|Ge=&KjLgCD*fAyGy&(^|+w-7I9`VhNYhaUXTQyxR*+FdZCAK7cuSzwxSlUi3 z4Y10qVygg~Pwa=b4EF0s*e7?aUd!>qGEq)nYFC>|f$G0-Db$6;N7u-apn0_6DddMP z?ze?lNVbsl04pzuEBq-g2kbGBzTLUH#LPQ!*m_Yb z0p5G?zg14n@Ta}Zbp>^`|6B*ZU>MexkLK=M?OTjOXA&(qQh!H#{j zdC#?45Ztlk$rx=h<+A|%ARX}V>LF#@uwy`OlUoJYKfF?3e2ibJM&T>rf!-vb|zVLW>qll}$KWS^$MO;|4LZ+e z`gR%Li|>XLSO0eQ{8La-#u`TExhLrS$1sY<1Q~{)8jG}m%h|JT{`?zfo8?>KEKeyO zcRk@{5VRD*UT1nRDQrJFvRMUs91P)l>^>W(l?VTXKm>k|f7uoO=A<+K?9~4^JtY_^ zGfGOX(WhYue{#v=su*98B`6M|Gqc*tBsUCwlu()P~nUY8!fZY+VdtK`<2WsK zMtyB_;;cZQVPL%nd(5YqPZ!Q!viXyIn(GCw{G2J~Gbq zg!9YV8A<88HFxd>vz3`T#~-?p@7&0Lwc5HR^ep&&1irO1y=)x0Q(l|kyA|mTi7-onLhu#`omdf!t6}$*5c=SEMZvEOkLo;bMA%BB zy&SLu#K}mbMASraWnmxEYGRR=X8poDlj#1?y#mrgXez4s3*s)8FBSgD;rwYwBK@R^ zc;-r6o43KE7My}xI_(t;ZulGR01H4}S|n$l#U45p!kMblDyqDmCxnzVBzcXgVXt1>ThxdCjHBL2M7rE_K5 ziib`}pBd+@x}w6rPxW$_;8>EmHTS2@OpDzExGv{9nL*^00)_couN~4WE?boZ$^3zK z5%oA*d9>HM6r`!@%(}_ps_v_#%w}_rft>%|RdxH=C#5~FN%Y)0|pa>L`eo|H|k>PG554U}iaaLZ6R!=OlPTjZ7Aqm@EunrDyo zMMO@?5TjmYBZ>}sMIC7g-|I`iJ;D3S*&YFtv~vr9eci70pUgu{`ge9If3lQh_`v2R z?eK45dk=K-^rVxx%Rey$G|=TJ?38Ik_%=-LaH_Iw#oN3capEFvY zHe$GC$*=s5lRH?`VJG>(zGP!EaQQOXt|+OegMP{@UsSn_dnzPvg!=7^FlXh0)6N(> zZ}8U>RxEFZ*Vz%Bmmn+wzjLD4v)G5kx(}}Ir=vLg$2gYf$Gn6eg*oNiNBmou5he1E z-+u3JNV1+(vb37zUFe-hxplOt(VfLmR$M%(4vP86S#8{Vq1*VIXVU_s`QJ$lI2+IS zmzH$7|2~8WMgkbb&^vcfSwYf}WXCS$I?SEX2;MT&)pCLfL%Mdg5m?VB_jO3e`z?hG z$MRFh)0{(MzpXeQ4P;BA4VQ=U2Ax;xntQ*I;gRi@PwG>$@al~c%dDVL-VZIpvaxR_ zW~Mtj%6wF{Lb-z8EuoDErbKElrymZ?Nr{e=9v_*a7Kz%~Ic@P>>u|JV4We{4IQhSX z<0=6Ti8fmB#%g}xS}bZCQ!Tq*jK@b~C061B)nXp3{*0l-6_J{z&b*{v6a*43J}jDy zyzTU-fyLYDY}HBUb{rd;NsPP2YSM;Z4PRpnMZce)|MoAtba+tp?UD>u-xzT#qPAi3 z{Mag=|M(u!9WGGX+VGo66Pj-w+`^94;}R|0s{YByQ+#G@+NrZek43;(BR*U+C7IOH zmw0oV4d~>;#2lADZ9UGJj+1&F5Ch{<7EA0nW(_9+3!0$G%Y06p|M75`^~@s())4u#9!RwP|=puJq$>$s2shacxjY4YyeF zySJ1t<;^E2O5zY&TtCM|SHUv%n}gF|x^!C2JD4r|r@dQAMMfPC(KNqCc2OOMUEWZ|X*9fQetilfdntH2k(7kuqiL z{G(YIkyL~1>@B)v*<4;R6O#I-dDSe{ybRP+qk@F1=>6(?$d5URV;-3G7Q)D4<5x5= zyk<1gG(E=S7n$jbx3L`xc;ZOqdcL&2tm5;DGH?~>UCDu;6K-x3!|E+GKlA!~ofJT< z07YLfv^R-9z3NL8IiO9bp4>FWBbk;M%kiGboq98Pzat!RPix*|;W5$gYVp-s^xI{p zS7luW4;CM5@R_|p+3>te7=E|0?Qfl!E%QxHlj*DEF!CwiA@|Goy->RHY`0=8rVsI2 zuPAuti|;bpn;d*%k4=0DA3KU?%Z7rF{l?)+|C_HK1* z&HPlpj7n9ZJm6?V%R*zdrGFWqN^;C7JFCHG5C`u3fg z=ul#I^U_Y!PVG=SKM(P4_R@zJ=%$Zbtz5EHEk?`>7Tx|u=Tl}qK5#JMz~HkVTLJS# z%7MlH7SSnD5kEw+iH1t|II5d;NFq$b=E`?f+*L?kvJMjiA8E}!bT};)zy^a)=-Ti6 zRK1$QOM(YtDV)7XHvbjzF#Ab_n+1$*Cf`E~{Vc&0G4NxIW9Ny}fxWRptSq5*>!_sr zx2x_!1*~Dj)U*kj@1tmNM;Ofez{2e|JIGDvLZ4HA)Jeyy2pH@5TRvG$+ZvDX=qerm zWj~TBlXf1!GR8SiEN|U|ylV5E@=Pp*Iq2P(I+q0CKHxjGlBaqM7Q9?4BM_suAK_^D zvLX48BHpN<84G>=5zg6@xACRWH^%jddin?R`|Nu>n;oO3D84kaZZUIM8J50!=`EXs z4YgvwsDTm5>uF+Zu~os*0b`SmjN!e@w~e$MOG={+WgO>ReFi z-_Mx$>&I`te{XUaKb4&l-JCp!SEsULszWkV=+)*n1Hkzs6&Mf!+XY(6KXF_6k`E>b zNR_WvScbhtm37_`*2CjS=eJP)cCbc7X;r(;8*h2tM+y5JMjciez$ujaRQ3CS8#nC*&alZ2bY_R`b7TQp6xT=;p3;|bL;yR{)u41zk3ROf^Wl}z@`N6JUdSM3g72zQ-Js# z-fc+bXzP;MKYIeL|9<`fJrTp+AUjGkeo^$^Us?`Jo47lLmi^YA$g!xZTvWfa)DcSp0A z89N@jH{EH&@tRVf{4DCb!7#FLc~h#Kr)?(h$CAzev;gNACp%p@>u0S~vCF1i2?&MR zU15pD=}sLqEsQy{&T~J%c#L=WT9UweA!Krc80z^jC<8h8Y_J1^;WmuG7wDyPY4n;r|5G16#2Bkqkx}~IJ6#g{KfFK=8myEP@mx4og zx1e+*GD8l-#F_J6@A>k4+}CsM-fP{zdp$h;P>!y2>pnD|9fVfC1yD8`GNMMk|I{F+q$!ZG@@+v}NmfLIuWz%z_ynXT%V-Z9~69tngQXLLb7``79;1P((Mk*Ur^q~1CQ zUWx{>z0YB@UK0fRPd>qAYU>FE(WuCC5#q`;&>ZWKO&}i@k-6>B`3!4w!9S}~8F;3B zuSNy(ri*4_3ZqCH*K-%6MsIhLCXh~l<47)M`EX??&Pou`}#){q! zje@E^27T#ADPDauH85EtZNrWe#i=t-Zlp1Kd7N*UOd@N}iT6wXZ>a zV1T42X37W=bqpB*?n4!K`9j1~IA4vVBh2?r1Uz8E(vVRIVZ`KR`mRNU8y`J>=~{T6 zW;FjPyZQBFin37S(+wZe6`EX+2*BLje^)-O8wt$qCf+nV+P0oaYg+v|a5~6aCO#hqY%WD1I7>PY=J^)lD z)ID(L&S1nYe9>69_zkNv&-5{5RqEYv0eqwVrdj_We0nME-1;;6$)xeufAHqnxow)z zCsBS=t}F5Ki~oT_pn7OxYIUB;nvLiFG@_Onze}$50beKFUsSyP&iAN#bungRz>Fa0 z71|azIm8^@%Kf5Vu1v-KDHC$1>P;Te?gP`-`#Z&U>*!0O!@z1TW8Bj1d_}}+f$D+A zWz{YP3K9?0n=-ME*?~Irc%|4E0C#rMCauyB02x)|m$)?C;#P|%TyKgT7g!yUu@p*H zS|J$wQoeKsR8Gf!vggA>a9TQ!p|0~C5n3k!v{P11%r-Fj{xfH|v>a%-4lb!W&N2B# zVBy^5Elnr?F^JV1skOfW^N3~n+hPZikhzmBm~n{A{)`?;rC$BW{G9ymi&D zb*Lzm1hMV|E}EXyNX~|G!n?-}w96ktJOSEmEb)xh^zTDR1M}*3DjKExCeqI39gI`# zXd+FEXD(k6nGwBvetFOXoJ0=L?aY!lm$!h{4)@mP3Wq5cZ&d=TTXZ&$kgj*lJa`y{ z-9dAkgFrZR4R`6H`T#nEr~ts3yBG@@V3X7#y(FrmV1Q9#2d5>epfK;rjdXN-TvBj)6wu9pKl)+z4_R%`TCf`o8`P7OgXeIA<-UL z1mW4z5h(Sk&6&owoET`74fxduFMD69z#qRe016=4Lm73A(`T((wYs8=?A)R%z>I#Y z(m`dfs_KYtfGDYuo!P7D&j!%v)oq&)|MS;R6r5D?P9ERe6fAmgpzf51y9UG4 z*r$wlQpA(nk4X2#f2e~ovT&G$(k%}Q@2p8MJzSD}ZKFU{G9p~$V{IsJ0y&Fc=3W}` zlNBQslSyWaS>QR@N1POL*8s+))_tja%h$n*6j~UA3}8IQnOwUll%}OU!PA_L@qFt< zBq5lKzE@&^C#?Be406VoMMBuft;;KvYgXdL533(PP_A_yUf$l?oQNYcWz`&(rQ&dB zA()Inte2J86t+O$iE@5Arff=QyI@Ri;r3TOoVE%?OOc9o_-Nsb{$)vYC}pWjWj_fT z_(u_RAxQopQVaS)=79s>rxZ7+J0evfFC)5&tw5%MT0k#xPxqo6S$j7#3I*SNCJtMd z?2hdJM-y4i29^0Vfni!F^JN0T4|ZV;(XGLE??->B7iD0VZx}c{2osb#S(GzV?xsIK z=f4{q*x;YE&gY3JEpiq!d(yt*oC~zLN+1kiXdr|f0~j!Rk0Z##>pwexKRPDHvtss>Ab!IvTyXr6rGuipcc`4HO$E0*y&49=Bsj*tM68 zCF826UcaY3oi03QM>x31xESikr{mv)B6oe$9+5Vc^WOZ+D1)Hw3dq!Y*A=t*MVj@@&_+Xf*J1uf=AQb;LMX~G68SIX614an}Guz zNB_WZ693R~zmx8EuU~F&@DEYvck(HJ8Y6dQF`It@sHP{9gk*GMPAy3SYQ^AV7GO|j zZ)H36xmS-+S%&pIK(3#KX5jq&a8^O+gf~;L~KmpaE!7>jYp^l>Jb0pX?wa zyPTmwBYKsJ;)U-Y0$Ao8`)cXW`$&E!G91^RSq=_MzZ=zOg3Y8mQbs0^q={@VHac6B z3d#4kq4-=T>(z!9pyI|RZFsCV?|Y?2{@Jcw<$WHJzQr~8C1mkKw4-iAnV)jBrTxp{s3985h$O}G z``gUAIQQQ}ouM0llHN3wOzPNHq@ymYD+^h1QXyZ^!IW)N*`|pzI9-8w4P|pl0?vt|gOH6mq5J zW{KC>S)c-KEl-))E??6d5Xe+)$`Lhe1LqUIQ7@Z4_}Sv>@;ccy63A91TS>4vu#u=D zN7DmP^F#060xGPGlgTKoIqS-xy<|^tbspOu5M2+I4;*Mb{N;p{NSjVvsvk+GZ?kwK zB+oL{VdvielqwAy3JA5Zdm(QQ@fH3izYP6*U|_?&$W$ERiM5F|XagJxe8=dwC5_ST z(S^%n{@WY7HEGP;xr5EhMB_$3g>T%RWf!2%+|~x5xAQ-UC1c7)92+@7ze=^L_A}3m z5)>XY$d^3hR7&Z@Jzo)D#xXfekVg_e|FmK((CTHiGu(N~Z&bW-nWprTw|IJl!HMKQ zi7u&vZ#kIFeZC|ple7yu`8xx4#Tk9UYlt`Nq zH@#rza}fS|)-Fi?6rzCLX*vF?%p~n&rfRHT7Lsw%?pCs!&uxHh7;fn2Dj}Ju`AnuG z#Y+2b@heMolG`(n&4sd^mRrf-k5uEi=&c0^6S@G!Kbd6H9^-zqfGm$}yhIEhn+|+5L7g1%>94_mzFj8A zad74UrfK6;b4?PAXfOY?HENrl=-c>hhpium^OEZR1Ax58wIBIFp#1Qd@U)Qr&N_k3a9X#2c-4*fw*PjZHj zDR&dqu0rL?3(s*1)@zpI=bO*x00|J%?<~WKt&`EQtzOh zl#MVs2R?dDi}74Vs^F@Pmpk_p&AcS!Nv1XqCW@? zKF_<{8_v!bH1EXklaX~3U$eml605T08Ik6iExJ682HD2rmfu|6eK|EBY8 zQ#BhMkCMH-A26YC+)824^<~hJ7;VKns_)ks>wB*aQ92z^h~56tp3f+t4-H}h@_{-0Bv$t)OL^W*a_gfc{U?Ra`Yj&8 z4+?1v(D!d1-@U!<0bRHhM*auSj4|Ks9ZV6lpzwPDGNL!TBf|HA_3kt>Zo4CHQVW1L zrFd2LP=|mgK6rp9>-#1v?gw`G0R&=E1R;%bLTb|&)bsm^nC^+1hngpTbN!4yNRt$* z;>?jngl$n1Otr3Mo|x}sPufW=m{bJh`<@VcXz*&gPUHves7w^}a~c$}@_+ScpaTkcf6T-7F(|g)?)qSk+|VT~j?K_r{7p+ng+Jdq0;0{qfJx~R9kt{ic-8Gt`g0u zlK&~+kKCQ&`4_ut!qWSh>S>z&ux}v-oUbPzaf=|QAD8+BI01X@1?;PLOncx_5At|| zBQvpFE`HvT=kDVyLRx711k910`kXLabkgVFgfoZ+8MQMAbfE0Zo@ucl!$+EeGk#GR z_SxkIaL1aIeylmMyPZGq1rBNTkYX>YsYhu~FiCAzncpDeTY8+N3?x+_?rHj}G|1~S z;(>9>vS0W6qT@TvnESc4Ii18~PTP)~K52={Gwtl+h2168b&v$?=&ilC(F1O;nzx2( zudz=LvfH{070c%;u$+)(ATe$P9r_}h`OQssWLts@Ly8ma{rZKeiw(7`Ugdp7;^~@6 zf0`mtYh?2M(-(!#VVVWf?Hv|7=pn_=~TgRZ_K4&yf3Q%A%iJdeNq{LK zL+s@CPK4d@;;otF>}uZ{vNCLftW#V;q-VS~db{bgMS32NP{gIsl+v-48jIDOZtHl!fSJ ztqpv2&Gs30yfu!v%=e{tC7S@*-zogtZx=@ws~u}cuHuH#pZ0v=2vSNzP9`(%=KF=*>Kc+ zZtqzx*>lV2Z80KTI6V(2Kxe*Lmh)S2cS)GpZurH%A%b13qLvhQgbY^}r&0>diYX8E z*NU{t1W|NpJSPVXcSiXC3@bcruddKbKpyMQIVpU*p~l-r@V&Gy0-c`;^pC|HK_q0%MeC}bJP{~}VTH4$rWDhiC0j`!#j>TjR2Mn{A3YI^z zRIheZ)BB5*PkrAteotmS>;qLV0Wr@QS#}ezvLbO7;j;Ibv>D>YRretW-iK-g9q!=# z*NhT~A2IS11hJ`J-H)a$i;E3DFgex*ag2eE+A*r@6rN+vw29rSYT|osPx$L>$HIGU77{nn z{|b-}ek3;oz?4TXGqO1O_9?w8N&Dztl!=u{?o|o%GL}LMBjj` zdXLq?iwkhwWFH$0LgCv{SgM(nimdSuDs!ltS{i?BOHXM!N`^H<5*2R5+B`6F^MpOQ z_`L#}gZS`VB~)TraKj6blOX~W51*@$0BY$j<4uj`hVyY0OXZ8lwF}|IGxx9tXqqV8 z!`c0Vt#P-G{TXway5m>921R^hUu?g&YM=WfOLk)#!6h^*A1`yAU4#3(DK9b~hkf8A z&XYiLY=^nu+4%Kckks;x=F!?6$L)s3!b8?Bew)Y?+yH9kN5m(dQx~^MGn;+^!K)=? zk)9J`8g;GI=pHTbu(`)|5Fa#PAv=?#BFJYbNhs? z8!64j=(qJ*j`IqSdoY9>UN=Pn|3MZYh1ZJ6{@chX?Z?`w!lO~X4gWwHXPIQ!L{pBP zXB>WaMTj40;~;5&yg4)eIGyv1(Sd-7o^Q6!bYfCaWnpO1^zO4{&D7Y9jFBs|v;>%Q~N zG&MP^oI8R^yMWXc{l(YbAYk=*^0)IK=esL|&fcbr z&p_g|OXuE0H#&f_p{GQwcF8&2vQ1^-s$;f!D4dePvJB|G@!5w-f-D=J?m8w$MH_VF zKc@4IZ_wkDADgG|m}yoKAV)o7od`ZEL@4Q+zLr{*o_A*RtKnfZ$4iC!D*f>9swxss zQ~IQ!O1&0pIwLt=qfF$RW@Ez6&wHVzQBqqKFYI3{D&DH~(m|hJS`(~ppH~Q`8&2!- zo%DL#2Cgz<)!^(i%dcesr>j>rCpIj4`<1xzD#l8w@i(#@XagoZ(J}8iJKJEzZLVaH z!!(~3RfRUdy%FTnyCWF@v)_5jq2|6`6lpWBP`qu;%ac{4KT90LRr$7V^qXTR9(jec zZ5Zt?#P}E(?`ZX6%Dl%m1J^@&E=nf4JSulC-!k>Yg3Yg**Gm2hBVuajzvC3A4bVH^ z48AVIb~n6PMrCOKbC+jLH4m*GqQ8QGnM1d^M*sWahB)S1$)x!^sAFElLGd|>5FfiI zhoEY;ySYf&j<#Q%O5a=mwk%RN=Q*DT`-Y3&;0CAMOP{>w+p%g~?w_tCtbILJ4~)9` zx&!LrGA@XPZvZpig4z4`T35yjl`^R2Vfl59zZ}18TC(s>EX*ctUQ5PatDQgtziw>*G2>;Z~tB0e_J>fZuPDW6w&kkS9&lDzRr z9OM|{pKNqnvdaY4n3SwxHjZ_i6R3P~+F>$C0yf5+2-&pAoMOs|J~p(kdZe|lis_El z==T?V(M8@Rbaa9%MJvf_lxUh;CZ8}qOERK1WM3tDHRXaPUb7(mgBCv*-(b1~fwOsp zHb=|zOhUdfzp;0>tb8elc!vqZrT@+T0363HB%D-wbXIw2&Uz?YniD^iL*2?$`2IPo zxQ6~{?(A03tJ{N4ZHWkSA%j(3DhjjbjBhd)W&Se9hnd~+d4s9}ss;8;>BVQr(AFjq z&KXN#8l_fS%@vFIE~zu-hT1q620xjdBuJq@dWn%*+w=jJrE^rD<+-V$Vq;d#7*OLr zQv7zF7#9{gez$aD|9@J5-;BUB<3BsUd9di?p=hoTP&sIS=wL*Ey{8qpbxB8N6J}tJ4#eSSkcXEnb{ec!*=I6_Y@KkXc?Pf$kpf_i= zrT`jGD()8$UQ1;0WSyJyFjJXy7g1KJ3f4Sna-Y= za=lZ>g2rCH|03a)t!_I{9~UH8tk{qk)L8-Lvbd0iQraQA;C% zO;?!zMHE?O&IfP06w7kO; zh@m_iDLem%51vo{eZ-E?m+>TqqnuO@!y#2C`Bgo)dl__g)Bd5&P>A z@UR+t8x=60ng|v~8ypQ|?_k(e;A32g=5L7oAU^Fs2+PD;1DzIO+ZDqX3#rE&Zt#x! zrj@ge+<5E(0y+$Nhzmv^AaFm1xo7~&MV;Zg>%|PJ8;GnV9-U7bMqg5n{BYYVy!BUD zEV1L#HIrB((+?~$+8i0Ga(!H2Y5KTp=4K+PmN2Qt_>0+|1p?+cr&kOmf+pEvUZGFW zh2e2!=Uf~vO0Oa2&aA;Wf@vZ7z-FGMeK=ur@h<2B7kqowhtsQ8O~9Gk-Sz+@rrB}z zurXjYXBy$ri-hl6g83Kmz`83n+HuI&=kJ^UP+AnDRC?VVF57^-K&jM4df z(yhPmKs^Rumu{>T)CGB(z=e8B>3t$5uQw9ztv2Wk{EB)1iVg&!!HokpuV}D#@b71u zT?2VPUu~c$t6Z@in()e9SQPO6LS-GPN%+DpjP~j1ZeU@%5c=-FY>_^netqmXHC6=& z?ZYMZI?<Vf=(6q_?RS2~aojuzd8z^$o}pORJK4F>eg`mg??Qs;fT%#|G^Y&sw5 zVeX0`SPI-S?5}YoY#TBU9Kdy%Vely9>De)4E4&wSe9(-h)5X=#!NLYoxad%pa9l76 zdam%cYC)s<4F!SVCujxl;&|4Jd=byLlA^U;=Tn;DXEU&S#HU;f{qHpV*%~ZpNSiam zjV7oL-6JD;*0U)a%()CXp)L?n5-pN1TM+oPLbl9lE~EK=06(X$tHo!@2;sfyQ;pkp zHWjoqx*l|4=Wm!JC=>$WzF{2faPGsEL-%p@hZ~=sN4>gdwL`;$<~7F*n+A`ItMf9a zR^tBNYj%J15hlooOTkiv{j1yjf`uYM7#`PzAJ}oGS6EpzjF0~ctV}s6YH!kZlgr39 z-Pk?30E;F(X#q4^8QSupWYKImTe>B`)iMET)oe@~4m}5!MF)XkkhcK#J4rOZTwI4k zeWnNJWz*>6@$HG7z)8O^)qkIy5od6DXav5WWgo`LfJ1u>zDEJ(^6HyjhTTWrMH=tna3%f%-cOc-Og|jJ($#*IVJFx!)%$B724K0UT6D70&bk%fvyC z6%v<5m?v9pw_7=u2G?AXPMV_o%(v*Qn^q-}7xmk+o9XYifbhFsTnuC$@&a~r06KCCs6agi}wU(c^V(mWS?$8&CI6>jRsfWQ6?AY4Bcp`3rBe*OuuIV zz-8EABoxm0=pV)b}#Q zD!4S2H-p~Qe`_NG3J9|};zz=^&9OY&h6!$|d>a zeH053<7x!FxZ#^?T>ZyTPNlZbXQli3E(u;brH5TZ3gMidqQw&@=JtO6Vx&-b=EIqf z?A7Uh3AdEhN>Z(&?Lu8h%_MB7`rdcrAYu)iqr&R=DJ1*&)TrhZ&IibGkHlN&#{62+ zN)HG9+})rz z8!fut=}i2;$sto!NjXe)%*w5il8>6KfFf9iW)YrT;}IYYBu9X`xh7nyYt-4 zyqX5N;S`aNk(Ow79nIq3wa9wK=7HDJw+1)dsK8ms_gOXEbu4NY$ckx3-mv5N(A8K= zv^C;P7PEZ0myd#UJjz+_x1~M?Vq9PWhq1Dlpsn_Ph@-;8iLIL(vWV-S$(cMq=bx{> z%NZ2uc}kq1&9@!KE-rc^U;LKc?X3%#TbG;uqFzZXdgKRil}q3-1|o7hbZ)!lsu_~y zDImjLZ+c;qz5PMLZs{9qbd2Y|@aQSyOAp9zo|sx;zNki9M{it(RwWe2Vs^27491 zLhp{mIV=JvW8fR8Seofk`{NDQwuZRrPg01xjYSyNVOSyK$p*O+^y;h+IPb5IH9Uor zVby@h5c*Ig=Hc^Ul|KuxNS}Utm-mW|3v}*D@+F5*XEwj06lbbx>??4@da821i%uJ6Aiell`AoXhbpNpBp`nnD=sBPd&}6+zWEpcASR z!qXeyb|tBfTLQ=5{&wV9=K&vw>?>j~T+g}MHuoSFD1#>%m;^1OEnYC}2zJ_zIjF)7 z9g+={WdCRphGPQevm@cAh`lwWK-FCPliW|1m0H-(h(A-1SJ(HjkI@HWgI;P=8_veZvfLf9 za!>gJ#Dyb=$g>n<2tT*xmM%p%F3p8YYXsd1rKH~Fo0Ev<7^uw$R~To}0) zVSS7kPe^BhScB;I^k?aE6MsY%Hm~=kGDF`ouRL&Q5FvgEd~Z9c*mK1w|agjZeh7kDM_ZzF2L#PC3l|im{LSx_1jm`J-*th zEcGqMlW=Y))$yysgJH(U>Ku=s{n%V~zkfIpb>%4NA};6Ju;&@d`BsZXGcTEA zmHi{-V}P1+jMA_Fj^CbqNDd%$x_q*f7*r!)$N!VMD13&EJw=I0p_WTlb{2BNZ!GXo zZCC?mhEBw?z*eJvKD5)|bl>zG?08stpZrURnu;hU8hbP`i1%{} ze$fl{-CCM)=h(lrcwmIi$5dgv;ps_5y>uAst?9ure1z7{o8(`&L7$baa+B9UmkiQatRs&C9?#pf)oyl(soK|A&4t|tfB&btC zTC1za)vxC18F5iqjA{x|@DUKZOO30|dvwi?LS*8GHa5|r_*ra;jaC1{-~|ObW>OFf z<7*!pcJ{t0A2F0Q|2}rM`$2G=X>nnqJkyGHlI+6lYxk1Woag1({RXXfm@X|Be^m|0 z7XO;Aq(@!mv9Gek;3?&Jj@X0drGSQeJxtQ9?Aqv&Z5j#vn-Yab(pJBvRIV~q7EA`r zwt7B5Kfsg>bL?s#EHZ!jV5gkEO}Du>B8G7%^nu|7TGsX>=3=S^NW{CMrVG?wO-+6e z>>FL+6+hUQdG>=!B{|M3^N|0dNc=uCju$D!V52C?mM!2+8^6J1Aya2{uh0$OpB1k{ zPfO%XaFW?+likO5wO=EGai9@M1h z;eo13X>UOfN)N&SVdmU75!-*|G>|A5am^YgEE%FN;sQeSVZ;i>_To#&m{J%77+VB55jU;@fy(~nSddZwzjreSjLAgSw1(bx7PISgd zs{eK!c;Uy^4!l@8ajP1`>4!gGu}`fh3ixE*5aS|&7l&->bJ4g5?FwgE$l0>}{SqVy zXxb}?GJEJgZRG7+LvUEHUgk1azCfq*UF*L%!|GpV<4GzK#qY9sUSf&Dlel^Kp2(Bs zp+kia**KBHnEUO_WBXBmXCPM}^Ybl=tZA+OiO;O$RJ<_t389{aObvQ`b)uoe-@maJ zC@oAZ_&*xe&uTWWFk=#QqCR{GS)3U~^>35isNAQg?}ZS}L$ymlUs?v;CvsO#Wss%S z`v^5R;JwI2ZYyB_YWpPn#1nkjCg?~D5jylG5!<*5y5l0p&P}mb)KrGfZp+vlrVsEk8Ap-7K7JF`K|Qr$=49Sw6=LpbrmQ(z`Y8_@5;U{P zX-~ueMTYqRYT2)p@4{0mFYLl0Td7YwT}5i-q}t<5_wTW&3_m4EEAbUq<$njPE$;kJ z^*H>y=u^%{y>DSN-~I#ZTe>_@xc8yCzVO3B+M#*D=IXi{|@gm?X%a=bpo5G^PjAPj0YO~8Fa3c!&yH`e6p15YyrGNc5`KDns z`-ASQ%VmVCYw^%C&U6{L$h3hL?8vufBQ#TV$!;qfK0M~HPBt;#)_cVfIIUl#1S)LZ zoi%TIJ682ObeZ1&WI&b(xF_gG?Mq_yIW6MnMZOuVe7m??TK zys=nly6SariJv`)Jd_CFHNgMKv#z;NP>9V&cS`8hVB6ezwpgkW-`mBIg1a=<(f3npGp4I!ib)}q{Ap@N^$4G_ zX7!%deql^ml9B0uQ}zwyiXVPImH0*f5oGPbgTsULHD0OA0Sc7w3iA#UkqWiR&C&* z6QuFmNV`F3D>LggiFo|k53uukYD&=gvUTDDKR6j0(Ho&O)tkg4^!xqOQp8=twZMNf zf;@_D6{<}vGM+Nmi73M%rRpb>#neK9pLR3K%(R@$7g}tnxD<$Hl@xjT{%y&Iazc)`pC#qNG@wj_TcL$^jai7 z4%;I4NsW=$@wJ-Yduh<_$Q<7Axg&r?vovFNE@7j%RtSskCYW$s>ER-JRi~Mh+yBR_ zhxmH~m*>rKB$qexZ>J}v+e^(X{G+KV_MAnABaI>EAcUJ{xjzP8uS=ZV2 zbmrb)j}&>*HOfr|&tGu6+~qE&xBBIzY}wt!Yl>)MdVcRK8a_|Pl$WDBsvVKA6as^t z-ptc#uvPCpG_e?6^{6p#?IlynT&V1%;;#bl-eft{D61AiGg~0Bp>pY$x)a1Qsf0I z4z9kAtk|$a_zfEDe-4E*2n;BR9IsP1d;?GEM2rF={8=lrL=V|m`m3LZZ=p8U;8i1u zG(yxY!~3eR9xhueoqtz6c(^IZ8s+}Jyy8ZRAZby^!F&J2ZDbiKd66E{V)L&t83+1~ z-GCPw)G?hQn8bRyru$0uYeewKDTaKv@5k9|=qxv{BLxZ3j2}uWucIqRd6;1$9wvld$%7(n$O8E zy}asQEbw{hZ*ov`^D~4Bc2{xo3LLlkIF!U3azdC5K}embS;_kB$Px;yd_D(qc{Kv; z`+c)!r97Z_FlK{z>cO6SMPZ@#q-yWx%zQh%g6_)3d6b1Wo4Jn!zL;C6muDc8RPsz5 zV1XIPMvh+*jWk8PT$l?~#PnU+<>JcF(~Ebn5t1O{`>F6$|BTEQ9Gs{aHus`NUpOEQ#cx$7g;VLi=D; z;8i71#M$4#^vRo@sf$+}Q^P+$zbL?7e68+LSM$9RN{=dPxL+)6-csHDhRUT?Wj_H^iyrhm(MJd$y0Im+f|3r|KP- z9dqCaW#dYa7jiT-MBvA4RqY$H=C)`>aJkMWmOFNZDED`Gv$>l76xll57+T(~Tb8J% zHZB{uJr0aqW##%8gWy$~eTr?S<(F{{I9<6cs_-r3BVHTiUvo{AQA`p+&XzhA-q6