├── .travis.yml
├── Objective-CArmyKnife
├── UIKitExtensions
│ ├── DataSourceCollections
│ │ ├── NSArray+CollectionViewDataSource.h
│ │ ├── NSArray+TableViewDataSource.h
│ │ ├── NSArray+CollectionViewDataSource.m
│ │ └── NSArray+TableViewDataSource.m
│ ├── HexStringColor
│ │ ├── UIColor+HexString.h
│ │ └── UIColor+HexString.m
│ ├── LoadImage
│ │ ├── UIImage+LoadImage.h
│ │ └── UIImage+LoadImage.m
│ ├── ViewFrame
│ │ ├── UIView+Frame.h
│ │ └── UIView+Frame.m
│ ├── RegisterCell
│ │ ├── UITableView+RegisterCell.h
│ │ ├── UICollectionView+RegisterCell.h
│ │ ├── UITableView+RegisterCell.m
│ │ └── UICollectionView+RegisterCell.m
│ ├── ImageViewAnimation
│ │ ├── UIImageView+Animation.h
│ │ └── UIImageView+Animation.m
│ ├── ShakeAnimation
│ │ ├── UIView+ShakeAnimation.h
│ │ └── UIView+ShakeAnimation.m
│ ├── RoundCorner
│ │ ├── UIView+RoundCorner.h
│ │ └── UIView+RoundCorner.m
│ ├── BounceAnimation
│ │ ├── UIView+BounceAnimation.h
│ │ └── UIView+BounceAnimation.m
│ ├── RotateAnimation
│ │ ├── UIView+RotateAnimation.h
│ │ └── UIView+RotateAnimation.m
│ ├── ColorfulNavigationBar
│ │ ├── NavigationBar+Colorful.h
│ │ └── NavigationBar+Colorful.m
│ ├── Transform3DAnimation
│ │ ├── UIView+Transform3DAnimation.h
│ │ └── UIView+Transform3DAnimation.m
│ ├── TableViewSeparator
│ │ ├── UITableView+Separator.m
│ │ └── UITableView+Separator.h
│ ├── MoveCell
│ │ ├── UITableView+MoveCell.h
│ │ └── UITableView+MoveCell.m
│ └── Tab+Navs
│ │ ├── UITabBarController+UINavigationController.m
│ │ └── UITabBarController+UINavigationController.h
├── PublicHeaders
│ ├── PrintModelProperty.h
│ └── Objective-CArmyKnife.h
├── FoundationExtensions
│ ├── UIView+Extensions.h
│ ├── Base64
│ │ ├── NSData+Base64.h
│ │ └── NSData+Base64.m
│ ├── Bundle
│ │ ├── NSString+Bundle.m
│ │ └── NSString+Bundle.h
│ ├── MD5
│ │ ├── NSString+MD5.h
│ │ └── NSString+MD5.m
│ ├── Week
│ │ ├── NSDate+Week.h
│ │ └── NSDate+Week.m
│ ├── UIView+Extensions.m
│ ├── UIDevice+Extensions.h
│ ├── Palindrome
│ │ ├── NSString+Palindrome.h
│ │ └── NSString+Palindrome.m
│ ├── Calendar
│ │ ├── NSDate+Calendar.h
│ │ └── NSDate+Calendar.m
│ ├── Regex
│ │ ├── NSString+Regex.h
│ │ └── NSString+Regex.m
│ ├── Edit
│ │ ├── NSString+Edit.m
│ │ └── NSString+Edit.h
│ └── UIDevice+Extensions.m
├── RuntimeExtensions
│ ├── PrintModelProperty
│ │ ├── NSArray+PrintModelProperty.h
│ │ ├── NSSet+PrintModelProperty.h
│ │ ├── NSDictionary+PrintModelProperty.h
│ │ ├── NSSet+PrintModelProperty.m
│ │ ├── NSObject+PrintModelProperty.h
│ │ ├── NSArray+PrintModelProperty.m
│ │ ├── NSDictionary+PrintModelProperty.m
│ │ └── NSObject+PrintModelProperty.m
│ └── MethodSwizzConvenienceInterface
│ │ ├── MethodSwizzConvenienceInterface.h
│ │ └── MethodSwizzConvenienceInterface.m
├── CoreAnimationExtensions
│ └── ConvenienceAnimation
│ │ ├── CAAnimation+Extensions.h
│ │ └── CAAnimation+Extensions.m
├── CoreGraphicsExtensions
│ └── CGRect
│ │ ├── CGRect+Convenience.m
│ │ └── CGRect+Convenience.h
└── Controls
│ ├── Loading
│ ├── OCKLoopLoadingView.h
│ └── OCKLoopLoadingView.m
│ └── Timer
│ ├── OCKCountDownLabel.h
│ └── OCKCountDownLabel.m
├── Objective-CArmyKnifeExample
├── Images.xcassets
│ ├── loading_loop.imageset
│ │ ├── loading_loop@2x.png
│ │ └── Contents.json
│ ├── loading_monkey.imageset
│ │ ├── loading_monkey@2x.png
│ │ └── Contents.json
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── ViewController.h
├── SecondViewController.h
├── TableViewController.h
├── GradientViewController.h
├── AppDelegate.h
├── Supporting Files
│ ├── main.m
│ └── Info.plist
├── GradientViewController.m
├── ViewController.m
├── AppDelegate.m
├── Base.lproj
│ ├── LaunchScreen.xib
│ └── Main.storyboard
├── SecondViewController.m
└── TableViewController.m
├── Objective-CArmyKnifeExample.xcodeproj
└── project.xcworkspace
│ └── contents.xcworkspacedata
├── .gitignore
├── Objective-CArmyKnife.podspec
├── Objective-CArmyKnifeExampleTests
├── Supporting Files
│ └── Info.plist
└── Objective_CArmyKnifeExampleTests.m
└── LICENSE
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: objective-c
2 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/DataSourceCollections/NSArray+CollectionViewDataSource.h:
--------------------------------------------------------------------------------
1 | @import UIKit;
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/DataSourceCollections/NSArray+TableViewDataSource.h:
--------------------------------------------------------------------------------
1 | @import UIKit;
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/DataSourceCollections/NSArray+CollectionViewDataSource.m:
--------------------------------------------------------------------------------
1 | #import "UIView+Extensions.h"
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/DataSourceCollections/NSArray+TableViewDataSource.m:
--------------------------------------------------------------------------------
1 | #import "NSArray+TableViewDataSource.h"
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/PublicHeaders/PrintModelProperty.h:
--------------------------------------------------------------------------------
1 | #import "NSObject+PrintProperty.h"
2 | #import "NSArray+PrintProperty.h"
3 | #import "NSSet+PrintProperty.h"
4 | #import "NSDictionary+PrintProperty.h"
5 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/FoundationExtensions/UIView+Extensions.h:
--------------------------------------------------------------------------------
1 | @import UIKit;
2 |
3 | //@interface UIView (TextSize)
4 | //
5 | //- (CGSize)boundingRectWithSize:(CGSize)size;
6 | //
7 | //@end
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/HexStringColor/UIColor+HexString.h:
--------------------------------------------------------------------------------
1 | @import UIKit;
2 |
3 | @interface UIColor (HexString)
4 |
5 | + (UIColor *)colorWithHexString:(NSString *)hexString;
6 |
7 | @end
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Objective-CArmyKnifeExample/Images.xcassets/loading_loop.imageset/loading_loop@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Michael-Lfx/Objective-CUtils/HEAD/Objective-CArmyKnifeExample/Images.xcassets/loading_loop.imageset/loading_loop@2x.png
--------------------------------------------------------------------------------
/Objective-CArmyKnifeExample/Images.xcassets/loading_monkey.imageset/loading_monkey@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Michael-Lfx/Objective-CUtils/HEAD/Objective-CArmyKnifeExample/Images.xcassets/loading_monkey.imageset/loading_monkey@2x.png
--------------------------------------------------------------------------------
/Objective-CArmyKnifeExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/RuntimeExtensions/PrintModelProperty/NSArray+PrintModelProperty.h:
--------------------------------------------------------------------------------
1 | @import Foundation;
2 |
3 |
4 | /**
5 | * 输出可便于阅读的内容
6 | */
7 | @interface NSArray (PrintModelProperty)
8 |
9 | /**
10 | * 输出可便于阅读的内容
11 | */
12 | - (NSString *)readableDescription;
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/RuntimeExtensions/PrintModelProperty/NSSet+PrintModelProperty.h:
--------------------------------------------------------------------------------
1 | @import Foundation;
2 |
3 |
4 | /**
5 | * 输出可便于阅读的内容
6 | */
7 | @interface NSSet (PrintModelProperty)
8 |
9 | /**
10 | * 输出可便于阅读的内容
11 | */
12 | - (NSString *)readableDescription;
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/LoadImage/UIImage+LoadImage.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @interface UIImage (LoadImage)
4 |
5 | + (instancetype)loadImageFromMainBundleWithPath:(NSString *)path;
6 |
7 | + (instancetype)loadOriginalImageFromMainBundleWithPath:(NSString *)path;
8 |
9 | @end
10 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/RuntimeExtensions/PrintModelProperty/NSDictionary+PrintModelProperty.h:
--------------------------------------------------------------------------------
1 | @import Foundation;
2 |
3 |
4 | /**
5 | * 输出可便于阅读的内容
6 | */
7 | @interface NSDictionary (PrintModelProperty)
8 |
9 | /**
10 | * 输出可便于阅读的内容
11 | */
12 | - (NSString *)readableDescription;
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/Objective-CArmyKnifeExample/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/8/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ViewController : UIViewController
12 |
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/Objective-CArmyKnifeExample/SecondViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // SecondViewController.h
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/11/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface SecondViewController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Objective-CArmyKnifeExample/TableViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // TableViewController.h
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/10/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface TableViewController : UITableViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/ViewFrame/UIView+Frame.h:
--------------------------------------------------------------------------------
1 | @import UIKit;
2 |
3 | @interface UIView (Frame)
4 |
5 | - (CGFloat)height;
6 | - (CGFloat)width;
7 | - (CGFloat)x;
8 | - (CGFloat)y;
9 | - (void)setHeight:(CGFloat)height;
10 | - (void)setWidth:(CGFloat)width;
11 | - (void)setX:(CGFloat)x;
12 | - (void)setY:(CGFloat)y;
13 |
14 | @end
15 |
--------------------------------------------------------------------------------
/Objective-CArmyKnifeExample/GradientViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // GradientViewController.h
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/12/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface GradientViewController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/FoundationExtensions/Base64/NSData+Base64.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+Base64.h
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/15/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface NSData (Base64)
12 |
13 | - (NSString *)base64String;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/RuntimeExtensions/PrintModelProperty/NSSet+PrintModelProperty.m:
--------------------------------------------------------------------------------
1 | #import "NSObject+PrintModelProperty.h"
2 | #import "NSSet+PrintModelProperty.h"
3 |
4 |
5 | @implementation NSSet (PrintModelProperty)
6 |
7 | - (NSString *)readableDescription {
8 | return [NSString stringWithFormat:@"{%@}", [[self allObjects] readableDescription]];
9 | }
10 |
11 | @end
12 |
13 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/LoadImage/UIImage+LoadImage.m:
--------------------------------------------------------------------------------
1 | #import "UIImage+LoadImage.h"
2 |
3 | @implementation UIImage (LoadImage)
4 |
5 | //+ (instancetype)loadOriginalImageFromMainBundleWithPath:(NSString *)path {
6 | // UIImage *image = [[UIImage imageNamed:selectedImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
7 | // return image;
8 | //}
9 |
10 | @end
11 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/RegisterCell/UITableView+RegisterCell.h:
--------------------------------------------------------------------------------
1 | @import UIKit;
2 |
3 |
4 | @interface UITableView (RegisterCell)
5 |
6 | - (instancetype)registerNibWithName:(NSString *)name forCellReuseIdentifier:(NSString *)identifier;
7 |
8 | - (instancetype)registerNibWithName:(NSString *)name bundle:(NSBundle *)bundleOrNil forCellReuseIdentifier:(NSString *)identifier;
9 |
10 | @end
11 |
--------------------------------------------------------------------------------
/Objective-CArmyKnifeExample/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/8/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/RuntimeExtensions/MethodSwizzConvenienceInterface/MethodSwizzConvenienceInterface.h:
--------------------------------------------------------------------------------
1 | @import Foundation;
2 |
3 | /**
4 | * 线程安全的混写,先尝试混写实例方法,再尝试混写类方法
5 | * 全部尝试失败时,输出“混写失败:srcSelector或dstSelector对应的Method不存在”
6 | *
7 | * @param cls 需要混写的类
8 | * @param srcSelector 原始选择器
9 | * @param dstSelector 目标选择器
10 | */
11 | extern void methodSwizz(Class cls, SEL srcSelector, SEL dstSelector);
12 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/RegisterCell/UICollectionView+RegisterCell.h:
--------------------------------------------------------------------------------
1 | @import UIKit;
2 |
3 |
4 | @interface UICollectionView (RegisterCell)
5 |
6 | //- (instancetype)registerNibWithName:(NSString *)name forCellReuseIdentifier:(NSString *)identifier;
7 | //
8 | //- (instancetype)registerNibWithName:(NSString *)name bundle:(NSBundle *)bundleOrNil forCellReuseIdentifier:(NSString *)identifier;
9 |
10 | @end
11 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/ImageViewAnimation/UIImageView+Animation.h:
--------------------------------------------------------------------------------
1 | @import UIKit;
2 |
3 | #ifndef kDuration
4 | #define kDuration (0.5)
5 | #endif
6 |
7 | @interface UIImageView (Animation)
8 |
9 | #pragma mark FrameAnimation
10 |
11 | - (void)defaultFrameAnimationWithImages:(NSArray *)images;
12 | - (void)frameAnimation:(UIImageView *)icon images:(NSArray *)images duration:(CGFloat)duration repeatCount:(CGFloat)repeatCount;
13 |
14 | @end
15 |
--------------------------------------------------------------------------------
/Objective-CArmyKnifeExample/Supporting Files/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/8/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 | #import
9 | #import "AppDelegate.h"
10 |
11 | int main(int argc, char * argv[]) {
12 | @autoreleasepool {
13 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Objective-CArmyKnifeExample/Images.xcassets/loading_loop.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "loading_loop@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Objective-CArmyKnife/PublicHeaders/Objective-CArmyKnife.h:
--------------------------------------------------------------------------------
1 |
2 | // UIKit
3 |
4 |
5 | // Foundation
6 | //#import "NSData+Extensions.h"
7 | //#import "NSObject+PrintProperty.h"
8 | //#import "NSArray+PrintProperty.h"
9 | //#import "NSSet+PrintProperty.h"
10 | //#import "NSDictionary+PrintProperty.h"
11 | //#import "NSString+Extensions.h"
12 |
13 | // Core Graphics
14 | //#import "CGRect+Extensions.h"
15 |
16 | // Core Animation
17 | //#import "CAAnimation+Extensions.h"
18 |
19 |
--------------------------------------------------------------------------------
/Objective-CArmyKnifeExample/Images.xcassets/loading_monkey.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x",
10 | "filename" : "loading_monkey@2x.png"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Objective-CArmyKnife/RuntimeExtensions/PrintModelProperty/NSObject+PrintModelProperty.h:
--------------------------------------------------------------------------------
1 | @import Foundation;
2 |
3 |
4 | extern void deleteLastTwoCharacters(NSMutableString *string);
5 |
6 | /**
7 | * 输出可便于阅读的内容,用于Debug
8 | */
9 | @interface NSObject (PrintModelProperty)
10 |
11 | /**
12 | * 输出对象及其继承的属性值,只支持自定义模型类
13 | * 不支持UIKit中定义的类及其派生类
14 | */
15 | - (NSString *)autoDescription;
16 |
17 | /**
18 | * 输出可便于阅读的内容
19 | */
20 | - (NSString *)readableDescription;
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/ShakeAnimation/UIView+ShakeAnimation.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+ShakeAnimation.h
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/12/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UIView (ShakeAnimation)
12 |
13 | - (void)defaultShakeAnimation;
14 |
15 | - (void)shakeAnimationWithMargin:(CGFloat)margin duration:(CGFloat)duration repeatCount:(CGFloat)repeatCount;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/RoundCorner/UIView+RoundCorner.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+RoundCorner.h
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/12/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /**
12 | * CALayer mask属性实现遮罩效果
13 |
14 | // 整合自:https://gist.github.com/bobmoff/5967220
15 |
16 | */
17 | @interface UIView (RoundCorner)
18 |
19 | - (void)setRoundCorners:(UIRectCorner)corners radius:(CGSize)size;
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/CoreAnimationExtensions/ConvenienceAnimation/CAAnimation+Extensions.h:
--------------------------------------------------------------------------------
1 | @import UIKit;
2 |
3 | @interface CAAnimation (Convenience)
4 |
5 | + (CAKeyframeAnimation *)keyframeAnimationWithKeyPath:(NSString *)keyPath values:(NSArray *)values duration:(CFTimeInterval)duration repeatCount:(float)repeatCount;
6 |
7 | + (CABasicAnimation *)basicAnimationWithKeyPath:(NSString *)keyPath fromValue:(CGFloat)fromValue toValue:(CGFloat)toValue duration:(CFTimeInterval)duration repeatCount:(float)repeatCount;
8 |
9 | @end
10 |
11 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/BounceAnimation/UIView+BounceAnimation.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+BounceAnimation.h
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/12/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /**
12 | * 弹性动画
13 | */
14 | @interface UIView (BounceAnimation)
15 |
16 | - (void)defaultBounceAnimation;
17 | - (void)bounceAnimationWithValues:(NSArray *)values duration:(CGFloat)duration repeatCount:(CGFloat)repeatCount;
18 |
19 | @end
20 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/RotateAnimation/UIView+RotateAnimation.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+RotateAnimation.h
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/12/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /**
12 | * 旋转360度动画
13 | */
14 | @interface UIView (RotateAnimation)
15 |
16 | - (void)defaultRotateAnimation;
17 |
18 | - (void)rotateAnimationFrom:(CGFloat)fromValue to:(CGFloat)toValue duration:(CGFloat)duration repeatCount:(CGFloat)repeatCount;
19 | @end
20 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/RuntimeExtensions/PrintModelProperty/NSArray+PrintModelProperty.m:
--------------------------------------------------------------------------------
1 | #import "NSObject+PrintModelProperty.h"
2 | #import "NSArray+PrintModelProperty.h"
3 |
4 |
5 | @implementation NSArray (PrintModelProperty)
6 |
7 | - (NSString *)readableDescription {
8 | NSMutableString *result = [NSMutableString string];
9 |
10 | for (id value in self) {
11 | [result appendFormat:@"%@, ", [value readableDescription]];
12 | }
13 | deleteLastTwoCharacters(result);
14 |
15 | return [NSString stringWithFormat:@"(%@)", result];
16 | }
17 |
18 | @end
19 |
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | build/
4 | *.pbxuser
5 | !default.pbxuser
6 | *.mode1v3
7 | !default.mode1v3
8 | *.mode2v3
9 | !default.mode2v3
10 | *.perspectivev3
11 | !default.perspectivev3
12 | xcuserdata
13 | *.xccheckout
14 | *.moved-aside
15 | DerivedData
16 | *.hmap
17 | *.ipa
18 | *.xcuserstate
19 |
20 | # CocoaPods
21 | #
22 | # We recommend against adding the Pods directory to your .gitignore. However
23 | # you should judge for yourself, the pros and cons are mentioned at:
24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
25 | #
26 | #Pods/
27 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "Objective-CArmyKnife"
3 | s.version = "v0.4-animation.alpha.1"
4 | s.summary = "收录oc常用工具方法,提高开发效率,避免重复造轮子,欢迎分享代码"
5 | s.homepage = "http://github.com/Michael-Lfx/Objective-CArmyKnife"
6 | s.license = "MIT"
7 | s.author = { "Michael-LFX" => "cihv2@163.com" }
8 | s.platform = :ios, "7.0"
9 | s.source = { :git => "https://github.com/Michael-Lfx/Objective-CArmyKnife.git", :tag => s.version.to_s }
10 | s.source_files = "Objective-CArmyKnife", "Objective-CArmyKnife/**/*.{h,m}"
11 | s.requires_arc = true
12 |
13 | end
14 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/FoundationExtensions/Bundle/NSString+Bundle.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+Bundle.m
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/15/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import "NSString+Bundle.h"
10 |
11 | @implementation NSString (Bundle)
12 |
13 | + (NSString *)stringFromMainBundleWithFilename:(NSString *)filename {
14 | NSString *path = [[NSBundle mainBundle] pathForResource:filename ofType:nil];
15 | NSString *text = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
16 | return text;
17 | }
18 |
19 | @end
20 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/ColorfulNavigationBar/NavigationBar+Colorful.h:
--------------------------------------------------------------------------------
1 | @import UIKit;
2 |
3 | /**
4 | * @brief 支持透明、多种颜色渐变的NavigationBar。
5 | *
6 | * 说明:Xcode 6.3.2中Interface Builder不支持NavigationBar的实时渲染,加上IB_DESIGNABLE与IBInspectable无任何意义
7 | * 故不做成子类,改用拓展实现
8 | */
9 | @interface UINavigationBar (Colorful)
10 |
11 | /**
12 | * 单个颜色,与gradientColors互斥
13 | *
14 | * @see 设置一组渐变色可使用 gradientColors 属性
15 | */
16 | @property (strong, nonatomic) UIColor *soloColor;
17 |
18 | /**
19 | * 一组(只支持两个,多了自己改代码吧)渐变颜色,从顶到底渐变。与soloColor互斥
20 | */
21 | @property (copy, nonatomic) NSArray *gradientColors; // for Colors
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/FoundationExtensions/Bundle/NSString+Bundle.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+Bundle.h
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/15/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface NSString (Bundle)
12 |
13 | /**
14 | * 读取Main Bundle中的文本文件内容
15 |
16 | 使用示例:
17 |
18 | NSString *contentOfSomeText = [NSString stringFromMainBundleWithFilename:@"readme.txt"];
19 |
20 | *
21 | * @param filename 文件名
22 | *
23 | * @return 文件内容
24 | */
25 | + (NSString *)stringFromMainBundleWithFilename:(NSString *)filename;
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/FoundationExtensions/MD5/NSString+MD5.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+MD5.h
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/15/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface NSString (MD5)
12 |
13 | /**
14 | - (NSString *)MD5Hash
15 | Generates an MD5 cryptographic hash of this NSString's contents
16 |
17 | Example:
18 | NSString *hash = [@"The quick brown fox jumped over the lazy dog" MD5Hash];
19 |
20 | Returns an NSString containing the hexidecimal representation of the MD5 hash.
21 | */
22 | - (NSString *)MD5Hash;
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/CoreGraphicsExtensions/CGRect/CGRect+Convenience.m:
--------------------------------------------------------------------------------
1 | #import "CGRect+Convenience.h"
2 |
3 | inline CGRect CGRectFromCGSize(CGSize size) {
4 | return (CGRect){ .origin = CGPointZero, .size = size };
5 | }
6 |
7 | inline CGRect CGRectMakeWithCenterAndSize(CGPoint center, CGSize size) {
8 | return (CGRect){ center.x - size.width * 0.5, center.y - size.height * 0.5, size };
9 | }
10 |
11 | inline CGRect CGRectMakeWithOriginAndSize(CGPoint origin, CGSize size) {
12 | return (CGRect){ .origin = origin, .size = size };
13 | }
14 |
15 | inline CGPoint CGRectCenter(CGRect rect) {
16 | return (CGPoint){ CGRectGetMidX(rect), CGRectGetMidY(rect) };
17 | }
18 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/RuntimeExtensions/PrintModelProperty/NSDictionary+PrintModelProperty.m:
--------------------------------------------------------------------------------
1 | #import "NSObject+PrintModelProperty.h"
2 | #import "NSDictionary+PrintModelProperty.h"
3 |
4 |
5 | @implementation NSDictionary (PrintModelProperty)
6 |
7 | - (NSString *)readableDescription {
8 | NSMutableString *result = [NSMutableString string];
9 |
10 | for (id key in self) {
11 | id value = [self objectForKey:key];
12 | [result appendFormat:@"%@ = %@; ", [key readableDescription], [value readableDescription]];
13 | }
14 | deleteLastTwoCharacters(result);
15 |
16 | return [NSString stringWithFormat:@"{%@}", result];
17 | }
18 |
19 | @end
20 |
21 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/Transform3DAnimation/UIView+Transform3DAnimation.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+Transform3DAnimation.h
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/12/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UIView (Transform3DAnimation)
12 |
13 | /**
14 | * 旋转动画效果
15 |
16 | 使用示例(每个单元格出现时旋转):
17 |
18 | - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
19 |
20 | [cell transform3DAnimation];
21 |
22 | }
23 | *
24 | * @return 当前视图
25 | */
26 | - (instancetype)transform3DAnimation;
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/Controls/Loading/OCKLoopLoadingView.h:
--------------------------------------------------------------------------------
1 | @import UIKit;
2 |
3 | /**
4 | * 旋转LoopImage、LogoImage时亮时暗动画的视图
5 | *
6 | * 建议使用场合:加载数据等无预计时间的等待画面
7 | */
8 | @interface OCKLoopLoadingView : UIView
9 |
10 | /**
11 | * 是否正在加载
12 | */
13 | @property (assign, nonatomic, readonly, getter=isLoading) BOOL loading;
14 |
15 | /**
16 | * 设置外圈旋转图标,应该大于LogoImage,且最好为非完整圆
17 | *
18 | * @param image 外圈旋转图标
19 | */
20 | - (void)setLoopImage:(UIImage *)image;
21 |
22 | /**
23 | * 内图标,要求小于LogoImage,最好被LoopImage包起来后还有些边距,一般是产品图标缩略图
24 | *
25 | * @param image 内圈LOGO图标
26 | */
27 | - (void)setLogoImage:(UIImage *)image;
28 |
29 | - (void)startAnimating;
30 |
31 | - (void)stopAnimating;
32 |
33 | @end
34 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/RegisterCell/UITableView+RegisterCell.m:
--------------------------------------------------------------------------------
1 | #import "UITableView+RegisterCell.h"
2 |
3 |
4 | @implementation UITableView (RegisterCell)
5 |
6 | - (instancetype)registerNibWithName:(NSString *)name
7 | forCellReuseIdentifier:(NSString *)identifier {
8 | return [self registerNibWithName:name bundle:nil forCellReuseIdentifier:identifier];
9 | }
10 |
11 | - (instancetype)registerNibWithName:(NSString *)name
12 | bundle:(NSBundle *)bundleOrNil
13 | forCellReuseIdentifier:(NSString *)identifier {
14 | UINib *nib = [UINib nibWithNibName:name bundle:bundleOrNil];
15 | [self registerNib:nib forCellReuseIdentifier:identifier];
16 | return self;
17 | }
18 |
19 | @end
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/RoundCorner/UIView+RoundCorner.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+RoundCorner.m
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/12/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import "UIView+RoundCorner.h"
10 |
11 | @implementation UIView (RoundCorner)
12 |
13 | - (void)setRoundCorners:(UIRectCorner)corners radius:(CGSize)size {
14 | UIBezierPath* maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:size];
15 |
16 | CAShapeLayer* maskLayer = [CAShapeLayer new];
17 | maskLayer.frame = self.bounds;
18 | maskLayer.path = maskPath.CGPath;
19 |
20 | self.layer.mask = maskLayer;
21 | }
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/FoundationExtensions/Week/NSDate+Week.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSDate+Week.h
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/15/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /**
12 | * NSLog(@"从周日开始算,今天是本周的第 %zi 天", [NSDate date].dayOfWeek)
13 | * NSLog(@"从周一开始算,今天是本周的第 %zi 天", [NSDate date].dayOfWeekStartWithMonday)
14 | */
15 | @interface NSDate (Week)
16 |
17 | /**
18 | * 日期所属的星期数,周日为1,周六为7。如 2015年1月1日为5,即周4
19 | *
20 | * @return 日期所属的星期数
21 | */
22 | - (NSUInteger)dayOfWeek;
23 |
24 | /**
25 | * 日期所属的星期数,周日为1,周六为7。如 2015年1月1日为4,即周4
26 | *
27 | * @return 日期所属的星期数
28 | */
29 | - (NSUInteger)dayOfWeekStartWithMonday;
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/FoundationExtensions/UIView+Extensions.m:
--------------------------------------------------------------------------------
1 | #import "UIView+Extensions.h"
2 |
3 |
4 | //@implementation UILabel (TextSize)
5 | //
6 | //- (CGSize)boundingRectWithSize:(CGSize)size {
7 | // NSDictionary *attribute = @{NSFontAttributeName: self.font};
8 | //
9 | // CGSize retSize = [self.text boundingRectWithSize:size
10 | // options:\
11 | // NSStringDrawingTruncatesLastVisibleLine |
12 | // NSStringDrawingUsesLineFragmentOrigin |
13 | // NSStringDrawingUsesFontLeading
14 | // attributes:attribute
15 | // context:nil].size;
16 | //
17 | // return retSize;
18 | //}
19 | //
20 | //
21 | //@end
22 |
23 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/CoreGraphicsExtensions/CGRect/CGRect+Convenience.h:
--------------------------------------------------------------------------------
1 | @import UIKit;
2 |
3 | /**
4 | * 创建一个origin = CGPointZero,size为传入size的矩形
5 | *
6 | * @param size 矩形大小
7 | *
8 | * @return 新建的矩形
9 | */
10 | OBJC_EXPORT CGRect CGRectFromCGSize(CGSize size);
11 |
12 | /**
13 | * 根据中心点及大小创建矩形
14 | *
15 | * @param center 中心点坐标
16 | * @param size 大小
17 | *
18 | * @return 新建的矩形
19 | */
20 | OBJC_EXPORT CGRect CGRectMakeWithCenterAndSize(CGPoint center, CGSize size);
21 |
22 | /**
23 | * 通过起点坐标及大小创建矩形
24 | *
25 | * @param origin 起点坐标
26 | * @param size 大小
27 | *
28 | * @return 新建的矩形
29 | */
30 | OBJC_EXPORT CGRect CGRectMakeWithOriginAndSize(CGPoint origin, CGSize size);
31 |
32 | /**
33 | * 返回矩形中心点坐标
34 | *
35 | * @param rect 矩形
36 | *
37 | * @return 中心点坐标
38 | */
39 | OBJC_EXPORT CGPoint CGRectCenter(CGRect rect);
40 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/FoundationExtensions/UIDevice+Extensions.h:
--------------------------------------------------------------------------------
1 | @import UIKit;
2 |
3 | @interface UIDevice (Identifier)
4 |
5 | /*
6 | * @method uniqueDeviceIdentifier
7 | * @description use this method when you need a unique identifier in one app.
8 | * It generates a hash from the MAC-address in combination with the bundle identifier
9 | * of your app.
10 | */
11 | - (NSString *) uniqueDeviceIdentifier;
12 |
13 | /*
14 | * @method uniqueGlobalDeviceIdentifier
15 | * @description use this method when you need a unique global identifier to track a device
16 | * with multiple apps. as example a advertising network will use this method to track the device
17 | * from different apps.
18 | * It generates a hash from the MAC-address only.
19 | */
20 | - (NSString *) uniqueGlobalDeviceIdentifier;
21 |
22 | - (NSString *) platformString;
23 |
24 | @end
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/Objective-CArmyKnifeExampleTests/Supporting Files/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | io.github.michael-lfx.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/RegisterCell/UICollectionView+RegisterCell.m:
--------------------------------------------------------------------------------
1 | #import "UICollectionView+RegisterCell.h"
2 |
3 |
4 | @implementation UICollectionView (RegisterCell)
5 |
6 | //- (instancetype)registerNibWithName:(NSString *)name
7 | // forCellReuseIdentifier:(NSString *)identifier {
8 | // return [self registerNibWithName:name bundle:nil forCellReuseIdentifier:identifier];
9 | //}
10 | //
11 | //- (instancetype)registerNibWithName:(NSString *)name
12 | // bundle:(NSBundle *)bundleOrNil
13 | // forCellReuseIdentifier:(NSString *)identifier {
14 | // UINib *nib = [UINib nibWithNibName:name bundle:bundleOrNil];
15 | //// [self registerNib:<#(UINib *)#> forSupplementaryViewOfKind:<#(NSString *)#> withReuseIdentifier:<#(NSString *)#>]
16 | // [self registerNib:nib forCellReuseIdentifier:identifier];
17 | // return self;
18 | //}
19 |
20 | @end
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/ShakeAnimation/UIView+ShakeAnimation.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+ShakeAnimation.m
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/12/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import "UIView+ShakeAnimation.h"
10 |
11 | @implementation UIView (ShakeAnimation)
12 |
13 | - (void)defaultShakeAnimation {
14 | [self shakeAnimationWithMargin:10 duration:0.20 repeatCount:2];
15 | }
16 |
17 | - (void)shakeAnimationWithMargin:(CGFloat)margin duration:(CGFloat)duration repeatCount:(CGFloat)repeatCount {
18 | CAKeyframeAnimation *shakeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation.x"];
19 | shakeAnimation.values = @[@0, @(-margin), @(margin), @0];
20 | shakeAnimation.duration = duration;
21 | shakeAnimation.repeatCount = repeatCount;
22 | [self.layer addAnimation:shakeAnimation forKey:@"shakeAnimationWithX"];
23 | }
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/FoundationExtensions/Palindrome/NSString+Palindrome.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+Palindrome.h
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/15/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface NSString (Palindrome)
12 |
13 | /**
14 | - (BOOL)isPalindrome
15 | 判断字符串是否为回文串。
16 |
17 | Example:
18 | [@"HANNAH" isPalindrome]; // returns YES
19 | [@"CLAUDE" isPalindrome]; // returns NO
20 |
21 | Returns a BOOL corresponding to this NSString's palindrome status.
22 | */
23 | - (BOOL)isPalindrome;
24 |
25 | /**
26 | + (BOOL)stringIsPalindrome:
27 | 判断字符串是否为回文串。
28 |
29 | aString - The NSString to be tested.
30 |
31 | Example:
32 | [NSString stringIsPalindrome:@"RADAR"]; // return YES
33 |
34 | Returns a BOOL cooresponding to the NSString palindrome status.
35 | */
36 | + (BOOL)stringIsPalindrome:(NSString*)aString;
37 |
38 | @end
39 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/ImageViewAnimation/UIImageView+Animation.m:
--------------------------------------------------------------------------------
1 | #import "UIImageView+Animation.h"
2 |
3 | @implementation UIImageView (Animation)
4 |
5 | #pragma mark FrameAnimation
6 |
7 | - (void)defaultFrameAnimationWithImages:(NSArray *)images {
8 | [self frameAnimation:self images:images duration:kDuration repeatCount:1];
9 | }
10 |
11 | - (void)frameAnimation:(UIImageView *)icon images:(NSArray *)images duration:(CGFloat)duration repeatCount:(CGFloat)repeatCount {
12 | CAKeyframeAnimation *frameAnimation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];
13 | frameAnimation.calculationMode = kCAAnimationDiscrete;
14 | frameAnimation.duration = duration;
15 | frameAnimation.values = images;
16 | frameAnimation.repeatCount = 1;
17 | frameAnimation.removedOnCompletion = false;
18 | frameAnimation.fillMode = kCAFillModeForwards;
19 | [icon.layer addAnimation:frameAnimation forKey:@"frameAnimation"];
20 | }
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/TableViewSeparator/UITableView+Separator.m:
--------------------------------------------------------------------------------
1 | #import "UITableView+Separator.h"
2 | #import "MethodSwizzConvenienceInterface.h"
3 | #import
4 |
5 | @implementation UITableView (Separator)
6 |
7 | - (instancetype)clearExtraSeparator {
8 | UIView *maskView = [[UIView alloc] init];
9 | maskView.backgroundColor = self.backgroundColor;
10 | self.tableFooterView = maskView;
11 | return self;
12 | }
13 |
14 | /**
15 | * 参考 http://stackoverflow.com/questions/25770119/ios-8-uitableview-separator-inset-0-not-working/25772101#25772101
16 | */
17 | - (UITableViewCell *)makeSeparatorEqualToScreenWidthWithCell:(UITableViewCell *)cell {
18 | static dispatch_once_t onceToken;
19 | dispatch_once(&onceToken, ^{
20 | self.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0);
21 | });
22 | cell.layoutMargins = UIEdgeInsetsZero;
23 | cell.preservesSuperviewLayoutMargins = NO;
24 | return cell;
25 | }
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/ViewFrame/UIView+Frame.m:
--------------------------------------------------------------------------------
1 | #import "UIView+Frame.h"
2 |
3 |
4 | @implementation UIView (Frame)
5 |
6 | - (CGFloat)x {
7 | return self.frame.origin.x;
8 | }
9 |
10 | - (void)setX:(CGFloat)newX {
11 | CGRect frame = self.frame;
12 | frame.origin.x = newX;
13 | self.frame = frame;
14 | }
15 |
16 | - (CGFloat)y {
17 | return self.frame.origin.y;
18 | }
19 |
20 | - (void)setY:(CGFloat)newY {
21 | CGRect frame = self.frame;
22 | frame.origin.y = newY;
23 | self.frame = frame;
24 | }
25 |
26 | - (CGFloat)width {
27 | return self.frame.size.width;
28 | }
29 |
30 | - (void)setWidth:(CGFloat)newWidth {
31 | CGRect frame = self.frame;
32 | frame.size.width = newWidth;
33 | self.frame = frame;
34 | }
35 |
36 | - (CGFloat)height {
37 | return self.frame.size.height;
38 | }
39 |
40 | - (void)setHeight:(CGFloat)newHeight {
41 | CGRect frame = self.frame;
42 | frame.size.height = newHeight;
43 | self.frame = frame;
44 | }
45 |
46 | @end
47 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/BounceAnimation/UIView+BounceAnimation.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+BounceAnimation.m
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/12/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import "UIView+BounceAnimation.h"
10 |
11 | @implementation UIView (BounceAnimation)
12 |
13 | - (void)defaultBounceAnimation {
14 | [self bounceAnimationWithValues:@[@1.0, @1.4, @0.9, @1.15, @0.95, @1.02, @1.0] duration:0.5 repeatCount:1];
15 | }
16 |
17 | - (void)bounceAnimationWithValues:(NSArray *)values duration:(CGFloat)duration repeatCount:(CGFloat)repeatCount {
18 | CAKeyframeAnimation *bounceAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
19 | bounceAnimation.values = values;
20 | bounceAnimation.duration = duration;
21 | bounceAnimation.repeatCount = repeatCount;
22 | bounceAnimation.calculationMode = kCAAnimationCubic;
23 | [self.layer addAnimation:bounceAnimation forKey:@"bounceAnimation"];
24 | }
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/RotateAnimation/UIView+RotateAnimation.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+RotateAnimation.m
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/12/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import "UIView+RotateAnimation.h"
10 |
11 | @implementation UIView (RotateAnimation)
12 |
13 | - (void)defaultRotateAnimation {
14 | [self rotateAnimationFrom:0 to:M_PI * 2 duration:0.5 repeatCount:1];
15 | }
16 |
17 | - (void)rotateAnimationFrom:(CGFloat)fromValue to:(CGFloat)toValue duration:(CGFloat)duration repeatCount:(CGFloat)repeatCount {
18 | CABasicAnimation *rotateAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
19 | rotateAnimation.fromValue = [NSNumber numberWithDouble:fromValue];
20 | rotateAnimation.toValue = [NSNumber numberWithDouble:toValue];
21 | rotateAnimation.duration = duration;
22 | rotateAnimation.repeatCount = repeatCount;
23 | [self.layer addAnimation:rotateAnimation forKey:@"rotation360"];
24 | }
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/FoundationExtensions/Calendar/NSDate+Calendar.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSData+Calendar.h
3 | // WMObjCsWorld
4 | //
5 | // Created by maginawin on 15/6/15.
6 | // Copyright (c) 2015年 wendong wang. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /**
12 | * 由514763292提供
13 | */
14 | @interface NSDate (Calendar)
15 |
16 | /**
17 | * @return 当前日期的年
18 | */
19 | - (NSInteger)year;
20 |
21 | /**
22 | * @return 当前日期的月
23 | */
24 | - (NSInteger)month;
25 |
26 | /**
27 | * @return 当前日期的日
28 | */
29 | - (NSInteger)day;
30 |
31 | /**
32 | * @return 当前月有多少天
33 | */
34 | - (NSUInteger)numberOfDaysInCurrentMonth;
35 |
36 | /**
37 | * @return 当前月的第一个星期有几天
38 | */
39 | - (NSInteger)firstWeekDayInMonth;
40 |
41 | /**
42 | * @return 一个月有几周
43 | */
44 | - (NSUInteger)numberOfWeeksInCurrentMonth;
45 |
46 | /**
47 | * @param date : 对比日期
48 | * @return 对比日期的上一个月的日期
49 | */
50 | - (NSDate *)lastMonthDate:(NSDate *)date;
51 |
52 | /**
53 | * @param date : 对比日期
54 | * @return 对比日期的下一个月的日期
55 | */
56 | - (NSDate *)nextMonthDate:(NSDate *)date;
57 |
58 | @end
59 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Michael-Lfx
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/Objective-CArmyKnifeExampleTests/Objective_CArmyKnifeExampleTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // Objective_CArmyKnifeExampleTests.m
3 | // Objective-CArmyKnifeExampleTests
4 | //
5 | // Created by Michael on 6/8/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface Objective_CArmyKnifeExampleTests : XCTestCase
13 |
14 | @end
15 |
16 | @implementation Objective_CArmyKnifeExampleTests
17 |
18 | - (void)setUp {
19 | [super setUp];
20 | // Put setup code here. This method is called before the invocation of each test method in the class.
21 | }
22 |
23 | - (void)tearDown {
24 | // Put teardown code here. This method is called after the invocation of each test method in the class.
25 | [super tearDown];
26 | }
27 |
28 | - (void)testExample {
29 | // This is an example of a functional test case.
30 | XCTAssert(YES, @"Pass");
31 | }
32 |
33 | - (void)testPerformanceExample {
34 | // This is an example of a performance test case.
35 | [self measureBlock:^{
36 | // Put the code you want to measure the time of here.
37 | }];
38 | }
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/MoveCell/UITableView+MoveCell.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | typedef void(^MoveCellDataSourceUpdateBlock)(NSIndexPath *dstIndexPath, NSIndexPath *srcIndexPath);
4 |
5 | @interface UITableView (MoveCell)
6 |
7 | /**
8 | * 长按拖拽TableViewCells,数据源需要在block中更新
9 | *
10 |
11 | 示例用法:
12 |
13 | @property (strong, nonatomic) NSMutableArray *dataForTableView;
14 |
15 | __weak typeof(self) weakSelf = self;
16 |
17 | [self.tableView enableDragCellWithDataSourceUpdateBlock:
18 |
19 | ^(NSIndexPath *dstIndexPath, NSIndexPath *srcIndexPath) {
20 |
21 | [weakSelf.dataForTableView exchangeObjectAtIndex:dstIndexPath.row withObjectAtIndex:srcIndexPath.row];
22 |
23 | }];
24 |
25 | 开始用二维指针传递数据源的方式实现,想把整个流程做得更自动化。发现要照顾的细节较多,故改成block由调用方决定数据源的同步操作。
26 |
27 | 参考自:http://www.raywenderlich.com/63089/cookbook-moving-table-view-cells-with-a-long-press-gesture
28 |
29 | TODO:UICollectionView实现类似功能
30 | TODO:拖拽超过屏幕时,调整容器,方便向上或向下移动单元格
31 | TODO:更自然的动画
32 |
33 | * @param block 更新数据源
34 | *
35 | * @return 表视图
36 | */
37 | - (instancetype)enableDragCellWithDataSourceUpdateBlock:(__autoreleasing MoveCellDataSourceUpdateBlock)block;
38 |
39 | @end
40 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/FoundationExtensions/Week/NSDate+Week.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSDate+Week.m
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/15/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import "NSDate+Week.h"
10 |
11 | static inline NSUInteger dayOfWeek(NSDate *date) {
12 | NSCalendar *calendar = [[NSCalendar alloc]
13 | initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
14 | NSDateComponents *components = [[NSDateComponents alloc] init];
15 | NSInteger unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitWeekday | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
16 | components = [calendar components:unitFlags
17 | fromDate:date];
18 | NSUInteger weekday = [components weekday];
19 | return weekday;
20 | }
21 |
22 |
23 | @implementation NSDate (Week)
24 |
25 | - (NSUInteger)dayOfWeek {
26 | NSUInteger weekday = dayOfWeek(self);
27 | return weekday;
28 | }
29 |
30 | - (NSUInteger)dayOfWeekStartWithMonday {
31 | NSUInteger weekday = dayOfWeek(self);
32 | return weekday - 1;
33 | }
34 |
35 | @end
36 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/CoreAnimationExtensions/ConvenienceAnimation/CAAnimation+Extensions.m:
--------------------------------------------------------------------------------
1 | #import "CAAnimation+Extensions.h"
2 |
3 | #pragma mark - 便捷方法
4 |
5 | @implementation CAAnimation (Convenience)
6 |
7 | + (CAKeyframeAnimation *)keyframeAnimationWithKeyPath:(NSString *)keyPath values:(NSArray *)values duration:(CFTimeInterval)duration repeatCount:(float)repeatCount {
8 | CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:keyPath];
9 | animation.values = values;
10 | animation.duration = duration;
11 | animation.calculationMode = kCAAnimationCubic;
12 | animation.fillMode = kCAFillModeForwards;
13 | return animation;
14 | }
15 |
16 | + (CABasicAnimation *)basicAnimationWithKeyPath:(NSString *)keyPath fromValue:(CGFloat)fromValue toValue:(CGFloat)toValue duration:(CFTimeInterval)duration repeatCount:(float)repeatCount {
17 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:keyPath];
18 | animation.fromValue = [NSNumber numberWithDouble:fromValue];
19 | animation.toValue = [NSNumber numberWithDouble:toValue];
20 | animation.duration = duration;
21 | animation.repeatCount = repeatCount;
22 | return animation;
23 | }
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/FoundationExtensions/Regex/NSString+Regex.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+Regex.h
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/15/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /**
12 | * 整合自 https://github.com/carlbrown/RegexOnNSString
13 | */
14 | @interface NSString (Regex)
15 |
16 | - (NSString *)stringByReplacingRegexPattern:(NSString *)regex withString:(NSString *)replacement;
17 | - (NSString *)stringByReplacingRegexPattern:(NSString *)regex withString:(NSString *)replacement caseInsensitive:(BOOL)ignoreCase;
18 | - (NSString *)stringByReplacingRegexPattern:(NSString *)regex withString:(NSString *)replacement caseInsensitive:(BOOL)ignoreCase treatAsOneLine:(BOOL)assumeMultiLine;
19 | - (NSArray *)stringsByExtractingGroupsUsingRegexPattern:(NSString *)regex;
20 | - (NSArray *)stringsByExtractingGroupsUsingRegexPattern:(NSString *)regex caseInsensitive:(BOOL) ignoreCase treatAsOneLine:(BOOL)assumeMultiLine;
21 | - (BOOL)matchesPatternRegexPattern:(NSString *)regex;
22 | - (BOOL)matchesPatternRegexPattern:(NSString *)regex caseInsensitive:(BOOL)ignoreCase treatAsOneLine:(BOOL)assumeMultiLine;
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/Transform3DAnimation/UIView+Transform3DAnimation.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+Transform3DAnimation.m
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/12/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import "UIView+Transform3DAnimation.h"
10 |
11 | @implementation UIView (Transform3DAnimation)
12 |
13 | - (instancetype)transform3DAnimation {
14 | CATransform3D transform;
15 | transform = CATransform3DMakeRotation( (90.0 * M_PI) / 180, 0.0, 0.7, 0.4);
16 | transform.m34 = 1.0/ -600;
17 |
18 | self.layer.shadowColor = [[UIColor blackColor]CGColor];
19 | self.layer.shadowOffset = CGSizeMake(10, 10);
20 | self.alpha = 0;
21 |
22 | self.layer.transform = transform;
23 | self.layer.anchorPoint = CGPointMake(0, 0.5);
24 |
25 | [UIView animateWithDuration:0.3 animations:^{
26 | self.layer.transform = CATransform3DIdentity;
27 | self.alpha = 1;
28 | self.layer.shadowOffset = CGSizeMake(0, 0);
29 | self.frame = CGRectMake(0, self.frame.origin.y, self.frame.size.width, self.frame.size.height);
30 |
31 | }];
32 |
33 | return self;
34 | }
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/FoundationExtensions/MD5/NSString+MD5.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+MD5.m
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/15/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import "NSString+MD5.h"
10 |
11 | // 整合自:https://gist.github.com/dsibilly/1038500
12 |
13 | #import
14 |
15 | @implementation NSString (MD5)
16 |
17 | - (NSString*)MD5Hash {
18 | // Create a C-style pointer to the UT8-encoded contents of the NSString
19 | const char *pointer = [self UTF8String];
20 |
21 | // Create a buffer array big enough to hold the digest
22 | unsigned char buffer[CC_MD5_DIGEST_LENGTH];
23 |
24 | // Create 16-byte MD5 hash value, store in buffer
25 | // See: CC_MD5(3cc) manpage on OS X & iOS.
26 | CC_MD5(pointer, (CC_LONG)strlen(pointer), buffer);
27 |
28 | // Convert MD5 digest in buffer to an autoreleased NSString of hexidecimal
29 | // values.
30 | NSMutableString *result = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
31 | for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i += 1) {
32 | [result appendFormat:@"%02x", buffer[i]];
33 | }
34 |
35 | return [result copy];
36 | }
37 |
38 | @end
39 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/Controls/Timer/OCKCountDownLabel.h:
--------------------------------------------------------------------------------
1 | //
2 | // WMCountDownLabel.h
3 | // WMObjCsWorld
4 | //
5 | // Created by maginawin on 15/6/17.
6 | // Copyright (c) 2015年 wendong wang. All rights reserved.
7 | //
8 |
9 | /// 支持倒计时的 UILabel, 可以拖控件用, 也可以代码初始化, 在后台继续倒计 (伪)
10 | /// 使用例子:
11 | /// [_countDownLabel setupCountDownSeconds:888];
12 | /// [_countDownLabel start];
13 | /// [_countDownLabel stop];
14 | /// warning : 暂时最高支持 99 分钟 59 秒, 小时还未写, 有空补上
15 |
16 | #import
17 |
18 | @protocol OCKCountDownLabelDelegate
19 |
20 | @optional
21 |
22 | /**
23 | * @brief 倒计时开始
24 | * @param mTag : count down label's tag
25 | */
26 | - (void)countDownLabelStart:(NSInteger)mTag;
27 |
28 | /**
29 | * @brief 倒计时结束
30 | * @param mTag : count down label's tag
31 | */
32 | - (void)countDownLabelStop:(NSInteger)mTag;
33 |
34 | @end
35 |
36 | @interface OCKCountDownLabel : UILabel
37 |
38 | @property (weak, nonatomic) id delegate;
39 |
40 | /**
41 | * @brief 设置倒计时的倒计时间, 建议在未 start 的情况下设置
42 | * @param seconds : 倒计时间, 不要超过 99 分钟, 小时的还没有实现, 有空再来写
43 | */
44 | - (void)setupCountDownSeconds:(NSInteger)seconds;
45 |
46 | /**
47 | * @brief 开始倒计时
48 | */
49 | - (void)start;
50 |
51 | /**
52 | * @brief 结束倒计时
53 | */
54 | - (void)stop;
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/Tab+Navs/UITabBarController+UINavigationController.m:
--------------------------------------------------------------------------------
1 | #import "UITabBarController+UINavigationController.h"
2 |
3 |
4 | @implementation UITabBarController (UINavigationController)
5 |
6 | - (instancetype)addChildViewController:(UIViewController *)childViewController
7 | withNavigationControllerTitle:(NSString *)title
8 | tabBarItemImage:(UIImage *)tabBarItemImage {
9 | return [self addChildViewController:childViewController
10 | withNavigationControllerTitle:title
11 | tabBarItemImage:tabBarItemImage
12 | tabBarItemSelectedImage:nil];
13 | }
14 |
15 | - (instancetype)addChildViewController:(UIViewController *)childViewController
16 | withNavigationControllerTitle:(NSString *)title
17 | tabBarItemImage:(UIImage *)tabBarItemImage
18 | tabBarItemSelectedImage:(UIImage *)tabBarItemSelectedImage {
19 | UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:childViewController];
20 | childViewController.title = title;
21 | childViewController.tabBarItem.image = tabBarItemImage;
22 | childViewController.tabBarItem.selectedImage = tabBarItemSelectedImage;
23 | [self addChildViewController:navigationController];
24 | return self;
25 | }
26 |
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/FoundationExtensions/Palindrome/NSString+Palindrome.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+Palindrome.m
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/15/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import "NSString+Palindrome.h"
10 |
11 | // 整合自:https://gist.github.com/dsibilly/1038500
12 |
13 | @implementation NSString (Palindrome)
14 |
15 | - (BOOL)isPalindrome {
16 | return [NSString stringIsPalindrome:self];
17 | }
18 |
19 | + (BOOL)stringIsPalindrome:(NSString *)aString position:(NSInteger)position {
20 | NSString *_string = [NSString stringWithString:aString];
21 | NSInteger _position = position;
22 |
23 | if (!_string) {
24 | return NO;
25 | }
26 |
27 | NSInteger stringLength = [_string length];
28 | NSString *firstChar = [[_string substringToIndex:_position] substringToIndex:1];
29 | NSString *lastChar = [[_string substringToIndex:(stringLength - 1 - _position)] substringToIndex:1];
30 |
31 | if (_position > (stringLength / 2)) {
32 | return YES;
33 | }
34 |
35 | if (! [firstChar isEqualToString:lastChar]) {
36 | return NO;
37 | }
38 |
39 | return [NSString stringIsPalindrome:_string position:(_position + 1)];
40 | }
41 |
42 | + (BOOL)stringIsPalindrome:(NSString *)aString {
43 | return [NSString stringIsPalindrome:aString position:0];
44 | }
45 |
46 | @end
47 |
--------------------------------------------------------------------------------
/Objective-CArmyKnifeExample/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "29x29",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "29x29",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "40x40",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "40x40",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "76x76",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "76x76",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/Objective-CArmyKnifeExample/GradientViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // GradientViewController.m
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/12/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import "GradientViewController.h"
10 |
11 | @interface GradientViewController ()
12 |
13 | @end
14 |
15 | @implementation GradientViewController
16 |
17 | - (void)viewDidLoad {
18 | [super viewDidLoad];
19 | // Do any additional setup after loading the view.
20 |
21 |
22 | CAGradientLayer *gradientLayer = [CAGradientLayer layer];
23 | gradientLayer.frame = self.view.bounds;
24 | gradientLayer.startPoint = CGPointMake(0.5, 0);
25 | gradientLayer.endPoint = CGPointMake(0.5, 1);
26 |
27 | gradientLayer.colors = @[(__bridge id)[UIColor blueColor].CGColor, (__bridge id)[UIColor redColor].CGColor];
28 |
29 | gradientLayer.locations = @[@0.3, @0.8];
30 |
31 | [self.view.layer addSublayer:gradientLayer];
32 | }
33 |
34 | - (void)didReceiveMemoryWarning {
35 | [super didReceiveMemoryWarning];
36 | // Dispose of any resources that can be recreated.
37 | }
38 |
39 | /*
40 | #pragma mark - Navigation
41 |
42 | // In a storyboard-based application, you will often want to do a little preparation before navigation
43 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
44 | // Get the new view controller using [segue destinationViewController].
45 | // Pass the selected object to the new view controller.
46 | }
47 | */
48 |
49 | @end
50 |
--------------------------------------------------------------------------------
/Objective-CArmyKnifeExample/Supporting Files/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | zh_CN
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | io.github.michael-lfx.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/TableViewSeparator/UITableView+Separator.h:
--------------------------------------------------------------------------------
1 | @import UIKit;
2 |
3 | @interface UITableView (Separator)
4 |
5 | /**
6 | 消除Plain样式下的多余分割线
7 |
8 | Plain样式,行数不够填满整个屏幕时,无数据的Cell也会有分割线,此函数就是处理它们的
9 |
10 | * @return 当前表视图
11 | */
12 | - (instancetype)clearExtraSeparator;
13 |
14 | /**
15 | * 让Cell分割线等于屏幕宽度
16 |
17 | 建议用法:
18 |
19 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
20 |
21 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"TestCell" forIndexPath:indexPath];
22 |
23 | [tableView makeSeparatorEqualToScreenWidthWithCell:cell]
24 |
25 | // Configure the cell...
26 |
27 | .textLabel
28 |
29 | .text = self.dataForTableView[indexPath.row];
30 |
31 | return cell;
32 |
33 | }
34 |
35 | 做这个功能时,我走了些弯路。想过混写dealloc,但是ARC下混写dealloc,听说有较大副作用。
36 |
37 | https://github.com/zhigang1992/ZGParallelView/issues/8
38 |
39 | >Overriding -dealloc in a category is fatal; it replaces the existing implementation, ensuring that every UITableView deallocation will, at best, leak and, at worst, crash or yield undefined behavior.
40 |
41 | >As well, you shouldn't be overriding the KVO methods, either (or any other method of the original class) in a category.
42 |
43 | ```
44 | + (void)load
45 | {
46 | Method origMethod = class_getInstanceMethod([self class], NSSelectorFromString(@"dealloc"));
47 | Method newMethod = class_getInstanceMethod([self class], @selector(my_dealloc));
48 | method_exchangeImplementations(origMethod, newMethod);
49 | }
50 |
51 | - (void)my_dealloc
52 | {
53 | // do your logic here
54 |
55 |
56 | //this calls original dealloc method
57 | [self my_dealloc];
58 | }
59 | ```
60 | *
61 | * @return 当前UITableViewCell
62 | */
63 | - (UITableViewCell *)makeSeparatorEqualToScreenWidthWithCell:(UITableViewCell *)cell;
64 |
65 | @end
66 |
--------------------------------------------------------------------------------
/Objective-CArmyKnifeExample/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/8/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import "ViewController.h"
10 | #import "OCKLoopLoadingView.h"
11 | #import "NavigationBar+Colorful.h"
12 | #import "UIView+BounceAnimation.h"
13 |
14 | @interface ViewController ()
15 |
16 | @property (strong, nonatomic) OCKLoopLoadingView *loadingView;
17 | @property (weak, nonatomic) IBOutlet UIView *viewForBounceAnimation;
18 | @property (strong, nonatomic) NSString *hello;
19 |
20 | @end
21 |
22 | @implementation ViewController
23 |
24 | - (void)viewDidLoad {
25 | [super viewDidLoad];
26 | // Do any additional setup after loading the view, typically from a nib.
27 |
28 | OCKLoopLoadingView *loading = [[OCKLoopLoadingView alloc] initWithFrame:CGRectMake(50, 100, 100, 100)];
29 | [self.view addSubview:loading];
30 | self.loadingView = loading;
31 |
32 | // 透明
33 | self.navigationController.navigationBar.soloColor = [UIColor clearColor];
34 | // 渐变
35 | // UIColor *topColor = [[UIColor blueColor] colorWithAlphaComponent:1];
36 | // UIColor *bottomColor = [[UIColor blueColor] colorWithAlphaComponent:0.2];
37 | // self.navigationController.navigationBar.gradientColors = @[topColor, bottomColor];
38 | self.title = @"我就是测试";
39 | [self setHello:nil];
40 | self.hello = nil;
41 | }
42 |
43 | - (void)viewDidAppear:(BOOL)animated {
44 | [super viewDidAppear:animated];
45 |
46 | [self.loadingView setLoopImage:[UIImage imageNamed:@"loading_loop"]];
47 | [self.loadingView setLogoImage:[UIImage imageNamed:@"loading_monkey"]];
48 | [self.loadingView startAnimating];
49 | }
50 |
51 | - (IBAction)tapBounceAnimationBtn:(id)sender {
52 | [self.viewForBounceAnimation defaultBounceAnimation];
53 | [self.loadingView stopAnimating];
54 | }
55 |
56 | @end
57 |
58 |
59 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/RuntimeExtensions/MethodSwizzConvenienceInterface/MethodSwizzConvenienceInterface.m:
--------------------------------------------------------------------------------
1 | #import "MethodSwizzConvenienceInterface.h"
2 | #import
3 |
4 | void swizz(Class cls, SEL, SEL, Method, Method);
5 | BOOL swizzClassMethod(Class, SEL srcSelector, SEL);
6 | BOOL swizzInstanceMethod(Class, SEL, SEL);
7 | BOOL trySwizz(Class cls, SEL, SEL, Method, Method);
8 |
9 | inline void methodSwizz(Class cls, SEL srcSelector, SEL dstSelector) {
10 | if (swizzInstanceMethod(cls, srcSelector, dstSelector) ||
11 | swizzClassMethod(cls, srcSelector, dstSelector))
12 | {
13 | return;
14 | }
15 | printf("\n=====混写失败:srcSelector或dstSelector对应的Method不存在=====\n\n");
16 | }
17 |
18 | #pragma mark - 私有实现
19 |
20 | inline BOOL swizzInstanceMethod(Class cls, SEL srcSelector, SEL dstSelector) {
21 | Method srcMethod = class_getInstanceMethod(cls, srcSelector);
22 | Method dstMethod = class_getInstanceMethod(cls, dstSelector);
23 | return trySwizz(cls, srcSelector, dstSelector, srcMethod, dstMethod);
24 | }
25 |
26 | inline BOOL swizzClassMethod(Class cls, SEL srcSelector, SEL dstSelector) {
27 | Method srcMethod = class_getClassMethod(cls, srcSelector);
28 | Method dstMethod = class_getClassMethod(cls, dstSelector);
29 | return trySwizz(objc_getMetaClass(class_getName(cls)), srcSelector, dstSelector, srcMethod, dstMethod);
30 | }
31 |
32 | inline BOOL trySwizz(Class cls, SEL srcSelector, SEL dstSelector, Method srcMethod, Method dstMethod) {
33 | if ((srcMethod == NULL || dstMethod == NULL)) {
34 | return FALSE;
35 | }
36 | swizz(cls, srcSelector, dstSelector, srcMethod, dstMethod);
37 | return TRUE;
38 | }
39 |
40 | inline void swizz(Class cls, SEL srcSelector, SEL dstSelector, Method srcMethod, Method dstMethod) {
41 | @synchronized(cls) {
42 | BOOL didAddMethod = class_addMethod(cls, srcSelector, method_getImplementation(dstMethod), method_getTypeEncoding(dstMethod));
43 | if (didAddMethod) {
44 | class_replaceMethod(cls, dstSelector, method_getImplementation(srcMethod), method_getTypeEncoding(srcMethod));
45 | } else {
46 | method_exchangeImplementations(srcMethod, dstMethod);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/FoundationExtensions/Edit/NSString+Edit.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+Edit.m
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/15/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import "NSString+Edit.h"
10 |
11 | #pragma mark - Edit
12 |
13 | // 整合自:https://gist.github.com/dsibilly/1038500
14 |
15 | #ifndef ELLIPSIS
16 | #define ELLIPSIS @"..."
17 | #endif
18 |
19 | @implementation NSString (Edit)
20 |
21 | - (NSString *)reverse {
22 | NSMutableString *reversedString = [NSMutableString stringWithCapacity:[self length]];
23 |
24 | for (NSUInteger i = ([self length] - 1); i > 0; i -= 1) {
25 | [reversedString appendString:[NSString stringWithFormat:@"%C", [self characterAtIndex:i]]];
26 | }
27 |
28 | return reversedString;
29 | }
30 |
31 | + (NSString *)stringTruncatedToWidth:(CGFloat)width withString:(NSString *)string andFont:(UIFont *)font {
32 | return [string truncateToWidth:width withFont:font];
33 | }
34 |
35 | - (NSString *)truncateToWidth:(CGFloat)width withFont:(UIFont *)font {
36 | // Obtain a mutable copy of this NSString.
37 | NSMutableString *truncatedString = [self mutableCopy];
38 |
39 | // If this NSString is longer than the desired width, truncate.
40 | if ([self sizeWithAttributes:@{NSFontAttributeName: font}].width > width) {
41 | // Subtract an ellipsis' worth of width from the desired width to obtain the
42 | // truncation width.
43 | width -= [ELLIPSIS sizeWithAttributes:@{NSFontAttributeName: font}].width;
44 |
45 | // While the string is longer than the truncation width, remove characters
46 | // from the end of the string.
47 | NSRange range = {truncatedString.length - 1, 1};
48 | while ([truncatedString sizeWithAttributes:@{NSFontAttributeName: font}].width > width) {
49 | [truncatedString deleteCharactersInRange:range];
50 | range.location -= 1;
51 | }
52 |
53 | // Once truncation is complete, append an ellipsis to the end of the string.
54 | [truncatedString replaceCharactersInRange:range withString:ELLIPSIS];
55 | }
56 |
57 | return [truncatedString copy];
58 | }
59 |
60 | @end
--------------------------------------------------------------------------------
/Objective-CArmyKnife/FoundationExtensions/Edit/NSString+Edit.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+Edit.h
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/15/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | @import UIKit;
10 |
11 | @interface NSString (Edit)
12 |
13 | /**
14 | -(NSString*)reverse
15 | Reverses the contents of this NSString.
16 |
17 | Example:
18 | NSString *testString = @"stressed";
19 | NSString *testReversed = [testString reverse]; // @"desserts"
20 |
21 | Returns an NSString with the original NSString's contents reversed
22 | */
23 | - (NSString *)reverse;
24 |
25 | /**
26 | + (NSString*)stringTruncatedToWidth:withString:andFont:
27 | Generates a truncated copy of the given NSString, truncated to the desired
28 | width for the given typeface and size.
29 |
30 | width - A CGFloat representing the desired width of the truncated NSString.
31 | string - An NSString object with the content to be truncated.
32 | font - A UIFont object representing the desired typeface and font size.
33 |
34 | Example:
35 | NSString *message = @"Can you hear this long-winded message?";
36 | UIFont *messageFont = [UIFont fontWithName:@"Marker Felt" size:32];
37 | NSString *output = [NSString stringTruncatedToWidth:48.0f
38 | withString:message
39 | andFont:messageFont];
40 |
41 | Returns an NSString containing the truncated string, followed by an ellipsis.
42 | */
43 | + (NSString *)stringTruncatedToWidth:(CGFloat)width
44 | withString:(NSString *)string
45 | andFont:(UIFont *)font;
46 |
47 | /**
48 | - (NSString*)truncateToWidth:withFont:
49 | 返回适应给定字体及其大小的删减后的字符串。Generates an NSString truncated to the indicated width
50 | for a given a typeface and size.
51 |
52 | width - A CGFloat representing the desired width of the truncated NSString.
53 | font - A UIFont object representing the desired typeface and font size.
54 |
55 | Example:
56 | NSString *testString = @"This string is too damn long!"
57 | [testString truncateToWidth:64.0f
58 | withFont:[UIFont fontWithName:@"Helvetica"
59 | size:28]];
60 |
61 | Returns an NSString containing the truncated string, followed by an ellipsis.
62 | */
63 | - (NSString *)truncateToWidth:(CGFloat)width withFont:(UIFont *)font;
64 |
65 | @end
66 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/Tab+Navs/UITabBarController+UINavigationController.h:
--------------------------------------------------------------------------------
1 | @import UIKit;
2 |
3 |
4 | /**
5 | * 快速实现以UITabBarController为基础结构的View骨架
6 | * 建议用法:
7 | * AppleViewController *appleViewController = [AppleViewController new];
8 | * BoyViewController *boyViewController = [BananaViewController new];
9 | * CarViewController *carViewController = [CarViewController new];
10 | * DogViewController *dogViewController = [DogViewController new];
11 | *
12 | * self.window.rootViewController =
13 | * [[[[UITabBarController new]
14 | * addChildViewController:appleViewController withNavigationControllerTitle:@"苹果" ...]
15 | * addChildViewController:boyViewController withNavigationControllerTitle:@"男孩" ...]
16 | * addChildViewController:carViewController withNavigationControllerTitle:@"车" ...]
17 | * addChildViewController:dogViewController withNavigationControllerTitle:@"狗" ...];
18 | */
19 | @interface UITabBarController (UINavigationController)
20 |
21 | /**
22 | * 用UINavigationController将childViewController并加到UITabBarController中
23 | *
24 | * @param childViewController 当成UINavigationController rootViewController的UIViewController
25 | * @param title 导航栏标题
26 | * @param tabBarItemImage 默认TabBarItem图片
27 | *
28 | * @return 持有装载childViewController的UINavigationController的UITabBarController实例
29 | */
30 | - (instancetype)addChildViewController:(UIViewController *)childViewController
31 | withNavigationControllerTitle:(NSString *)title
32 | tabBarItemImage:(UIImage *)tabBarItemImage;
33 | /**
34 | * 用UINavigationController将childViewController并加到UITabBarController中
35 | *
36 | * @param childViewController 当成UINavigationController rootViewController的UIViewController
37 | * @param title 导航栏标题
38 | * @param tabBarItemImage 默认TabBarItem图片
39 | * @param tabBarItemSelectedImage 选中时TabBarItem图片
40 | *
41 | * @return 持有装载childViewController的UINavigationController的UITabBarController实例
42 | */
43 | - (instancetype)addChildViewController:(UIViewController *)childViewController
44 | withNavigationControllerTitle:(NSString *)title
45 | tabBarItemImage:(UIImage *)tabBarItemImage
46 | tabBarItemSelectedImage:(UIImage *)tabBarItemSelectedImage;
47 |
48 | @end
49 |
--------------------------------------------------------------------------------
/Objective-CArmyKnifeExample/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/8/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 | #import "NSDate+Week.h"
11 |
12 | @interface AppDelegate ()
13 |
14 | @end
15 |
16 | @implementation AppDelegate
17 |
18 |
19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
20 | // Override point for customization after application
21 | // [UIViewController printViewControllerHierarchySwitchOn];
22 | return YES;
23 | }
24 |
25 | - (void)applicationWillResignActive:(UIApplication *)application {
26 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
27 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
28 | }
29 |
30 | - (void)applicationDidEnterBackground:(UIApplication *)application {
31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
33 | // if (i % 2) {
34 | // [UIViewController printViewControllerHierarchySwitchOff];
35 | // } else {
36 | // [UIViewController printViewControllerHierarchySwitchOn];
37 | // }
38 | i++;
39 | }
40 |
41 | static int i = 0;
42 |
43 | - (void)applicationWillEnterForeground:(UIApplication *)application {
44 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
45 | }
46 |
47 | - (void)applicationDidBecomeActive:(UIApplication *)application {
48 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
49 | }
50 |
51 | - (void)applicationWillTerminate:(UIApplication *)application {
52 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
53 | }
54 |
55 | @end
56 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/HexStringColor/UIColor+HexString.m:
--------------------------------------------------------------------------------
1 | #import "UIColor+HexString.h"
2 |
3 | @implementation UIColor (HexString)
4 |
5 | + (UIColor *)colorWithHexString:(NSString *)hexString {
6 | NSString *colorString = [[hexString stringByReplacingOccurrencesOfString:@"#" withString:@""] uppercaseString];
7 | CGFloat alpha, red, blue, green;
8 | switch ([colorString length]) {
9 | case 3: // #RGB
10 | alpha = 1.0f;
11 | red = [self colorComponentFrom:colorString start:0 length:1];
12 | green = [self colorComponentFrom:colorString start:1 length:1];
13 | blue = [self colorComponentFrom:colorString start:2 length:1];
14 | break;
15 | case 4: // #ARGB
16 | alpha = [self colorComponentFrom:colorString start:0 length:1];
17 | red = [self colorComponentFrom:colorString start:1 length:1];
18 | green = [self colorComponentFrom:colorString start:2 length:1];
19 | blue = [self colorComponentFrom:colorString start:3 length:1];
20 | break;
21 | case 6: // #RRGGBB
22 | alpha = 1.0f;
23 | red = [self colorComponentFrom:colorString start:0 length:2];
24 | green = [self colorComponentFrom:colorString start:2 length:2];
25 | blue = [self colorComponentFrom:colorString start:4 length:2];
26 | break;
27 | case 8: // #AARRGGBB
28 | alpha = [self colorComponentFrom:colorString start:0 length:2];
29 | red = [self colorComponentFrom:colorString start:2 length:2];
30 | green = [self colorComponentFrom:colorString start:4 length:2];
31 | blue = [self colorComponentFrom:colorString start:6 length:2];
32 | break;
33 | default:
34 | [NSException raise:@"Invalid color value" format:@"Color value %@ is invalid. It should be a hex value of the form #RBG, #ARGB, #RRGGBB, or #AARRGGBB", hexString];
35 | break;
36 | }
37 | return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
38 | }
39 |
40 | + (CGFloat)colorComponentFrom:(NSString *)string start:(NSUInteger)start length:(NSUInteger)length {
41 | NSString *substring = [string substringWithRange:NSMakeRange(start, length)];
42 | NSString *fullHex = length == 2 ? substring : [NSString stringWithFormat:@"%@%@", substring, substring];
43 | unsigned hexComponent;
44 | [[NSScanner scannerWithString:fullHex] scanHexInt:&hexComponent];
45 | return hexComponent / 255.0;
46 | }
47 |
48 | @end
49 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/FoundationExtensions/Base64/NSData+Base64.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSData+Base64.m
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/15/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import "NSData+Base64.h"
10 |
11 | static char base64EncodingTable[64] = {
12 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
13 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
14 | 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
15 | 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
16 | };
17 |
18 | @implementation NSData (Base64)
19 |
20 | - (NSString *)base64String {
21 | unsigned long ixtext, lentext;
22 | long ctremaining;
23 | unsigned char input[3], output[4];
24 | short i, charsonline = 0, ctcopy;
25 | const unsigned char *raw;
26 | NSMutableString *result;
27 |
28 | lentext = self.length;
29 | if (lentext < 1) {
30 | return @"";
31 | }
32 | result = [NSMutableString stringWithCapacity: lentext];
33 | raw = [self bytes];
34 | ixtext = 0;
35 |
36 | while (true) {
37 | ctremaining = lentext - ixtext;
38 | if (ctremaining <= 0) {
39 | break;
40 | }
41 | for (i = 0; i < 3; i++) {
42 | unsigned long ix = ixtext + i;
43 | if (ix < lentext) {
44 | input[i] = raw[ix];
45 | }
46 | else {
47 | input[i] = 0;
48 | }
49 | }
50 | output[0] = (input[0] & 0xFC) >> 2;
51 | output[1] = ((input[0] & 0x03) << 4) | ((input[1] & 0xF0) >> 4);
52 | output[2] = ((input[1] & 0x0F) << 2) | ((input[2] & 0xC0) >> 6);
53 | output[3] = input[2] & 0x3F;
54 | ctcopy = 4;
55 | switch (ctremaining) {
56 | case 1:
57 | ctcopy = 2;
58 | break;
59 | case 2:
60 | ctcopy = 3;
61 | break;
62 | }
63 |
64 | for (i = 0; i < ctcopy; i++) {
65 | [result appendString: [NSString stringWithFormat: @"%c", base64EncodingTable[output[i]]]];
66 | }
67 |
68 | for (i = ctcopy; i < 4; i++) {
69 | [result appendString: @"="];
70 | }
71 |
72 | ixtext += 3;
73 | charsonline += 4;
74 |
75 | if ((self.length > 0) && (charsonline >= self.length)) {
76 | charsonline = 0;
77 | }
78 | }
79 | return result;
80 | }
81 |
82 | @end
83 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/RuntimeExtensions/PrintModelProperty/NSObject+PrintModelProperty.m:
--------------------------------------------------------------------------------
1 | #import "NSObject+PrintModelProperty.h"
2 | #import
3 |
4 |
5 | /**
6 | * 当拓展实现协议时会输出hash、superclass、description、debugDescription等属性
7 | * 干扰阅读,本函数是删除这些额外的信息
8 | */
9 | static inline BOOL isAvoidProperty(id obj, NSString *propertyName) {
10 | NSArray *avoidSelectorNames = @[@"hash", @"superclass", @"description", @"debugDescription"];
11 | return [avoidSelectorNames containsObject:propertyName];
12 | }
13 |
14 | static NSString* makePropertiesAndValuesString(Class cls, id obj) {
15 | NSMutableString *result = [NSMutableString string];
16 |
17 | uint property_count;
18 | objc_property_t *property_list = class_copyPropertyList(cls, &property_count); // 可获取到拓展实现了协议中的属性
19 |
20 | for (int i = 0; i < property_count; i++) {
21 | objc_property_t property = property_list[i];
22 | const char *property_name = property_getName(property); // 这里假设不会返回空字符串
23 | NSString *propertyName = [NSString stringWithCString:property_name encoding:NSASCIIStringEncoding];
24 | if (isAvoidProperty(obj, propertyName)) {
25 | continue;
26 | }
27 | id value = [obj valueForKey:propertyName];
28 | [result appendFormat:@"%@ = %@; ", propertyName, [value readableDescription]];
29 | }
30 |
31 | if (property_list) free(property_list);
32 |
33 | return result;
34 | }
35 |
36 | inline void deleteLastTwoCharacters(NSMutableString *string) {
37 | NSUInteger length = [string length];
38 | if (length > 2) {
39 | [string deleteCharactersInRange:NSMakeRange(length - 2, 2)];
40 | }
41 | }
42 |
43 | @implementation NSObject (PrintModelProperty)
44 |
45 | /**
46 | * 采用非递归实现。尝试了支持所有类,在处理UIKit时遇到取出的属性要么不存在,要么不支持KVC,故放弃。
47 | *
48 | * @return 对象本身定义的属性及其继承的属性与值组成的字符串,如:p1 = v1; p2 = v2
49 | */
50 | - (NSString *)enumeratePropertiesAndValues {
51 | @autoreleasepool {
52 | NSMutableString *result = [NSMutableString string];
53 |
54 | Class cls = self.class;
55 | while (cls != nil && ![cls isEqual:NSObject.class]) {
56 | [result appendString:makePropertiesAndValuesString(cls, self)];
57 | cls = class_getSuperclass(cls);
58 | }
59 | deleteLastTwoCharacters(result);
60 | return [result copy];
61 | }
62 | }
63 |
64 | - (NSString *)autoDescription {
65 | return [NSString stringWithFormat:@"<%@: %p; %@>", NSStringFromClass(self.class), self, [self enumeratePropertiesAndValues]];
66 | }
67 |
68 | - (NSString *)readableDescription {
69 | return [self description];
70 | }
71 |
72 | @end
73 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/ColorfulNavigationBar/NavigationBar+Colorful.m:
--------------------------------------------------------------------------------
1 | #import "NavigationBar+Colorful.h"
2 | #import
3 |
4 | @implementation UINavigationBar (Colorful)
5 |
6 | #pragma mark - 公开接口
7 |
8 | static const char *kSoloColorKey = "kSoloColorKey";
9 |
10 | - (void)setSoloColor:(UIColor *)soloColor {
11 | objc_setAssociatedObject(self, &kSoloColorKey, soloColor, OBJC_ASSOCIATION_RETAIN);
12 | UIImage *image = [self imageWithColorConstructBlock:^(CGRect *rect) {
13 | [soloColor setFill];
14 | UIRectFill(*rect);
15 | }];
16 | [self updateNavigationBarWithImage:image];
17 | }
18 |
19 | - (UIColor *)soloColor {
20 | return (UIColor *)objc_getAssociatedObject(self, &kSoloColorKey);
21 | }
22 |
23 | static const char *kGradientColorsKey = "kGradientColorsKey";
24 | #define kEndPoint 1.5
25 |
26 | - (void)setGradientColors:(NSArray *)gradientColors {
27 | objc_setAssociatedObject(self, &kGradientColorsKey, gradientColors, OBJC_ASSOCIATION_COPY);
28 | UIImage *image = [self imageWithColorConstructBlock:^(CGRect *rect) {
29 | CFMutableArrayRef colors = CFArrayCreateMutable(CFAllocatorGetDefault(), gradientColors.count, nil);
30 | for (UIColor *color in gradientColors) {
31 | CFArrayAppendValue(colors, color.CGColor);
32 | }
33 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
34 | CGFloat locations[] = { 0.0, 1.0 };
35 | CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, colors, locations);
36 | CGPoint startPoint = CGPointMake(rect->size.width / 2, 0);
37 | CGPoint endPoint = CGPointMake(rect->size.width / 2, rect->size.height / kEndPoint);
38 |
39 | CGContextRef context = UIGraphicsGetCurrentContext();
40 | CGContextSaveGState(context);
41 | CGContextAddRect(context, *rect);
42 | CGContextClip(context);
43 | CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, kCGGradientDrawsBeforeStartLocation);
44 | CGContextSetStrokeColorWithColor(context, [[UIColor clearColor] CGColor]);
45 | CGContextRestoreGState(context);
46 | if (colors) {
47 | CFRelease(colors);
48 | }
49 | }];
50 | [self updateNavigationBarWithImage:image];
51 | }
52 |
53 | - (NSArray *)gradientColors {
54 | return (NSArray *)objc_getAssociatedObject(self, &kGradientColorsKey);
55 | }
56 |
57 | #pragma mark - 私有接口
58 |
59 | - (UIImage *)imageWithColorConstructBlock:(void (^)(CGRect *rect))block {
60 | __block UIImage *image = nil;
61 | dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
62 | CGRect rect = CGRectMake(0, 0, 1, 1);
63 | UIGraphicsBeginImageContextWithOptions(rect.size, NO/*透明*/, 0/*device’s main screen*/);
64 | block(&rect);
65 | image = UIGraphicsGetImageFromCurrentImageContext();
66 | UIGraphicsEndImageContext();
67 | });
68 |
69 | return image;
70 | }
71 |
72 | - (void)updateNavigationBarWithImage:(UIImage *)image {
73 | // setShadowImage:需要setBackgroundImage:forBarMetrics:配合
74 | [self setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];
75 | self.shadowImage = [UIImage new]; // 清除导航栏最下面那条线,它起到分割导航栏与下面控件内容的作用。
76 | }
77 |
78 | @end
79 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/FoundationExtensions/Calendar/NSDate+Calendar.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSData+Calendar.m
3 | // WMObjCsWorld
4 | //
5 | // Created by maginawin on 15/6/15.
6 | // Copyright (c) 2015年 wendong wang. All rights reserved.
7 | //
8 |
9 | #import "NSDate+Calendar.h"
10 |
11 | @implementation NSDate (Calendar)
12 |
13 | - (NSInteger)year {
14 | NSCalendar* gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
15 | NSDateComponents* components = [gregorian components:NSCalendarUnitYear fromDate:self];
16 | return components.year;
17 | }
18 |
19 | - (NSInteger)month {
20 | NSCalendar* gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
21 | NSDateComponents* components = [gregorian components:NSCalendarUnitMonth fromDate:self];
22 | return components.month;
23 | }
24 |
25 | - (NSInteger)day {
26 | NSCalendar* gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
27 | NSDateComponents* components = [gregorian components:NSCalendarUnitDay fromDate:self];
28 | return components.day;
29 | }
30 |
31 | - (NSUInteger)numberOfDaysInCurrentMonth {
32 | return [[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:self].length;
33 | }
34 |
35 | - (NSInteger)firstWeekDayInMonth {
36 | NSCalendar* gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
37 | [gregorian setFirstWeekday:1];
38 |
39 | NSDateComponents* comps = [gregorian components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:self];
40 | [comps setDay:1];
41 | NSDate* newDate = [gregorian dateFromComponents:comps];
42 |
43 | return (8 - [gregorian ordinalityOfUnit:NSCalendarUnitWeekday inUnit:NSCalendarUnitWeekOfMonth forDate:newDate]);
44 | }
45 |
46 | - (NSUInteger)numberOfWeeksInCurrentMonth {
47 | NSUInteger weeks = 0;
48 | NSUInteger weekday = [self firstWeekDayInMonth];
49 | if (weekday > 0) {
50 | weeks += 1;
51 | }
52 | NSUInteger monthDays = [self numberOfDaysInCurrentMonth];
53 | weeks = weeks + (monthDays - weekday) / 7;
54 | if ((monthDays - weekday) % 7 > 0) {
55 | weeks += 1;
56 | }
57 | return weeks;
58 | }
59 |
60 | - (NSDate*)lastMonthDate:(NSDate *)date {
61 | NSCalendar* gregorian = [NSCalendar currentCalendar];
62 | NSDateComponents* comps = [gregorian components:NSCalendarUnitWeekday | NSCalendarUnitMonth | NSCalendarUnitYear | NSCalendarUnitDay fromDate:date];
63 | if (comps.month == 1) {
64 | [comps setMonth:12];
65 | [comps setYear:comps.year - 1];
66 | } else {
67 | [comps setMonth:comps.month - 1];
68 | }
69 | return [gregorian dateFromComponents:comps];
70 | }
71 |
72 | - (NSDate*)nextMonthDate:(NSDate *)date {
73 | NSCalendar* gregorian = [NSCalendar currentCalendar];
74 | NSDateComponents* comps = [gregorian components:NSCalendarUnitWeekday | NSCalendarUnitMonth | NSCalendarUnitYear | NSCalendarUnitDay fromDate:date];
75 | if (comps.month == 12) {
76 | [comps setMonth:1];
77 | [comps setYear:comps.year + 1];
78 | } else {
79 | [comps setMonth:comps.month + 1];
80 | }
81 | return [gregorian dateFromComponents:comps];
82 | }
83 |
84 | @end
85 |
--------------------------------------------------------------------------------
/Objective-CArmyKnifeExample/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/FoundationExtensions/Regex/NSString+Regex.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+Regex.m
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/15/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import "NSString+Regex.h"
10 |
11 | @implementation NSString (Regex)
12 |
13 | - (NSString *)stringByReplacingRegexPattern:(NSString *)regex withString:(NSString *)replacement caseInsensitive:(BOOL)ignoreCase {
14 | return [self stringByReplacingRegexPattern:regex withString:replacement caseInsensitive:ignoreCase treatAsOneLine:NO];
15 | }
16 |
17 | - (NSString *)stringByReplacingRegexPattern:(NSString *)regex withString:(NSString *)replacement caseInsensitive:(BOOL)ignoreCase treatAsOneLine:(BOOL)assumeMultiLine {
18 |
19 | NSUInteger options=0;
20 | if (ignoreCase) {
21 | options = options | NSRegularExpressionCaseInsensitive;
22 | }
23 | if (assumeMultiLine) {
24 | options = options | NSRegularExpressionDotMatchesLineSeparators;
25 | }
26 |
27 | NSError *error=nil;
28 | NSRegularExpression *pattern = [NSRegularExpression regularExpressionWithPattern:regex options:options error:&error];
29 | if (error) {
30 | NSLog(@"Error creating Regex: %@",[error description]);
31 | return nil;
32 | }
33 |
34 | NSString *retVal= [pattern stringByReplacingMatchesInString:self options:0 range:NSMakeRange(0, [self length]) withTemplate:replacement];
35 | return retVal;
36 | }
37 |
38 | - (NSString *)stringByReplacingRegexPattern:(NSString *)regex withString:(NSString *)replacement {
39 | return [self stringByReplacingRegexPattern:regex withString:replacement caseInsensitive:NO treatAsOneLine:NO];
40 | }
41 |
42 | - (NSArray *)stringsByExtractingGroupsUsingRegexPattern:(NSString *)regex caseInsensitive:(BOOL)ignoreCase treatAsOneLine:(BOOL)assumeMultiLine {
43 | NSUInteger options=0;
44 | if (ignoreCase) {
45 | options = options | NSRegularExpressionCaseInsensitive;
46 | }
47 | if (assumeMultiLine) {
48 | options = options | NSRegularExpressionDotMatchesLineSeparators;
49 | }
50 |
51 | NSError *error=nil;
52 | NSRegularExpression *pattern = [NSRegularExpression regularExpressionWithPattern:regex options:options error:&error];
53 | if (error) {
54 | NSLog(@"Error creating Regex: %@",[error description]);
55 | return nil;
56 | }
57 |
58 | __block NSMutableArray *retVal = [NSMutableArray array];
59 | [pattern enumerateMatchesInString:self options:0 range:NSMakeRange(0, [self length]) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
60 | //Note, we only want to return the things in parens, so we're skipping index 0 intentionally
61 | for (int i=1; i<[result numberOfRanges]; i++) {
62 | NSString *matchedString=[self substringWithRange:[result rangeAtIndex:i]];
63 | [retVal addObject:matchedString];
64 | }
65 | }];
66 | return retVal;
67 | }
68 |
69 | - (NSArray *)stringsByExtractingGroupsUsingRegexPattern:(NSString *)regex {
70 | return [self stringsByExtractingGroupsUsingRegexPattern:regex caseInsensitive:NO treatAsOneLine:NO];
71 | }
72 |
73 | - (BOOL)matchesPatternRegexPattern:(NSString *)regex caseInsensitive:(BOOL)ignoreCase treatAsOneLine:(BOOL)assumeMultiLine {
74 | NSUInteger options=0;
75 | if (ignoreCase) {
76 | options = options | NSRegularExpressionCaseInsensitive;
77 | }
78 | if (assumeMultiLine) {
79 | options = options | NSRegularExpressionDotMatchesLineSeparators;
80 | }
81 |
82 | NSError *error=nil;
83 | NSRegularExpression *pattern = [NSRegularExpression regularExpressionWithPattern:regex options:options error:&error];
84 | if (error) {
85 | NSLog(@"Error creating Regex: %@",[error description]);
86 | return NO; //Can't possibly match an invalid Regex
87 | }
88 |
89 | return ([pattern numberOfMatchesInString:self options:0 range:NSMakeRange(0, [self length])] > 0);
90 | }
91 |
92 | - (BOOL)matchesPatternRegexPattern:(NSString *)regex {
93 | return [self matchesPatternRegexPattern:regex caseInsensitive:NO treatAsOneLine:NO];
94 | }
95 |
96 | @end
97 |
--------------------------------------------------------------------------------
/Objective-CArmyKnifeExample/SecondViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // SecondViewController.m
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/11/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import "SecondViewController.h"
10 | #import "UIView+Frame.h"
11 | #import "UIView+Transform3DAnimation.h"
12 |
13 | @interface SecondViewController ()
14 |
15 | @property (strong, nonatomic) UIRefreshControl *refreshControl;
16 | @property (strong, nonatomic) UITableView *tableView;
17 | @property (strong, nonatomic) NSArray *array;
18 |
19 | @end
20 |
21 | @implementation SecondViewController
22 |
23 | - (void)viewDidLoad {
24 | [super viewDidLoad];
25 |
26 | self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
27 | [self.view addSubview:self.tableView];
28 |
29 | self.refreshControl = [UIRefreshControl new];
30 | [self.refreshControl addTarget:self action:@selector(refreshView:) forControlEvents:UIControlEventValueChanged];
31 | [self.refreshControl setAttributedTitle:[[NSAttributedString alloc] initWithString:@"松手更新数据"]];
32 | [self.tableView addSubview:self.refreshControl];
33 | self.tableView.dataSource = self;
34 | self.tableView.delegate = self;
35 |
36 | self.tableView.tableHeaderView = [UIView new];
37 |
38 | self.array = @[@"hello", @"world", @"objc", @"programming", @"language",@"hello", @"world", @"objc", @"programming", @"language",@"hello", @"world", @"objc", @"programming", @"language",@"hello", @"world", @"objc", @"programming", @"language",@"hello", @"world", @"objc", @"programming", @"language",@"hello", @"world", @"objc", @"programming", @"language",@"hello", @"world", @"objc", @"programming", @"language",@"hello", @"world", @"objc", @"programming", @"language"];
39 |
40 | UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(foregroundTapped:)];
41 | tap.delegate = self;
42 |
43 | UIScrollView *view = self.tableView;
44 | [view addGestureRecognizer:tap];
45 | }
46 |
47 | - (void)foregroundTapped:(UIGestureRecognizer *)reg {
48 | NSLog(@"%@", reg);
49 | }
50 |
51 | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
52 | {
53 | // 若为UITableViewCellContentView(即点击了tableViewCell),则不截获Touch事件
54 | if ([NSStringFromClass([touch.view class]) isEqualToString:@"UITableViewCellContentView"]) {
55 | return NO;
56 | }
57 | return YES;
58 | }
59 |
60 |
61 | - (void)refreshView:(UIRefreshControl *)refresh {
62 | refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"更新数据中..."];
63 |
64 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
65 | [formatter setDateFormat:@"MMM d, h:mm a"];
66 | NSString *lastUpdated = [NSString stringWithFormat:@"上次更新日期 %@",
67 | [formatter stringFromDate:[NSDate date]]];
68 | refresh.attributedTitle = [[NSAttributedString alloc] initWithString:lastUpdated];
69 |
70 | [self.tableView reloadData];
71 | [refresh endRefreshing];
72 | }
73 |
74 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
75 | // Return the number of rows in the section.
76 | return self.array.count;
77 | }
78 |
79 |
80 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
81 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"TestCell"];
82 | if (!cell) {
83 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"TestCell"];
84 | }
85 |
86 |
87 | // Configure the cell...
88 | cell.textLabel
89 | .text = self.array[indexPath.row];
90 |
91 | return cell;
92 | }
93 |
94 | - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
95 | [cell transform3DAnimation];
96 | }
97 |
98 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
99 | NSLog(@"%@", NSStringFromSelector(_cmd));
100 | }
101 |
102 | @end
103 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/Controls/Loading/OCKLoopLoadingView.m:
--------------------------------------------------------------------------------
1 | #import "OCKLoopLoadingView.h"
2 |
3 | @interface OCKLoopLoadingView ()
4 |
5 | /**
6 | * 外圈旋转图标
7 | */
8 | @property (weak, nonatomic, readonly) UIImageView *loopImageView;
9 |
10 | /**
11 | * 内圈LOGO图标
12 | */
13 | @property (weak, nonatomic, readonly) UIImageView *logoImageView;
14 |
15 | /**
16 | * 默认值0度
17 | */
18 | @property (nonatomic, assign) CGFloat loopAngle;
19 |
20 | /**
21 | * 默认值1.0,完全不透明
22 | */
23 | @property (nonatomic, assign) CGFloat logoAlpha;
24 |
25 | /**
26 | * 默认值360/3 = 120度
27 | */
28 | @property (nonatomic, assign) CGFloat angleStep;
29 |
30 | /**
31 | * 步进:默认值1.0/3.0
32 | */
33 | @property (nonatomic, assign) CGFloat alphaStep;
34 |
35 | /**
36 | * 默认值 NO
37 | */
38 | @property (assign, nonatomic, readwrite) BOOL loading;
39 |
40 | @end
41 |
42 | @implementation OCKLoopLoadingView
43 |
44 | - (instancetype)initWithFrame:(CGRect)frame {
45 | self = [super initWithFrame:frame];
46 | if (self) {
47 | self.backgroundColor = [UIColor clearColor];
48 |
49 | _loopImageView = [self buildImageView];
50 | _logoImageView = [self buildImageView];
51 |
52 | _loopAngle = 0.0;
53 | _logoAlpha = 1.0;
54 | _angleStep = 360/3;
55 | _alphaStep = 1.0/3.0;
56 | _loading = NO;
57 | }
58 | return self;
59 | }
60 |
61 | - (UIImageView *)buildImageView {
62 | UIImageView *imageView = [UIImageView new];
63 | imageView.center = self.center;
64 | [self addSubview:imageView];
65 | [self makeCenterEqualLayoutConstraintForView:imageView];
66 | return imageView;
67 | }
68 |
69 | - (void)makeCenterEqualLayoutConstraintForView:(UIView *)view {
70 | view.translatesAutoresizingMaskIntoConstraints = false;
71 | [self makeCenterEqualLayoutConstraintForView:view attribute:NSLayoutAttributeCenterX];
72 | [self makeCenterEqualLayoutConstraintForView:view attribute:NSLayoutAttributeCenterY];
73 | }
74 |
75 | - (void)makeCenterEqualLayoutConstraintForView:(UIView *)view attribute:(NSLayoutAttribute)attr{
76 | NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:view
77 | attribute:attr
78 | relatedBy:NSLayoutRelationEqual
79 | toItem:self
80 | attribute:attr
81 | multiplier:1
82 | constant:0];
83 | [self addConstraint:constraint];
84 | }
85 |
86 | - (void)loadingAnimation{
87 | static CGFloat duration = 0.25f;
88 | self.loopAngle += self.angleStep;
89 | if (self.logoAlpha <= 0.0 || self.logoAlpha >= 1.0 ) {
90 | self.alphaStep = -self.alphaStep;
91 | }
92 | self.logoAlpha += self.alphaStep;
93 | [UIView animateWithDuration:duration delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
94 | [self updateLoopAngleTransform];
95 | } completion:^(BOOL finished) {
96 | if (self.isLoading && [self superview] != nil) {
97 | [self loadingAnimation];
98 | } else {
99 | [self removeFromSuperview];
100 |
101 | self.loopAngle = 0.0;
102 | self.logoAlpha = 0;
103 | self.alphaStep = ABS(self.alphaStep);
104 | [self updateLoopAngleTransform];
105 | }
106 | }];
107 | }
108 |
109 | - (void)updateLoopAngleTransform {
110 | CGAffineTransform loopAngleTransform = CGAffineTransformMakeRotation(self.loopAngle * (M_PI / 180.0f));
111 | self.loopImageView.transform = loopAngleTransform;
112 | self.logoImageView.alpha = self.logoAlpha;
113 | }
114 |
115 | #pragma mark - 分开接口
116 |
117 | - (void)startAnimating{
118 | self.hidden = NO;
119 | if (self.isLoading) {
120 | return;
121 | }
122 | self.loading = YES;
123 | [self loadingAnimation];
124 | }
125 |
126 | - (void)stopAnimating{
127 | self.hidden = YES;
128 | self.loading = NO;
129 | }
130 |
131 | - (void)setLoopImage:(UIImage *)image {
132 | self.loopImageView.image = image;
133 | }
134 |
135 | - (void)setLogoImage:(UIImage *)image {
136 | self.logoImageView.image = image;
137 | }
138 |
139 | @end
140 |
--------------------------------------------------------------------------------
/Objective-CArmyKnifeExample/TableViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // TableViewController.m
3 | // Objective-CArmyKnifeExample
4 | //
5 | // Created by Michael on 6/10/15.
6 | // Copyright (c) 2015 Michael-lfx. All rights reserved.
7 | //
8 |
9 | #import "TableViewController.h"
10 | #import "UITableView+Separator.h"
11 | #import "UITableView+MoveCell.h"
12 |
13 | @interface TableViewController ()
14 | @property (strong, nonatomic) NSMutableArray *dataForTableView;
15 | @end
16 |
17 | @implementation TableViewController
18 |
19 | - (void)viewDidLoad {
20 | [super viewDidLoad];
21 |
22 | // Uncomment the following line to preserve selection between presentations.
23 | // self.clearsSelectionOnViewWillAppear = NO;
24 |
25 | // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
26 | // self.navigationItem.rightBarButtonItem = self.editButtonItem;
27 | NSArray *array = @[@"hello", @"world", @"objc", @"programming", @"language",@"hello", @"world", @"objc", @"programming", @"language",@"hello", @"world", @"objc", @"programming", @"language",@"hello", @"world", @"objc", @"programming", @"language",@"hello", @"world", @"objc", @"programming", @"language",@"hello", @"world", @"objc", @"programming", @"language",@"hello", @"world", @"objc", @"programming", @"language",@"hello", @"world", @"objc", @"programming", @"language"];
28 |
29 | id x = [array mutableCopy];
30 | NSLog(@"%p", x);
31 | self.dataForTableView = [array mutableCopy];
32 | [self.tableView clearExtraSeparator];
33 | __weak typeof(self) weakSelf = self;
34 | [self.tableView enableDragCellWithDataSourceUpdateBlock:^(NSIndexPath *dstIndexPath, NSIndexPath *srcIndexPath) {
35 | [weakSelf.dataForTableView exchangeObjectAtIndex:dstIndexPath.row withObjectAtIndex:srcIndexPath.row];
36 | }];
37 |
38 | }
39 |
40 | - (void)didReceiveMemoryWarning {
41 | [super didReceiveMemoryWarning];
42 | // Dispose of any resources that can be recreated.
43 | }
44 |
45 | #pragma mark - Table view data source
46 |
47 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
48 | // Return the number of rows in the section.
49 | return self.dataForTableView.count;
50 | }
51 |
52 |
53 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
54 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"TestCell" forIndexPath:indexPath];
55 |
56 | [tableView makeSeparatorEqualToScreenWidthWithCell:cell]
57 | // Configure the cell...
58 | .textLabel
59 | .text = self.dataForTableView[indexPath.row];
60 |
61 | return cell;
62 | }
63 |
64 |
65 | /*
66 | // Override to support conditional editing of the table view.
67 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
68 | // Return NO if you do not want the specified item to be editable.
69 | return YES;
70 | }
71 | */
72 |
73 | /*
74 | // Override to support editing the table view.
75 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
76 | if (editingStyle == UITableViewCellEditingStyleDelete) {
77 | // Delete the row from the data source
78 | [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
79 | } else if (editingStyle == UITableViewCellEditingStyleInsert) {
80 | // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
81 | }
82 | }
83 | */
84 |
85 | /*
86 | // Override to support rearranging the table view.
87 | - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
88 | }
89 | */
90 |
91 | /*
92 | // Override to support conditional rearranging of the table view.
93 | - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
94 | // Return NO if you do not want the item to be re-orderable.
95 | return YES;
96 | }
97 | */
98 |
99 | /*
100 | #pragma mark - Navigation
101 |
102 | // In a storyboard-based application, you will often want to do a little preparation before navigation
103 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
104 | // Get the new view controller using [segue destinationViewController].
105 | // Pass the selected object to the new view controller.
106 | }
107 | */
108 |
109 | @end
110 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/Controls/Timer/OCKCountDownLabel.m:
--------------------------------------------------------------------------------
1 | //
2 | // WMCountDownLabel.m
3 | // WMObjCsWorld
4 | //
5 | // Created by maginawin on 15/6/17.
6 | // Copyright (c) 2015年 wendong wang. All rights reserved.
7 | //
8 |
9 | #import "OCKCountDownLabel.h"
10 | #import "AppDelegate.h"
11 |
12 | @interface OCKCountDownLabel()
13 |
14 | @property (nonatomic) NSInteger seconds;
15 |
16 | @property (strong, nonatomic) NSTimer* countTimer;
17 |
18 | @property (nonatomic) BOOL isStarting;
19 | @property (nonatomic) NSInteger remainSeconds;
20 | @property (nonatomic) NSDate* dateEnterBackground;
21 |
22 | @end
23 |
24 | @implementation OCKCountDownLabel
25 |
26 | - (id)initWithCoder:(NSCoder *)aDecoder {
27 | self = [super initWithCoder:aDecoder];
28 | if (self) {
29 |
30 | }
31 | return self;
32 | }
33 |
34 | - (id)initWithFrame:(CGRect)frame {
35 | self = [super initWithFrame:frame];
36 | if (self) {
37 | [self setupDefaultValues];
38 | }
39 | return self;
40 | }
41 |
42 | - (void)awakeFromNib {
43 | [self setupDefaultValues];
44 | }
45 |
46 | #pragma mark - Out methods
47 |
48 | - (void)setupCountDownSeconds:(NSInteger)seconds {
49 | _seconds = seconds;
50 | _remainSeconds = _seconds;
51 |
52 | [self showLabelTextWithSeconds:_seconds];
53 | }
54 |
55 | - (void)start {
56 | if (!_isStarting) {
57 | _isStarting = YES;
58 |
59 | [self handleCountDown];
60 |
61 | _countTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(handleCountDown) userInfo:nil repeats:YES];
62 |
63 | @try {
64 | [_delegate countDownLabelStart:self.tag];
65 | }
66 | @catch (NSException *exception) {
67 | NSLog(@"delegate countDownLabelStart exception : %@", exception);
68 | }
69 | @finally {
70 |
71 | }
72 | }
73 | }
74 |
75 | - (void)stop {
76 | _isStarting = NO;
77 |
78 | _remainSeconds = _seconds;
79 | [self showLabelTextWithSeconds:_seconds];
80 |
81 | if (_countTimer.isValid) {
82 | [_countTimer invalidate];
83 | _countTimer = nil;
84 | }
85 |
86 | @try {
87 | [_delegate countDownLabelStop:self.tag];
88 | }
89 | @catch (NSException *exception) {
90 | NSLog(@"delegate countDownLabelStop exception : %@", exception);
91 | }
92 | @finally {
93 |
94 | }
95 | }
96 |
97 | - (void)pause {
98 |
99 | }
100 |
101 | #pragma mark - Assistor
102 |
103 | /**
104 | * @brief 初始化, 默认值与视图, 配置等
105 | */
106 | - (void)setupDefaultValues {
107 | [self setupNotificationForEnterBackground];
108 |
109 | _isStarting = NO;
110 | _seconds = 30;
111 | _remainSeconds = _seconds;
112 |
113 | [self showLabelTextWithSeconds:_seconds];
114 |
115 | _countTimer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(handleCountDown) userInfo:nil repeats:YES];
116 | }
117 |
118 | /**
119 | * @brief 添加后台监听, 即后台支持
120 | */
121 | - (void)setupNotificationForEnterBackground {
122 | [[NSNotificationCenter defaultCenter] removeObserver:self];
123 | [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *note) {
124 | _dateEnterBackground = [NSDate date];
125 | }];
126 | [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *note) {
127 | NSTimeInterval timeInterval = [[NSDate date] timeIntervalSinceDate:_dateEnterBackground];
128 | if (_isStarting) {
129 | _remainSeconds -= timeInterval;
130 | }
131 | }];
132 | }
133 |
134 | /**
135 | * @brief 倒计时每秒减 1 秒, 作用于 mTimer
136 | */
137 | - (void)handleCountDown {
138 | if (!_isStarting) {
139 | [self showLabelTextWithSeconds:_seconds];
140 | return;
141 | }
142 |
143 | // 自然结束
144 | if (_remainSeconds <= 0) {
145 | [self stop];
146 | return;
147 | }
148 |
149 | [self showLabelTextWithSeconds:_remainSeconds];
150 |
151 | _remainSeconds--;
152 | }
153 |
154 | /**
155 | * @brief 根据传入的秒数来改变 Label.text, 暂时只支持 mm : ss 格式, 所以不要超过 99 分钟
156 | * @param seconds : 需要显示的秒数
157 | */
158 | - (void)showLabelTextWithSeconds:(NSInteger)seconds {
159 | NSString* minString, * secondString;
160 |
161 | NSInteger min = seconds / 60;
162 | if (min < 10) {
163 | minString = [NSString stringWithFormat:@"0%zi", min];
164 | } else {
165 | minString = [NSString stringWithFormat:@"%zi", min];
166 | }
167 |
168 | NSInteger second = seconds % 60;
169 | if (second < 10) {
170 | secondString = [NSString stringWithFormat:@"0%zi", second];
171 | } else {
172 | secondString = [NSString stringWithFormat:@"%zi", second];
173 | }
174 |
175 | NSString* time = [NSString stringWithFormat:@"%@ : %@", minString, secondString];
176 |
177 | self.text = time;
178 | }
179 |
180 | @end
181 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/FoundationExtensions/UIDevice+Extensions.m:
--------------------------------------------------------------------------------
1 | //#import "UIDevice+Extensions.h"
2 | //
3 | //#include // Per msqr
4 | //#include
5 | //#include
6 | //#include
7 | //
8 | //@interface UIDevice(Private)
9 | //
10 | //- (NSString *) macaddress;
11 | //
12 | //@end
13 | //
14 | //@implementation UIDevice (IdentifierAddition)
15 | //
16 | //////////////////////////////////////////////////////////////////////////////////
17 | //#pragma mark -
18 | //#pragma mark Private Methods
19 | //
20 | //// Return the local MAC addy
21 | //// Courtesy of FreeBSD hackers email list
22 | //// Accidentally munged during previous update. Fixed thanks to erica sadun & mlamb.
23 | //- (NSString *) macaddress{
24 | //
25 | // int mib[6];
26 | // size_t len;
27 | // char *buf;
28 | // unsigned char *ptr;
29 | // struct if_msghdr *ifm;
30 | // struct sockaddr_dl *sdl;
31 | //
32 | // mib[0] = CTL_NET;
33 | // mib[1] = AF_ROUTE;
34 | // mib[2] = 0;
35 | // mib[3] = AF_LINK;
36 | // mib[4] = NET_RT_IFLIST;
37 | //
38 | // if ((mib[5] = if_nametoindex("en0")) == 0) {
39 | // printf("Error: if_nametoindex error\n");
40 | // return NULL;
41 | // }
42 | //
43 | // if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
44 | // printf("Error: sysctl, take 1\n");
45 | // return NULL;
46 | // }
47 | //
48 | // if ((buf = malloc(len)) == NULL) {
49 | // printf("Could not allocate memory. error!\n");
50 | // return NULL;
51 | // }
52 | //
53 | // if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
54 | // printf("Error: sysctl, take 2");
55 | // free(buf);
56 | // return NULL;
57 | // }
58 | //
59 | // ifm = (struct if_msghdr *)buf;
60 | // sdl = (struct sockaddr_dl *)(ifm + 1);
61 | // ptr = (unsigned char *)LLADDR(sdl);
62 | // NSString *outstring = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X",
63 | // *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)];
64 | // free(buf);
65 | //
66 | // return outstring;
67 | //}
68 | //
69 | //////////////////////////////////////////////////////////////////////////////////
70 | //#pragma mark -
71 | //#pragma mark Public Methods
72 | //
73 | //- (NSString *) SFAgentUniqueDeviceIdentifier{
74 | // NSString *macaddress = [[UIDevice currentDevice] macaddress];
75 | // NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
76 | //
77 | // NSString *stringToHash = [NSString stringWithFormat:@"%@%@",macaddress,bundleIdentifier];
78 | // NSString *uniqueIdentifier = [UtilityHelper md5:stringToHash];
79 | //
80 | // return uniqueIdentifier;
81 | //}
82 | //
83 | //- (NSString *) uniqueGlobalDeviceIdentifier{
84 | // NSString *macaddress = [[UIDevice currentDevice] macaddress];
85 | // NSString *uniqueIdentifier = [UtilityHelper md5:macaddress];
86 | //
87 | // return uniqueIdentifier;
88 | //}
89 | //
90 | //
91 | ////- (BOOL)isJailbroken
92 | ////{
93 | //// BOOL jailbroken = NO;
94 | //// NSString *cydiaPath = @"/Applications/Cydia.app";
95 | ////
96 | //// NSString *aptPath = @"/private/var/lib/apt/";
97 | ////
98 | //// if ([[NSFileManager defaultManager] fileExistsAtPath:cydiaPath]) {
99 | ////
100 | //// jailbroken = YES;
101 | ////
102 | //// }
103 | ////
104 | //// if ([[NSFileManager defaultManager] fileExistsAtPath:aptPath]) {
105 | ////
106 | //// jailbroken = YES;
107 | ////
108 | //// }
109 | ////
110 | //// return jailbroken;
111 | ////}
112 | //
113 | //- (NSString *) platform
114 | //{
115 | // size_t size;
116 | //
117 | // sysctlbyname("hw.machine", NULL, &size, NULL, 0);
118 | //
119 | // char *machine = malloc(size);
120 | //
121 | // sysctlbyname("hw.machine", machine, &size, NULL, 0);
122 | //
123 | // NSString *platform = [NSString stringWithCString:machine encoding:NSUTF8StringEncoding];
124 | //
125 | // free(machine);
126 | //
127 | // return platform;
128 | //}
129 | //
130 | //- (NSString *) platformString
131 | //{
132 | // NSString *platform = [self platform];
133 | //
134 | // if ([platform isEqualToString:@"iPhone1,1"]) return @"iPhone 1G";
135 | // if ([platform isEqualToString:@"iPhone1,2"]) return @"iPhone 3G";
136 | // if ([platform isEqualToString:@"iPhone2,1"]) return @"iPhone 3GS";
137 | // if ([platform isEqualToString:@"iPhone3,1"]) return @"iPhone 4";
138 | // if ([platform isEqualToString:@"iPhone3,2"] || [platform isEqualToString:@"iPhone3,3"]) return @"iPhone 4";
139 | // if ([platform isEqualToString:@"iPhone4,1"]) return @"iPhone 4S";
140 | // if ([platform isEqualToString:@"iPhone5,2"]) return @"iPhone 5";
141 | // if ([platform isEqualToString:@"iPhone5,3"] || [platform isEqualToString:@"iPhone5,4"]) {
142 | // return @"iPhone 5C";//add by tongkun
143 | // }
144 | // if ([platform isEqualToString:@"iPhone6,2"] || [platform isEqualToString:@"iPhone6,1"]) {
145 | // return @"iPhone 5S";//add by tongkun
146 | // }
147 | // if ([platform isEqualToString:@"iPod1,1"]) return @"iPod Touch 1G";
148 | // if ([platform isEqualToString:@"iPod2,1"]) return @"iPod Touch 2G";
149 | // if ([platform isEqualToString:@"iPod3,1"]) return @"iPod Touch 3G";
150 | // if ([platform isEqualToString:@"iPod4,1"]) return @"iPod Touch 4G";
151 | // if ([platform isEqualToString:@"iPod5,1"]) return @"iPod Touch 5G";
152 | // if ([platform isEqualToString:@"iPad1,1"]) return @"iPad";
153 | // if ([platform isEqualToString:@"iPad2,1"]) return @"iPad 2 (WiFi)";
154 | // if ([platform isEqualToString:@"iPad2,2"]) return @"iPad 2 (GSM)";
155 | // if ([platform isEqualToString:@"iPad2,3"]) return @"iPad 2 (CDMA)";
156 | // if ([platform isEqualToString:@"iPad2,5"]) return @"iPad mini (WiFi)";
157 | // if ([platform isEqualToString:@"i386"] || [platform isEqualToString:@"x86_64"])
158 | // return @"Simulator";
159 | // return @"";
160 | //}
161 | //
162 | //@end
163 |
--------------------------------------------------------------------------------
/Objective-CArmyKnife/UIKitExtensions/MoveCell/UITableView+MoveCell.m:
--------------------------------------------------------------------------------
1 | #import "UITableView+MoveCell.h"
2 | #import
3 |
4 | @implementation UITableView (MoveCell)
5 |
6 | - (instancetype)enableDragCellWithDataSourceUpdateBlock:(MoveCellDataSourceUpdateBlock)block {
7 | UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(moveCell_longPressGestureRecognizer:)];
8 | [self addGestureRecognizer:longPress];
9 | objc_setAssociatedObject(self, @selector(longPressGestureRecognizer), longPress, OBJC_ASSOCIATION_RETAIN);
10 | [self setMoveCellDataSourceUpdateBlock:block];
11 |
12 | return self;
13 | }
14 |
15 | - (UILongPressGestureRecognizer *)longPressGestureRecognizer {
16 | return objc_getAssociatedObject(self, @selector(longPressGestureRecognizer));
17 | }
18 |
19 | - (MoveCellDataSourceUpdateBlock)moveCellDataSourceUpdateBlock {
20 | return objc_getAssociatedObject(self, @selector(moveCellDataSourceUpdateBlock));
21 | }
22 |
23 | - (void)setMoveCellDataSourceUpdateBlock:(MoveCellDataSourceUpdateBlock)moveCellDataSourceUpdateBlock {
24 | objc_setAssociatedObject(self, @selector(moveCellDataSourceUpdateBlock), moveCellDataSourceUpdateBlock, OBJC_ASSOCIATION_COPY);
25 | }
26 |
27 | - (void)moveCell_longPressGestureRecognizer:(id)sender {
28 | UILongPressGestureRecognizer *longPress = (UILongPressGestureRecognizer *)sender;
29 | if (longPress != self.longPressGestureRecognizer) {
30 | return;
31 | }
32 | UIGestureRecognizerState state = longPress.state;
33 |
34 | // 手指位置
35 | CGPoint location = [longPress locationInView:self];
36 | // 手指位置对应的单元格索引,当按在section header等非普通cell时,索引无效
37 | NSIndexPath *indexPath = [self indexPathForRowAtPoint:location];
38 |
39 | static UIView *snapshot = nil; ///< A snapshot of the row user is moving.
40 | static NSIndexPath *sourceIndexPath = nil; ///< Initial index path, where gesture begins.
41 |
42 | switch (state) {
43 | case UIGestureRecognizerStateBegan: {
44 | if (indexPath) {
45 | sourceIndexPath = indexPath;
46 |
47 | UITableViewCell *cell = [self cellForRowAtIndexPath:indexPath];
48 |
49 | // Take a snapshot of the selected row using helper method.
50 | snapshot = [self snapshotFromView:cell];
51 |
52 | // Add the snapshot as subview, centered at cell's center...
53 | __block CGPoint center = cell.center;
54 | snapshot.center = center;
55 | snapshot.alpha = 0.0;
56 | [self addSubview:snapshot];
57 | [UIView animateWithDuration:0.25 animations:^{
58 |
59 | // Offset for gesture location.
60 | center.y = location.y;
61 | snapshot.center = center;
62 | snapshot.transform = CGAffineTransformMakeScale(1.05, 1.05);
63 | snapshot.alpha = 0.98;
64 | cell.alpha = 0.0;
65 |
66 | } completion:^(BOOL finished) {
67 |
68 | cell.hidden = YES;
69 |
70 | }];
71 | }
72 | break;
73 | }
74 |
75 | case UIGestureRecognizerStateChanged: {
76 | CGPoint center = snapshot.center;
77 | center.y = location.y;
78 | snapshot.center = center;
79 |
80 | // Is destination valid and is it different from source?
81 | if (indexPath && ![indexPath isEqual:sourceIndexPath]) {
82 |
83 | @autoreleasepool {
84 | // ... update data source.
85 | if ([self moveCellDataSourceUpdateBlock]) {
86 | [self moveCellDataSourceUpdateBlock](indexPath, sourceIndexPath);
87 | }
88 | }
89 |
90 | // ... move the rows.
91 | [self moveRowAtIndexPath:sourceIndexPath toIndexPath:indexPath];
92 |
93 | // ... and update source so it is in sync with UI changes.
94 | sourceIndexPath = indexPath;
95 | }
96 | break;
97 | }
98 |
99 | default: {
100 | // Clean up.
101 | UITableViewCell *cell = [self cellForRowAtIndexPath:sourceIndexPath];
102 | cell.hidden = NO;
103 | cell.alpha = 0.0;
104 |
105 | [UIView animateWithDuration:0.25 animations:^{
106 |
107 | snapshot.center = cell.center;
108 | snapshot.transform = CGAffineTransformIdentity;
109 | snapshot.alpha = 0.0;
110 | cell.alpha = 1.0;
111 |
112 | } completion:^(BOOL finished) {
113 |
114 | sourceIndexPath = nil;
115 | [snapshot removeFromSuperview];
116 | snapshot = nil;
117 |
118 | }];
119 |
120 | break;
121 | }
122 | }
123 | [self reloadData];
124 | }
125 |
126 | #pragma mark - Helper methods
127 |
128 | /** @brief Returns a customized snapshot of a given view. */
129 | - (UIView *)snapshotFromView:(UIView *)inputView {
130 |
131 | // Make an image from the input view.
132 | UIGraphicsBeginImageContextWithOptions(inputView.bounds.size, NO, 0);
133 | [inputView.layer renderInContext:UIGraphicsGetCurrentContext()];
134 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
135 | UIGraphicsEndImageContext();
136 |
137 | // Create an image view.
138 | UIView *snapshot = [[UIImageView alloc] initWithImage:image];
139 |
140 | snapshot.layer.shadowOffset = CGSizeMake(-5.0, 0.0);
141 | snapshot.layer.shadowRadius = 5.0;
142 | snapshot.layer.shadowOpacity = 0.4;
143 |
144 | return snapshot;
145 | }
146 |
147 | @end
148 |
--------------------------------------------------------------------------------
/Objective-CArmyKnifeExample/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
28 |
37 |
38 |
39 |
40 |
41 |
50 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
109 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
--------------------------------------------------------------------------------