Commit d0fb816a authored by jz's avatar jz

添加全局查看是否是ispush上报埋点用 这个地方一期加的时候 准备放在各业务代码中 后考虑还是放在gmrouter中

parent 0ffb5668
......@@ -324,13 +324,27 @@
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-GMRouter_Example/Pods-GMRouter_Example-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/GMCache/GMCache.framework",
"${BUILT_PRODUCTS_DIR}/GMKit/GMKit.framework",
"${BUILT_PRODUCTS_DIR}/GMPhobos/GMPhobos.framework",
"${BUILT_PRODUCTS_DIR}/GMRouter/GMRouter.framework",
"${BUILT_PRODUCTS_DIR}/MJExtension/MJExtension.framework",
"${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework",
"${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework",
"${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework",
"${BUILT_PRODUCTS_DIR}/TMCache/TMCache.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GMCache.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GMKit.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GMPhobos.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GMRouter.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJExtension.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SnapKit.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/TMCache.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
......
use_frameworks!
platform :ios, '8.0'
#require 'pry'
#open source
source 'https://github.com/CocoaPods/Specs.git'
#our company
source 'git@git.wanmeizhensuo.com:gengmeiios/GMSpecs.git'
target 'GMRouter_Example' do
pod 'GMRouter', :path => '../'
......
PODS:
- GMRouter (0.1.2):
- GMCache (1.0.1):
- TMCache (= 2.1.0)
- GMKit (1.2.5):
- GMKit/Category (= 1.2.5)
- GMKit/Color (= 1.2.5)
- GMKit/Constant (= 1.2.5)
- GMKit/FDFullscreenPopGesture (= 1.2.5)
- GMKit/Kit (= 1.2.5)
- GMKit/Protocol (= 1.2.5)
- Masonry
- SDWebImage
- SnapKit
- GMKit/Category (1.2.5):
- GMKit/Color (= 1.2.5)
- GMKit/Constant (= 1.2.5)
- GMKit/Protocol (= 1.2.5)
- Masonry
- SDWebImage
- SnapKit
- GMKit/Color (1.2.5):
- Masonry
- SDWebImage
- SnapKit
- GMKit/Constant (1.2.5):
- Masonry
- SDWebImage
- SnapKit
- GMKit/FDFullscreenPopGesture (1.2.5):
- Masonry
- SDWebImage
- SnapKit
- GMKit/Kit (1.2.5):
- GMKit/Category (= 1.2.5)
- GMKit/Color (= 1.2.5)
- GMKit/Constant (= 1.2.5)
- GMKit/Protocol (= 1.2.5)
- Masonry
- SDWebImage
- SnapKit
- GMKit/Protocol (1.2.5):
- Masonry
- SDWebImage
- SnapKit
- GMPhobos (1.3.5):
- GMCache
- GMKit
- GMRouter (0.1.5):
- GMPhobos
- MJExtension
- Masonry (1.1.0)
- MJExtension (3.2.1)
- SDWebImage (5.6.1):
- SDWebImage/Core (= 5.6.1)
- SDWebImage/Core (5.6.1)
- SnapKit (4.2.0)
- TMCache (2.1.0)
DEPENDENCIES:
- GMRouter (from `../`)
SPEC REPOS:
https://github.com/cocoapods/specs.git:
"git@git.wanmeizhensuo.com:gengmeiios/GMSpecs.git":
- GMCache
- GMKit
- GMPhobos
https://github.com/CocoaPods/Specs.git:
- Masonry
- MJExtension
- SDWebImage
- SnapKit
- TMCache
EXTERNAL SOURCES:
GMRouter:
:path: "../"
SPEC CHECKSUMS:
GMRouter: e5ee4c93aee2f94f977a847f13ec1371a5fbd372
GMCache: b78d8e46db864405e91d226ce640cc80d966c611
GMKit: 239609b2a4ea4d36d34fc74f08210ad47e260bd3
GMPhobos: 1e2d68c456b69bf156276d7242877498107474db
GMRouter: 347439b99a04d744714992d439d70a7d0afa80e9
Masonry: 678fab65091a9290e40e2832a55e7ab731aad201
MJExtension: 635f2c663dcb1bf76fa4b715b2570a5710aec545
SDWebImage: 7edb9c3ea661e77a66661f7f044de8c1b55d1120
SnapKit: fe8a619752f3f27075cc9a90244d75c6c3f27e2a
TMCache: 95ebcc9b3c7e90fb5fd8fc3036cba3aa781c9bed
PODFILE CHECKSUM: bcbc555b81a3b21a917383786de0d49ebef33013
PODFILE CHECKSUM: ea22114f5446c23313cc25de2cf84ff760e403e0
COCOAPODS: 1.7.4
COCOAPODS: 1.9.0
//
// GMCache.h
// Gengmei
//
// Created by Thierry on 1/5/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <TMCache/TMCache.h>
@interface GMCache : NSObject
#pragma mark - 异步磁盘读写操作
/*** @brief 由对应的键获取对应的缓存数据*/
+ (void)storeObjectAtDiskWithkey:(NSString *)key
object:(id <NSCoding>)object
block:(TMDiskCacheObjectBlock)block;
/*** @brief 给特定的键,标记缓存数据并缓存*/
+ (void)fetchObjectAtDiskWithkey:(NSString *)key
block:(TMDiskCacheObjectBlock)block;
/*** @brief 删除特定的键,对应的缓存数据*/
+ (void)removeObjectAtDiskWithkey:(NSString *)key
block:(TMDiskCacheObjectBlock)block;
/*** @brief 清空所有的缓存数据*/
+ (void)removeAllObjectsAtDiskWithBlock:(TMDiskCacheBlock)block;
#pragma mark - 同步磁盘读写操作
/*** @brief 由对应的键获取对应的缓存数据*/
+ (void)storeObjectAtDiskWithkey:(NSString *)key
object:(id <NSCoding>)object;
/*** @brief 给特定的键,标记缓存数据并缓存*/
+ (id)fetchObjectAtDiskWithkey:(NSString *)key;
/*** @brief 删除特定的键,对应的缓存数据*/
+ (void)removeObjectAtDiskWithkey:(NSString *)key;
/*** @brief 清空所有的缓存数据*/
+ (void)removeAllObjectsAtDisk;
#pragma mark - 异步内存读写操作
/*** @brief 由对应的键获取对应的缓存数据*/
+ (void)storeObjectAtMemoryWithkey:(NSString *)key
object:(id <NSCoding>)object
block:(TMMemoryCacheObjectBlock)block;
/*** @brief 给特定的键,标记缓存数据并缓存*/
+ (void)fetchObjectAtMemoryWithkey:(NSString *)key
block:(TMMemoryCacheObjectBlock)block;
/*** @brief 删除特定的键,对应的缓存数据*/
+ (void)removeObjectAtMemoryWithkey:(NSString *)key
block:(TMMemoryCacheObjectBlock)block;
/*** @brief 清空所有的缓存数据*/
+ (void)removeAllObjectsAtMemoryWithBlock:(TMMemoryCacheBlock)block;
#pragma mark - 同步内存读写操作
/*** @brief 由对应的键获取对应的缓存数据*/
+ (void)storeObjectAtMemoryWithkey:(NSString *)key
object:(id)object;
/*** @brief 给特定的键,标记缓存数据并缓存*/
+ (id)fetchObjectAtMemoryWithkey:(NSString *)key;
/*** @brief 删除特定的键,对应的缓存数据*/
+ (void)removeObjectAtMemoryWithkey:(NSString *)key;
/*** @brief 清空所有的缓存数据*/
+ (void)removeAllObjectsAtMemory;
#pragma mark - 这里将数据缓存到Ducument目录下。异步
+ (void)storeObjectAtDocumentPathWithkey:(NSString *)key
object:(id <NSCoding>)object
block:(TMDiskCacheObjectBlock)block;
+ (void)fetchObjectAtDocumentPathWithkey:(NSString *)key
block:(TMDiskCacheObjectBlock)block;
+ (void)removeObjectAtDocumentPathWithkey:(NSString *)key
block:(TMDiskCacheObjectBlock)block;
+ (void)removeAllObjectsAtDocumentPathWithBlock:(TMDiskCacheBlock)block;
#pragma mark - 这里将数据缓存到Ducument目录下。同步内存读写操作
+ (void)storeObjectAtDocumentPathWithkey:(NSString *)key
object:(id <NSCoding>)object;
+ (id)fetchObjectAtDocumentPathWithkey:(NSString *)key;
+ (void)removeObjectAtDocumentPathWithkey:(NSString *)key;
+ (void)removeAllObjectsAtDocumentPath;
@end
//
// GMCache.m
// Gengmei
//
// Created by Thierry on 1/5/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import "GMCache.h"
@interface WMDocumentCache : TMCache
@end
@implementation GMCache
+ (void)storeObjectAtDiskWithkey:(NSString *)key object:(id <NSCoding>)object block:(TMDiskCacheObjectBlock)block{
NSAssert([GMCache gmCache_isNonEmpty:key], @"key不能为空");
if (![GMCache gmCache_isNonEmpty:key]) {
return;
}
[[TMCache sharedCache].diskCache setObject:object forKey:key block:block];
}
+ (void)fetchObjectAtDiskWithkey:(NSString *)key block:(TMDiskCacheObjectBlock)block{
NSAssert([GMCache gmCache_isNonEmpty:key], @"key不能为空");
if (![GMCache gmCache_isNonEmpty:key]) {
return;
}
[[TMCache sharedCache].diskCache objectForKey:key block:block];
}
+ (void)removeObjectAtDiskWithkey:(NSString *)key block:(TMDiskCacheObjectBlock)block{
NSAssert([GMCache gmCache_isNonEmpty:key], @"key不能为空");
if (![GMCache gmCache_isNonEmpty:key]) {
return;
}
[[TMCache sharedCache].diskCache removeObjectForKey:key block:block];
}
+ (void)removeAllObjectsAtDiskWithBlock:(TMDiskCacheBlock)block{
[[TMCache sharedCache].diskCache removeAllObjects:block];
}
+ (void)storeObjectAtDiskWithkey:(NSString *)key object:(id <NSCoding>)object{
NSAssert([GMCache gmCache_isNonEmpty:key], @"key不能为空");
if (![GMCache gmCache_isNonEmpty:key]) {
return;
}
[[TMCache sharedCache].diskCache setObject:object forKey:key];
}
+ (id)fetchObjectAtDiskWithkey:(NSString *)key{
NSAssert([GMCache gmCache_isNonEmpty:key], @"key不能为空");
if (![GMCache gmCache_isNonEmpty:key]) {
return nil;
}
return [[TMCache sharedCache].diskCache objectForKey:key];
}
+ (void)removeObjectAtDiskWithkey:(NSString *)key{
NSAssert([GMCache gmCache_isNonEmpty:key], @"key不能为空");
if (![GMCache gmCache_isNonEmpty:key]) {
return;
}
[[TMCache sharedCache].diskCache removeObjectForKey:key];
}
+ (void)removeAllObjectsAtDisk{
[[TMCache sharedCache].diskCache removeAllObjects];
}
+ (void)storeObjectAtMemoryWithkey:(NSString *)key object:(id <NSCoding>)object block:(TMMemoryCacheObjectBlock)block{
NSAssert([GMCache gmCache_isNonEmpty:key], @"key不能为空");
if (![GMCache gmCache_isNonEmpty:key]) {
return;
}
[[TMCache sharedCache].memoryCache setObject:object forKey:key block:block];
}
+ (void)fetchObjectAtMemoryWithkey:(NSString *)key block:(TMMemoryCacheObjectBlock)block{
NSAssert([GMCache gmCache_isNonEmpty:key], @"key不能为空");
if (![GMCache gmCache_isNonEmpty:key]) {
return;
}
[[TMCache sharedCache].memoryCache objectForKey:key block:block];
}
+ (void)removeObjectAtMemoryWithkey:(NSString *)key block:(TMMemoryCacheObjectBlock)block{
NSAssert([GMCache gmCache_isNonEmpty:key], @"key不能为空");
if (![GMCache gmCache_isNonEmpty:key]) {
return;
}
[[TMCache sharedCache].memoryCache removeObjectForKey:key block:block];
}
+ (void)removeAllObjectsAtMemoryWithBlock:(TMMemoryCacheBlock)block{
[[TMCache sharedCache].memoryCache removeAllObjects:block];
}
+ (void)storeObjectAtMemoryWithkey:(NSString *)key object:(id)object{
NSAssert([GMCache gmCache_isNonEmpty:key], @"key不能为空");
if (![GMCache gmCache_isNonEmpty:key]) {
return;
}
[[TMCache sharedCache].memoryCache setObject:object forKey:key];
}
+ (id)fetchObjectAtMemoryWithkey:(NSString *)key{
NSAssert([GMCache gmCache_isNonEmpty:key], @"key不能为空");
if (![GMCache gmCache_isNonEmpty:key]) {
return nil;
}
return [[TMCache sharedCache].memoryCache objectForKey:key];
}
+ (void)removeObjectAtMemoryWithkey:(NSString *)key{
NSAssert([GMCache gmCache_isNonEmpty:key], @"key不能为空");
if (![GMCache gmCache_isNonEmpty:key]) {
return;
}
[[TMCache sharedCache].memoryCache removeObjectForKey:key];
}
+ (void)removeAllObjectsAtMemory{
[[TMCache sharedCache].memoryCache removeAllObjects];
}
+ (void)storeObjectAtDocumentPathWithkey:(NSString *)key
object:(id <NSCoding>)object
block:(TMDiskCacheObjectBlock)block{
NSAssert([GMCache gmCache_isNonEmpty:key], @"key不能为空");
if (![GMCache gmCache_isNonEmpty:key]) {
return;
}
[[WMDocumentCache sharedCache].diskCache setObject:object forKey:key block:block];
}
+ (void)fetchObjectAtDocumentPathWithkey:(NSString *)key
block:(TMDiskCacheObjectBlock)block{
NSAssert([GMCache gmCache_isNonEmpty:key], @"key不能为空");
if (![GMCache gmCache_isNonEmpty:key]) {
return;
}
[[WMDocumentCache sharedCache].diskCache objectForKey:key block:block];
}
+ (void)removeObjectAtDocumentPathWithkey:(NSString *)key
block:(TMDiskCacheObjectBlock)block{
NSAssert([GMCache gmCache_isNonEmpty:key], @"key不能为空");
if (![GMCache gmCache_isNonEmpty:key]) {
return;
}
[[WMDocumentCache sharedCache].diskCache removeObjectForKey:key block:block];
}
+ (void)removeAllObjectsAtDocumentPathWithBlock:(TMDiskCacheBlock)block{
[[WMDocumentCache sharedCache].diskCache removeAllObjects:block];
}
+ (void)storeObjectAtDocumentPathWithkey:(NSString *)key
object:(id <NSCoding>)object{
NSAssert([GMCache gmCache_isNonEmpty:key], @"key不能为空");
if (![GMCache gmCache_isNonEmpty:key]) {
return;
}
[[WMDocumentCache sharedCache].diskCache setObject:object forKey:key];
}
+ (id)fetchObjectAtDocumentPathWithkey:(NSString *)key{
NSAssert([GMCache gmCache_isNonEmpty:key], @"key不能为空");
if (![GMCache gmCache_isNonEmpty:key]) {
return nil;
}
return [[WMDocumentCache sharedCache].diskCache objectForKey:key];
}
+ (void)removeObjectAtDocumentPathWithkey:(NSString *)key{
NSAssert([GMCache gmCache_isNonEmpty:key], @"key不能为空");
if (![GMCache gmCache_isNonEmpty:key]) {
return;
}
[[WMDocumentCache sharedCache].diskCache removeObjectForKey:key];
}
+ (void)removeAllObjectsAtDocumentPath{
[[WMDocumentCache sharedCache].diskCache removeAllObjects];
}
+ (BOOL)gmCache_isNonEmpty:(NSString *)key {
NSMutableCharacterSet *emptyStringSet = [[NSMutableCharacterSet alloc] init];
[emptyStringSet formUnionWithCharacterSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
[emptyStringSet formUnionWithCharacterSet: [NSCharacterSet characterSetWithCharactersInString: @" "]];
if ([key length] == 0) {
return NO;
}
NSString* str = [key stringByTrimmingCharactersInSet:emptyStringSet];
return [str length] > 0;
}
@end
NSString * const WMCacheSharedName = @"WMCacheShared";
@implementation WMDocumentCache
+ (instancetype)sharedCache{
static id cache;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
cache = [[self alloc] initWithName:WMCacheSharedName rootPath:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]];
});
return cache;
}
@end
Copyright (c) 2016 wangyang <wangyang@wanmeizhensuo.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# GMCache
[![CI Status](http://img.shields.io/travis/wangyang/GMCache.svg?style=flat)](https://travis-ci.org/wangyang/GMCache)
[![Version](https://img.shields.io/cocoapods/v/GMCache.svg?style=flat)](http://cocoapods.org/pods/GMCache)
[![License](https://img.shields.io/cocoapods/l/GMCache.svg?style=flat)](http://cocoapods.org/pods/GMCache)
[![Platform](https://img.shields.io/cocoapods/p/GMCache.svg?style=flat)](http://cocoapods.org/pods/GMCache)
## Usage
To run the example project, clone the repo, and run `pod install` from the Example directory first.
## Requirements
## Installation
GMCache is available through [CocoaPods](http://cocoapods.org). To install
it, simply add the following line to your Podfile:
```ruby
pod "GMCache"
```
## Author
wangyang, wangyang@wanmeizhensuo.com
## License
GMCache is available under the MIT license. See the LICENSE file for more info.
Copyright (c) 2016 北京更美互动信息科技有限公司
仅限北京更美互动信息科技有限公司内部使用
//
// CIContext+fixBug.h
// Gengmei
//
// Created by Terminator on 2017/7/31.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
#import <CoreImage/CoreImage.h>
//在swift3.0 iOS8系统下 CIContext(options: nil) 会crash 因此加了一个类别
@interface CIContext (fixBug)
+ (CIContext *)swiftContextWithOptions:(NSDictionary<NSString *, id> *)options;
@end
//
// CIContext+fixBug.m
// Gengmei
//
// Created by Terminator on 2017/7/31.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
#import "CIContext+fixBug.h"
@implementation CIContext (fixBug)
+ (CIContext *)swiftContextWithOptions:(NSDictionary<NSString *, id> *)options {
return [CIContext contextWithOptions:options];
}
@end
//
// NSString+Image.h
// Gengmei
//
// Created by Mikasa on 2019/7/4.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
NS_ASSUME_NONNULL_BEGIN
#define kGMSeparator @"-" //分隔符
#define IMAGE_URL_FORMAT_828x1792 @"828x1792_75"
#define IMAGE_URL_FORMAT_1242x2688 @"1242x2688_75"
#define IMAGE_URL_FORMAT_414x896 @"414x896_75"
#define IMAGE_URL_FORMAT_626x1344 @"626x1344_75"
#define IMAGE_URL_FORMAT_279x597 @"279x597_75"
#define IMAGE_URL_FORMAT_207x448 @"207x448_75"
#define IMAGE_URL_FORMAT_310x672 @"310x672_75"
#define IMAGE_URL_FORMAT_300x300_75 @"300x300_75"
#define IMAGE_URL_FORMAT_200x200_75 @"200x200_75"
@interface NSString (Image)
/**
* 适用于单栏展示图片
@return 适用于单栏展示图片
*/
- (NSString *)singleColumn;
/**
* 适用于双栏展示图片
@return 双栏展示图片地址
*/
- (NSString *)doubleColumn;
/**
* 适用于三栏展示图片
@return 三栏展示图片地址
*/
- (NSString *)threeColumn;
/**
* 适用于四栏展示图片
@return 四栏展示图片地址
*/
- (NSString *)fourColumn;
/**
* thumbnail
@return thumbnail图片地址
*/
- (NSString *)thumbnail;
@end
NS_ASSUME_NONNULL_END
//
// NSString+Image.m
// Gengmei
//
// Created by Mikasa on 2019/7/4.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#import "NSString+Image.h"
#import "UIScreen+GM.h"
@implementation NSString (Image)
/**
* 适用于单栏展示图片
@return 适用于单栏展示图片
*/
- (NSString *)singleColumn {
return [self stringByAppendingFormat:@"%@%@",kGMSeparator,[UIScreen isThreeScale]?IMAGE_URL_FORMAT_1242x2688:IMAGE_URL_FORMAT_828x1792];
}
/**
* 适用于双栏展示图片
@return 双栏展示图片地址
*/
- (NSString *)doubleColumn {
return [self stringByAppendingFormat:@"%@%@",kGMSeparator,[UIScreen isThreeScale]?IMAGE_URL_FORMAT_414x896:IMAGE_URL_FORMAT_279x597];
}
/**
* 适用于三栏展示图片
@return 三栏展示图片地址
*/
- (NSString *)threeColumn {
return [self stringByAppendingFormat:@"%@%@",kGMSeparator,[UIScreen isThreeScale]?IMAGE_URL_FORMAT_414x896:IMAGE_URL_FORMAT_279x597];
}
/**
* 适用于四栏展示图片
@return 四栏展示图片地址
*/
- (NSString *)fourColumn {
return [self stringByAppendingFormat:@"%@%@",kGMSeparator,[UIScreen isThreeScale]?IMAGE_URL_FORMAT_310x672:IMAGE_URL_FORMAT_207x448];
}
/**
* thumbnail
@return thumbnail图片地址
*/
- (NSString *)thumbnail {
return [self stringByAppendingFormat:@"%@%@",kGMSeparator,[UIScreen isThreeScale]?IMAGE_URL_FORMAT_300x300_75:IMAGE_URL_FORMAT_200x200_75];
}
@end
//
// UIAlertController+gm.h
// AFNetworking
//
// Created by Q14 on 2019/12/18.
//
NS_ASSUME_NONNULL_BEGIN
@interface UIAlertController (gm)
+ (void)showgm_OKAlertWithTitle:(NSString *)title message:(NSString *)message actionTitle:(NSString *)actionTitle actionHandler:(void(^)(void))actionHandler;
+ (void)gm_Alert:(NSString *)title leftTitle:(NSString *)leftTitle rightTitle:(NSString *)rightTitle leftAlterAction:(void(^)(void))leftAlterAction rightAlertAction:(void(^)(void))rightAlertAction;
@end
NS_ASSUME_NONNULL_END
//
// UIAlertController+gm.m
// AFNetworking
//
// Created by Q14 on 2019/12/18.
//
#import "UIAlertController+gm.h"
@implementation UIAlertController (gm)
//@objc static func showOKAlert(withTitle title: String?, message: String? = nil, actionTitle: String = "好", actionHandler: (() -> Void)? = nil) {
// let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
// let action = UIAlertAction(title: actionTitle, style: .default) { (_) in
// actionHandler?()
// }
// alert.addAction(action)
// UIApplication.shared.keyWindow?.rootViewController?.present(alert, animated: true, completion: nil)
// }
+ (void)showgm_OKAlertWithTitle:(NSString *)title message:(NSString *)message actionTitle:(NSString *)actionTitle actionHandler:(void(^)(void))actionHandler {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
// __weak typeof(self)weakSelf = self;
UIAlertAction *action = [UIAlertAction actionWithTitle:actionTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
if (actionHandler) {
actionHandler();
}
}];
[alert addAction:action];
[UIApplication.sharedApplication.keyWindow.rootViewController presentViewController:alert animated:YES completion:NULL];
}
+ (void)gm_Alert:(NSString *)title leftTitle:(NSString *)leftTitle rightTitle:(NSString *)rightTitle leftAlterAction:(void(^)(void))leftAlterAction rightAlertAction:(void(^)(void))rightAlertAction {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:@"" preferredStyle:UIAlertControllerStyleAlert];
// __weak typeof(self)weakSelf = self;
UIAlertAction *leftAction = [UIAlertAction actionWithTitle:leftTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
if (leftAlterAction) {
leftAlterAction();
}
}];
[alert addAction:leftAction];
UIAlertAction *rightAction = [UIAlertAction actionWithTitle:rightTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
if (rightAlertAction) {
rightAlertAction();
}
}];
[alert addAction:rightAction];
[UIApplication.sharedApplication.keyWindow.rootViewController presentViewController:alert animated:YES completion:NULL];
}
@end
//
// UIButton+ALReClicks.h
// GMAlpha
//
// Created by zhouLiang on 2019/4/4.
// Copyright © 2019 Gengmei. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIButton (ALReClicks)
/**
重复点击的间隔 大于 0 的时候才进行控制
默认值为2s
*/
@property (nonatomic, assign) NSTimeInterval multiControlTimeInterva;
/**
上次点击的时间 外界不使用
*/
@property (nonatomic, assign) NSTimeInterval cs_acceptEventTime;
@end
//
// UIButton+ALReClicks.m
// GMAlpha
//
// Created by zhouLiang on 2019/4/4.
// Copyright © 2019 Gengmei. All rights reserved.
//
#import "UIButton+ALReClicks.h"
#import <objc/runtime.h>
@implementation UIButton (ALReClicks)
static const char *UIControl_acceptEventInterval = "UIControl_acceptEventInterval";
static const char *UIControl_acceptEventTime = "UIControl_acceptEventTime";
- (NSTimeInterval)multiControlTimeInterva {
return [objc_getAssociatedObject(self, UIControl_acceptEventInterval) doubleValue];
}
- (void)setMultiControlTimeInterva:(NSTimeInterval)multiControlTimeInterva {
objc_setAssociatedObject(self, UIControl_acceptEventInterval, @(multiControlTimeInterva), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSTimeInterval)cs_acceptEventTime {
return [objc_getAssociatedObject(self, UIControl_acceptEventTime) doubleValue];
}
- (void)setCs_acceptEventTime:(NSTimeInterval)cs_acceptEventTime {
objc_setAssociatedObject(self, UIControl_acceptEventTime, @(cs_acceptEventTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
if (self.multiControlTimeInterva == 0) {
self.multiControlTimeInterva = 0;
}
if (self.multiControlTimeInterva > 0) {
if ([NSDate date].timeIntervalSince1970 - self.cs_acceptEventTime < self.multiControlTimeInterva) {
return;
}
self.cs_acceptEventTime = [NSDate date].timeIntervalSince1970;
}
[super sendAction:action to:target forEvent:event];
}
@end
//
// UIButton+GM.h
// Gengmei
//
// Created by Mikasa on 2019/8/1.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIButton (GM)
@end
NS_ASSUME_NONNULL_END
//
// UIButton+GM.m
// Gengmei
//
// Created by Mikasa on 2019/8/1.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#import "UIButton+GM.h"
@implementation UIButton (GM)
- (void)highlightedClick:(UIButton *)button {
button.highlighted = NO;
}
@end
//
// UIDevice+Reso.m
// Simple UIDevice Category for handling different iOSs hardware resolutions
//
// Created by Alejandro Luengo on 29/09/14.
// (c) 2014 Intelygenz
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSUInteger, UIDeviceResolution) {
UnknowDevice = 0, //未知设备
iPhone35Inches = 1, //3.5英寸、iphone4s
iPhone40Inches = 2, //4英寸iphone5、iphone5c、iphone5s
iPhone47Inches = 3, //4.7英寸iphone6、iphone7、iphone8
iPhone55Inches = 4, //5.5英寸iphone6 plus、iphone7 plus、iphone8 plus
iPhone58Inches = 5, //5.5英寸iphoneX
iPhoneXRInches = 6, //iphone XR
iPhoneXSMaxInches = 7 //iphone XS Max
};
typedef NS_ENUM(NSInteger, GMDeviceType) {
GMDeviceTypeUnknow = 0,
GMDeviceTypeSimulator,
GMDeviceTypeIPad,
GMDeviceTypeIPod,
GMDeviceTypeIPhone4,
GMDeviceTypeIPhone4S,
GMDeviceTypeIPhone5,
GMDeviceTypeIPhone5S,
GMDeviceTypeIPhone5C,
GMDeviceTypeIPhone6,
GMDeviceTypeIPhone6P,
GMDeviceTypeIPhone6S,
GMDeviceTypeIPhone6SP,
GMDeviceTypeIPhone7,
GMDeviceTypeIPhone7P,
GMDeviceTypeIPhone8,
GMDeviceTypeIPhone8P,
GMDeviceTypeIPhoneX,
GMDeviceTypeIPhoneXR,
GMDeviceTypeIPhoneXS,
GMDeviceTypeIPhoneXSMax,
};
typedef NS_ENUM(NSUInteger, GMDeviceAspectRatioType) {
GMDeviceAspectRatioTypeNarrow, //iPad、iphone4s、iphone5
GMDeviceAspectRatioTypeNormal, // Normal
GMDeviceAspectRatioTypeWide, // Plus、Max
};
@interface UIDevice (Resolutions)
/**
* @author licong, 16-12-29 17:12:54
*
* 判断设备的类型(eg:当前设备是5还是6s)
*
* @return 返回设备类型
*
* @since 5.8
*/
+ (UIDeviceResolution)resolutionType;
+ (GMDeviceAspectRatioType)aspectRatioType;
+ (NSString *)platform;
/**
获取设备的deviceId,如果能去到idfa,就返回idfa,否则就返回idfv
@author zhaiguojun 16-10-31 in (null)
@return deviceId
@since 6.5.0
*/
+ (NSString *)deviceId;
/**
获取设备详细类型,目前只到6s,和6s plus
@author zhaiguojun 16-09-18 in (null)
@return model
@since 6.3.0
*/
+ (NSString*)deviceVersion;
@end
//
// UIDevice+Reso.m
// Simple UIDevice Category for handling different iOSs hardware resolutions
//
// Created by Alejandro Luengo on 29/09/14.
// (c) 2014 Intelygenz
// iPhone 6 Plus 736x414 points 2208x1242 pixels 3x scale
// iPhone 6 667x375 points 1334x750 pixels 2x scale
// iPhone 5 568x320 points 1136x640 pixels 2x scale
// iPhone 4s 480x320 points 960x640 pixels 2x scale
// iPad 1024x768 points 1024x768 pixels 1x scale
// iPad Retina 1024x768 points 2048x1536 pixels 2x scale
#import "UIDevice+Resolutions.h"
#import "sys/utsname.h"
#import <AdSupport/AdSupport.h>
@implementation UIDevice (Resolutions)
+ (NSString *)deviceId {
NSString *idfa = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
NSString *idfv = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
if (![idfa isEqualToString:@"00000000-0000-0000-0000-000000000000"]) {
return idfa;
}
return idfv;
}
+ (UIDeviceResolution)resolutionType
{
UIScreenMode *mode = [UIScreen mainScreen].preferredMode;
if (mode.size.height == 960) {
return iPhone35Inches;
}
else if (mode.size.height == 1136) {
return iPhone40Inches;
}
else if (mode.size.height == 1334) {
return iPhone47Inches;
}
else if (mode.size.height == 2208) {
return iPhone55Inches;
}
else if (mode.size.height == 2436) {
return iPhone58Inches;
}
else if (mode.size.height == 1792) {
return iPhoneXRInches;
}
else if (mode.size.height == 2688) {
return iPhoneXSMaxInches;
}
else
return UnknowDevice;
}
+ (GMDeviceAspectRatioType)aspectRatioType {
UIDevice *device = [UIDevice currentDevice];
if ([device.model containsString:@"iPad"])
return GMDeviceAspectRatioTypeNarrow;
NSString *deviceVersion = [self deviceVersion];
UIScreenMode *mode = [UIScreen mainScreen].preferredMode;
if ([deviceVersion containsString:@"iPhone 4"] || [deviceVersion containsString:@"iPhone 5"] || mode.size.height == 960 || mode.size.height == 1136)
return GMDeviceAspectRatioTypeNarrow;
else if ([deviceVersion containsString:@"Plus"] || [deviceVersion containsString:@"Max"])
return GMDeviceAspectRatioTypeWide;
else
return GMDeviceAspectRatioTypeNormal;
}
+ (NSString *)platform {
struct utsname systemInfo;
uname(&systemInfo);
NSString *platform = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
return platform;
}
+ (NSString*)deviceVersion{
NSString *platform = [self platform];
//iPhone
if ([platform isEqualToString:@"iPhone3,1"]) return @"iPhone 4";
if ([platform isEqualToString:@"iPhone3,2"]) return @"iPhone 4";
if ([platform isEqualToString:@"iPhone3,3"]) return @"iPhone 4";
if ([platform isEqualToString:@"iPhone4,1"]) return @"iPhone 4S";
if ([platform isEqualToString:@"iPhone5,1"]) return @"iPhone 5";
if ([platform isEqualToString:@"iPhone5,2"]) return @"iPhone 5";
if ([platform isEqualToString:@"iPhone5,3"]) return @"iPhone 5C";
if ([platform isEqualToString:@"iPhone5,4"]) return @"iPhone 5C";
if ([platform isEqualToString:@"iPhone6,1"]) return @"iPhone 5S";
if ([platform isEqualToString:@"iPhone6,2"]) return @"iPhone 5S";
if ([platform isEqualToString:@"iPhone7,1"]) return @"iPhone 6 Plus";
if ([platform isEqualToString:@"iPhone7,2"]) return @"iPhone 6";
if ([platform isEqualToString:@"iPhone8,1"]) return @"iPhone 6s";
if ([platform isEqualToString:@"iPhone8,2"]) return @"iPhone 6s Plus";
if ([platform isEqualToString:@"iPhone8,3"]) return @"iPhoneSE";
if ([platform isEqualToString:@"iPhone8,4"]) return @"iPhoneSE";
if ([platform isEqualToString:@"iPhone9,1"]) return @"iPhone 7";
if ([platform isEqualToString:@"iPhone9,3"]) return @"iPhone 7";
if ([platform isEqualToString:@"iPhone9,2"]) return @"iPhone 7 Plus";
if ([platform isEqualToString:@"iPhone9,4"]) return @"iPhone 7 Plus";
if ([platform isEqualToString:@"iPhone10,1"]) return @"iPhone 8";
if ([platform isEqualToString:@"iPhone10,4"]) return @"iPhone 8";
if ([platform isEqualToString:@"iPhone10,2"]) return @"iPhone 8 Plus";
if ([platform isEqualToString:@"iPhone10,5"]) return @"iPhone 8 Plus";
if ([platform isEqualToString:@"iPhone10,3"]) return @"iPhone X";
if ([platform isEqualToString:@"iPhone10,6"]) return @"iPhone X";
if ([platform isEqualToString:@"iPhone11,8"]) return @"iPhone XR";
if ([platform isEqualToString:@"iPhone11,2"]) return @"iPhone XS";
if ([platform isEqualToString:@"iPhone11,4"]) return @"iPhone XS Max";
if ([platform isEqualToString:@"iPhone11,6"]) return @"iPhone XS Max";
return @"iphone X ++";
}
@end
//
// UIImage+Compress.h
// Gengmei
//
// Created by 朱璇 on 2018/11/15.
// Copyright © 2018年 更美互动信息科技有限公司. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIImage (Compress)
// 将图片按指定大小压缩
+ (NSData *)compressImage:(UIImage *)image toByte:(NSUInteger)maxLength size:(CGSize)size;
@end
//
// UIImage+Compress.m
// Gengmei
//
// Created by 朱璇 on 2018/11/15.
// Copyright © 2018年 更美互动信息科技有限公司. All rights reserved.
//
#import "UIImage+Compress.h"
@implementation UIImage (Compress)
+ (NSData *)compressImage:(UIImage *)image toByte:(NSUInteger)maxLength size:(CGSize)size {
// Compress by quality
CGFloat compression = 1;
NSData *data = UIImageJPEGRepresentation(image, compression);
if (data.length < maxLength) return data;
CGFloat max = 1;
CGFloat min = 0;
for (int i = 0; i < 6; ++i) {
compression = (max + min) / 2;
data = UIImageJPEGRepresentation(image, compression);
if (data.length < maxLength * 0.9) {
min = compression;
} else if (data.length > maxLength) {
max = compression;
} else {
break;
}
}
if (data.length < maxLength) return data;
UIImage *resultImage = [UIImage imageWithData:data];
// Compress by size
NSUInteger lastDataLength = 0;
while (data.length > maxLength && data.length != lastDataLength) {
lastDataLength = data.length;
CGFloat ratio = (CGFloat)maxLength / data.length;
CGSize size = CGSizeMake((NSUInteger)(resultImage.size.width * sqrtf(ratio)),
(NSUInteger)(resultImage.size.height * sqrtf(ratio)));
UIGraphicsBeginImageContext(size);
[resultImage drawInRect:CGRectMake(0, 0, size.width, size.height)];
resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
data = UIImageJPEGRepresentation(resultImage, compression);
}
return data;
}
@end
//
// UIImage+GM.h
// Gengmei
//
// Created by licong on 15/12/29. Rewrite by wangyang on 2016-7-4
// Copyright © 2016年 Wanmeichuangyi. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIImage (GM)
/**
* @brief 通过颜色生成图片
*
* @param color 颜色
*/
+ (UIImage *)imageWithColor:(UIColor *)color;
/**
* @author licong, 16-12-29 18:12:48
*
* 将图片调整到设定大小
*
* @param size 设定的图片大小
*
* @return 得到设定大小后的图片
*
* @since 5.8
*/
- (UIImage *)resizedImageWithSize:(CGSize)size;
/**
使用该方法的前提条件是认为这个图片为3倍图,使用该方法将返回一个适用于当前设备scale的UIImage实例。
比如一张90像素x90像素的网络下载的图片,使用该方法
- iPhone 8 Plus机型将返回一个size为(30, 30),scale=3的UIImage;
- iPhone 8 机型将返回返回一个size为(30, 30),scale=2的UIImage;
*/
- (UIImage *)resizeToDeviceScale;
/**
* @author wangyang in 2016-7-1
*
* 参考rotatedWithTransform
*/
- (UIImage *)rotatedWithAngle:(double)angle;
/**
* @author wangyang in 2016-7-1
*
* 使用这个方法旋转图片,导出的图片的imageOrientation为Up,绘制时会同时考虑待旋转图片的原 imageOrientation 与参数 transform
@note
1. 使用这个方法进行旋转,导出的图片大小可能会发生变化。比如旋转45度,那么能容下原图的bounds肯定要大一些;比如旋转90度,图片的高宽就会互换。
2. 旋转角度为0时,可以用来将图片的imageOrientation重置为Up。
* @return 新图片
*/
- (UIImage *)rotatedWithTransform:(CGAffineTransform)transform;
/**
* @author wangyang in 2016-7-4
*
* 裁剪图片
*/
- (UIImage *)imageWithCropRect:(CGRect)rect;
@end
//
// UIImage+GM.m
// Gengmei
//
// Created by licong on 15/12/29. Rewrite by wangyang on 2016-7-4
// Copyright © 2016年 Wanmeichuangyi. All rights reserved.
//
#import "UIImage+GM.h"
@implementation UIImage (GM)
#pragma mark - 从颜色生成图片
+ (UIImage *)imageWithColor:(UIColor *)color {
CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
#pragma mark - 改变大小
- (UIImage *)resizedImageWithSize:(CGSize)size {
UIGraphicsBeginImageContext(size);
CGRect rect = CGRectMake(0, 0, size.width, size.height);
// CGContextDrawImage时需要额外考虑UIImage.imageOrientation,drawInRect可以自动帮我们做好这件事
[self drawInRect:rect];
// 另外,我们不需要指定使用 CGContextSetInterpolationQuality,使用默认值Hight就可以。参考http://stackoverflow.com/questions/5685884/imagequality-with-cgcontextsetinterpolationquality
UIImage *newImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImg;
}
- (UIImage *)resizeToDeviceScale {
CGSize newSize = CGSizeMake(ceilf(self.size.width / 3), ceilf(self.size.height / 3));
UIGraphicsBeginImageContextWithOptions(newSize, NO, [UIScreen mainScreen].scale);
CGRect rect = CGRectMake(0, 0, newSize.width, newSize.height);
// CGContextDrawImage时需要额外考虑UIImage.imageOrientation,drawInRect可以自动帮我们做好这件事
[self drawInRect:rect];
// 另外,我们不需要指定使用 CGContextSetInterpolationQuality,使用默认值Hight就可以。参考http://stackoverflow.com/questions/5685884/imagequality-with-cgcontextsetinterpolationquality
UIImage *newImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImg;
}
#pragma mark - 旋转
- (UIImage *)rotatedWithAngle:(double)angle
{
CGAffineTransform transform = CGAffineTransformMakeRotation(angle * M_PI / 180);
return [self rotatedWithTransform:transform];
}
- (UIImage *)rotatedWithTransform:(CGAffineTransform)transform {
// 旋转后图片的大小
CGRect rotatedRect = CGRectApplyAffineTransform(CGRectMake(0, 0, self.size.width, self.size.height), transform);
rotatedRect.origin.x = 0;
rotatedRect.origin.y = 0;
CGSize rotatedSize = rotatedRect.size;
UIGraphicsBeginImageContextWithOptions(rotatedSize, YES, self.scale);
CGContextRef bitmap = UIGraphicsGetCurrentContext();
// 将 origin 图片的移动中间, 这样我们就可以绕着中心点旋转
CGContextTranslateCTM(bitmap, rotatedSize.width / 2, rotatedSize.height / 2);
// 旋转画布布
CGContextConcatCTM(bitmap, transform);
// 再将 origin 移回来
CGContextTranslateCTM(bitmap, rotatedSize.width / -2, rotatedSize.height / -2);
// drawInRect 会考虑图片的 orientation,也会考虑当前Context的变换
[self drawInRect:rotatedRect];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
#pragma mark - 剪切
- (UIImage *)imageWithCropRect:(CGRect)rect
{
CGImageRef croppedImage = CGImageCreateWithImageInRect(self.CGImage, rect);
UIImage *image = [UIImage imageWithCGImage:croppedImage];
CGImageRelease(croppedImage);
return image;
}
@end
//
// UILabel+CopyExtern.h
// CopyLabel
//
// Created by XingBo on 14-4-1.
// Copyright (c) 2014年 XingBo. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UILabel (CopyExtern)
- (void)attachTapHandler;
@end
//
// UILabel+CopyExtern.m
// CopyLabel
//
// Created by XingBo on 14-4-1.
// Copyright (c) 2014年 XingBo. All rights reserved.
//
#import "UILabel+CopyExtern.h"
@implementation UILabel (CopyExtern)
-(BOOL)canBecomeFirstResponder
{
return YES;
}
// 可以响应的方法
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
return (action == @selector(copyText:));
}
//针对于响应方法的实现
-(void)copyText:(id)sender
{
UIPasteboard *pboard = [UIPasteboard generalPasteboard];
/**
fix帖子详情页 楼主发帖复制崩溃bug
因为某些富文本label只设置了attributedText,导致self.text为nil崩溃
*/
if (self.text) {
pboard.string = self.text;
}else{
pboard.string = self.attributedText.string;
}
}
//UILabel默认是不接收事件的,我们需要自己添加touch事件
-(void)attachTapHandler{
self.userInteractionEnabled = YES; //用户交互的总开关
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
[self addGestureRecognizer:longPress];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIMenuControllerWillShowMenuNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIMenuControllerWillHideMenuNotification object:nil];
}
#pragma mark - notifation methods
- (void)menuShow:(NSNotification *)sender
{
if (self.isFirstResponder) {
self.backgroundColor = [UIColor grayColor];
}
}
- (void)menuHide:(NSNotification *)sender
{
self.backgroundColor = [UIColor clearColor];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
-(void)handleTap:(UIGestureRecognizer*) recognizer
{
if (recognizer.state == UIGestureRecognizerStateBegan) {
[self becomeFirstResponder];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(menuShow:) name:UIMenuControllerWillShowMenuNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(menuHide:) name:UIMenuControllerWillHideMenuNotification object:nil];
[[UIMenuController sharedMenuController] setMenuItems:nil];
UIMenuItem *copyLink = [[UIMenuItem alloc] initWithTitle:@"复制"
action:@selector(copyText:)];
[[UIMenuController sharedMenuController] setMenuItems:[NSArray arrayWithObjects:copyLink, nil]];
[[UIMenuController sharedMenuController] setTargetRect:self.frame inView:self.superview];
[[UIMenuController sharedMenuController] setMenuVisible:YES animated: YES];
// label复制选中时的背景颜色
self.backgroundColor = [UIColor clearColor];
}
}
@end
//
// UIScreen+GM.h
// Gengmei
//
// Created by Mikasa on 2019/7/4.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
NS_ASSUME_NONNULL_BEGIN
@interface UIScreen (GM)
+ (BOOL)isThreeScale;
@end
NS_ASSUME_NONNULL_END
//
// UIScreen+GM.m
// Gengmei
//
// Created by Mikasa on 2019/7/4.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#import "UIScreen+GM.h"
@implementation UIScreen (GM)
+ (BOOL)isThreeScale {
CGFloat scale = [UIScreen mainScreen].scale;
if (ABS(scale-3) <= 0.001) {
return YES;
} else {
return NO;
}
}
@end
//
// UITextView+Keyboard.h
// ZhengXing
//
// Created by Tulipa on 14-8-22.
// Copyright (c) 2014年 Wanmei Creative. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UITextView (Keyboard)
@property (nonatomic, assign) BOOL hasCloseButton;
@end
@interface UITextField (Keyboard)
@property (nonatomic, assign) BOOL hasCloseButton;
@end
//
// UITextView+Keyboard.m
// ZhengXing
//
// Created by Tulipa on 14-8-22.
// Copyright (c) 2014年 Wanmei Creative. All rights reserved.
//
#import "UITextView+Keyboard.h"
#import "UIView+Layout.h"
@implementation UITextView (Keyboard)
- (BOOL)hasCloseButton
{
return self.inputAccessoryView != nil;
}
- (void)setHasCloseButton:(BOOL)hasCloseButton
{
if (hasCloseButton)
{
UIButton *closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
[closeButton setBackgroundImage:[UIImage imageNamed:@"keyboard"] forState:UIControlStateNormal];
[closeButton sizeToFit];
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, closeButton.height)];
[view addSubview:closeButton];
[view setBackgroundColor:[UIColor clearColor]];
[closeButton setRight:view.width];
[closeButton setTop:0];
[closeButton addTarget:self action:@selector(resignFirstResponder) forControlEvents:UIControlEventTouchUpInside];
self.inputAccessoryView = view;
}
else
{
self.inputAccessoryView = nil;
}
}
@end
@implementation UITextField (Keyboard)
- (BOOL)hasCloseButton
{
return self.inputAccessoryView != nil;
}
- (void)setHasCloseButton:(BOOL)hasCloseButton
{
if (hasCloseButton)
{
UIButton *closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
[closeButton setBackgroundImage:[UIImage imageNamed:@"keyboard"] forState:UIControlStateNormal];
[closeButton sizeToFit];
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, closeButton.height)];
[view addSubview:closeButton];
[view setBackgroundColor:[UIColor clearColor]];
[closeButton setRight:view.width];
[closeButton setTop:0];
[closeButton addTarget:self action:@selector(resignFirstResponder) forControlEvents:UIControlEventTouchUpInside];
self.inputAccessoryView = view;
}
else
{
self.inputAccessoryView = nil;
}
}
@end
//
// UIView+GMShadow.h
// Gengmei
//
// Created by lizhen on 2019/3/20.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIView (GMShadow)
/**
设置四边阴影效果
@param shadowColor 阴影颜色
@param shadowOpacity 阴影透明度
@param shadowRadius 阴影半径
@param shadowOffset 阴影偏移
*/
- (void)addShadow:(UIColor *)shadowColor
shadowOpacity:(CGFloat)shadowOpacity
shadowRadius:(CGFloat)shadowRadius
shadowOffset:(CGSize)shadowOffset;
/**
设置单边阴影效果
@param shadowColor 阴影颜色
@param shadowOpacity 阴影透明度
@param shadowRadius 阴影半径
@param shadowOffset 阴影偏移
@param shdowFrame 单边阴影
*/
- (void)addShadow:(UIColor *)shadowColor
shadowOpacity:(CGFloat)shadowOpacity
shadowRadius:(CGFloat)shadowRadius
shadowOffset:(CGSize)shadowOffset
shadowFrame:(CGRect)shadowFrame;
@end
//
// UIView+GMShadow.m
// Gengmei
//
// Created by lizhen on 2019/3/20.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#import "UIView+GMShadow.h"
@implementation UIView (GMShadow)
#pragma mark - 设置四边阴影效果
- (void)addShadow:(UIColor *)shadowColor
shadowOpacity:(CGFloat)shadowOpacity
shadowRadius:(CGFloat)shadowRadius
shadowOffset:(CGSize)shadowOffset {
self.layer.shadowColor = shadowColor.CGColor;
self.layer.shadowOffset = shadowOffset;
self.layer.shadowOpacity = shadowOpacity;
self.layer.shadowRadius = shadowRadius;
}
#pragma mark - 设置单边阴影效果
- (void)addShadow:(UIColor *)shadowColor shadowOpacity:(CGFloat)shadowOpacity shadowRadius:(CGFloat)shadowRadius shadowOffset:(CGSize)shadowOffset shadowFrame:(CGRect)shadowFrame {
self.layer.shadowColor = shadowColor.CGColor;
self.layer.shadowOffset = shadowOffset;
self.layer.shadowOpacity = shadowOpacity;
self.layer.shadowRadius = shadowRadius;
self.layer.masksToBounds = NO;
UIBezierPath *path = [UIBezierPath bezierPathWithRect:shadowFrame];
self.layer.shadowPath = path.CGPath;
}
@end
//
// UIView+Layout.h
// Gengmei
//
// Created by licong on 15/12/29.
// Copyright © 2015年 Wanmeichuangyi. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIView (Layout)
/**
* Shortcut for frame.origin.x.
*
* Sets frame.origin.x = left
*/
@property (nonatomic) CGFloat left;
/**
* Shortcut for frame.origin.y
*
* Sets frame.origin.y = top
*/
@property (nonatomic) CGFloat top;
/**
* Shortcut for frame.origin.x + frame.size.width
*
* Sets frame.origin.x = right - frame.size.width
*/
@property (nonatomic) CGFloat right;
/**
* Shortcut for frame.origin.y + frame.size.height
*
* Sets frame.origin.y = bottom - frame.size.height
*/
@property (nonatomic) CGFloat bottom;
/**
* Shortcut for frame.size.width
*
* Sets frame.size.width = width
*/
@property (nonatomic) CGFloat width;
/**
* Shortcut for frame.size.height
*
* Sets frame.size.height = height
*/
@property (nonatomic) CGFloat height;
/**
* Shortcut for center.x
*
* Sets center.x = centerX
*/
@property (nonatomic) CGFloat centerX;
/**
* Shortcut for center.y
*
* Sets center.y = centerY
*/
@property (nonatomic) CGFloat centerY;
/**
* Return the x coordinate on the screen.
*/
@property (nonatomic, readonly) CGFloat screenX;
/**
* Return the y coordinate on the screen.
*/
@property (nonatomic, readonly) CGFloat screenY;
/**
* Return the x coordinate on the screen, taking into account scroll views.
*/
@property (nonatomic, readonly) CGFloat screenViewX;
/**
* Return the y coordinate on the screen, taking into account scroll views.
*/
@property (nonatomic, readonly) CGFloat screenViewY;
/**
* Return the view frame on the screen, taking into account scroll views.
*/
@property (nonatomic, readonly) CGRect screenFrame;
/**
* Shortcut for frame.origin
*/
@property (nonatomic) CGPoint origin;
/**
* Shortcut for frame.size
*/
@property (nonatomic) CGSize size;
/**
* Return the width in portrait or the height in landscape.
*/
@property (nonatomic, readonly) CGFloat orientationWidth;
/**
* Return the height in portrait or the width in landscape.
*/
@property (nonatomic, readonly) CGFloat orientationHeight;
/**
* Finds the first descendant view (including this view) that is a member of a particular class.
*/
- (UIView*)descendantOrSelfWithClass:(Class)cls;
/**
* Finds the first ancestor view (including this view) that is a member of a particular class.
*/
- (UIView*)ancestorOrSelfWithClass:(Class)cls;
/**
* Removes all subviews.
*/
- (void)removeAllSubviews;
@end
@interface UIView (GestureAction)
/**
Attaches the given block for a single tap action to the receiver.
@param block The block to execute.
*/
- (void)setTapActionWithBlock:(void (^)(void))block;
//- (void)removeTapAction;
/**
Attaches the given block for a long press action to the receiver.
@param block The block to execute.
*/
- (void)setLongPressActionWithBlock:(void (^)(void))block;
@end
//
// UIView+Layout.m
// Gengmei
//
// Created by licong on 15/12/29.
// Copyright © 2015年 Wanmeichuangyi. All rights reserved.
//
#import "UIView+Layout.h"
#import <objc/runtime.h>
static char kDTActionHandlerTapBlockKey;
static char kDTActionHandlerTapGestureKey;
static char kDTActionHandlerLongPressBlockKey;
static char kDTActionHandlerLongPressGestureKey;
@implementation UIView (Layout)
- (CGFloat)left {
return self.frame.origin.x;
}
- (void)setLeft:(CGFloat)x {
CGRect frame = self.frame;
frame.origin.x = x;
self.frame = frame;
}
- (CGFloat)top {
return self.frame.origin.y;
}
- (void)setTop:(CGFloat)y {
CGRect frame = self.frame;
frame.origin.y = y;
self.frame = frame;
}
- (CGFloat)right {
return self.frame.origin.x + self.frame.size.width;
}
- (void)setRight:(CGFloat)right {
CGRect frame = self.frame;
frame.origin.x = right - frame.size.width;
self.frame = frame;
}
- (CGFloat)bottom {
return self.frame.origin.y + self.frame.size.height;
}
- (void)setBottom:(CGFloat)bottom {
CGRect frame = self.frame;
frame.origin.y = bottom - frame.size.height;
self.frame = frame;
}
- (CGFloat)centerX {
return self.center.x;
}
- (void)setCenterX:(CGFloat)centerX {
self.center = CGPointMake(centerX, self.center.y);
}
- (CGFloat)centerY {
return self.center.y;
}
- (void)setCenterY:(CGFloat)centerY {
self.center = CGPointMake(self.center.x, centerY);
}
- (CGFloat)width {
return self.frame.size.width;
}
- (void)setWidth:(CGFloat)width {
CGRect frame = self.frame;
frame.size.width = width;
self.frame = frame;
}
- (CGFloat)height {
return self.frame.size.height;
}
- (void)setHeight:(CGFloat)height {
CGRect frame = self.frame;
frame.size.height = height;
self.frame = frame;
}
- (CGFloat)screenX {
CGFloat x = 0.0f;
for (UIView* view = self; view; view = view.superview) {
x += view.left;
}
return x;
}
- (CGFloat)screenY {
CGFloat y = 0.0f;
for (UIView* view = self; view; view = view.superview) {
y += view.top;
}
return y;
}
- (CGFloat)screenViewX {
CGFloat x = 0.0f;
for (UIView* view = self; view; view = view.superview) {
x += view.left;
if ([view isKindOfClass:[UIScrollView class]]) {
UIScrollView* scrollView = (UIScrollView*)view;
x -= scrollView.contentOffset.x;
}
}
return x;
}
- (CGFloat)screenViewY {
CGFloat y = 0;
for (UIView* view = self; view; view = view.superview) {
y += view.top;
if ([view isKindOfClass:[UIScrollView class]]) {
UIScrollView* scrollView = (UIScrollView*)view;
y -= scrollView.contentOffset.y;
}
}
return y;
}
- (CGRect)screenFrame {
return CGRectMake(self.screenViewX, self.screenViewY, self.width, self.height);
}
- (CGPoint)origin {
return self.frame.origin;
}
- (void)setOrigin:(CGPoint)origin {
CGRect frame = self.frame;
frame.origin = origin;
self.frame = frame;
}
- (CGSize)size {
return self.frame.size;
}
- (void)setSize:(CGSize)size {
CGRect frame = self.frame;
frame.size = size;
self.frame = frame;
}
- (CGFloat)orientationWidth {
return UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)
? self.height : self.width;
}
- (CGFloat)orientationHeight {
return UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)
? self.width : self.height;
}
- (UIView*)descendantOrSelfWithClass:(Class)cls {
if ([self isKindOfClass:cls])
return self;
for (UIView* child in self.subviews) {
UIView* it = [child descendantOrSelfWithClass:cls];
if (it)
return it;
}
return nil;
}
- (UIView*)ancestorOrSelfWithClass:(Class)cls {
if ([self isKindOfClass:cls]) {
return self;
} else if (self.superview) {
return [self.superview ancestorOrSelfWithClass:cls];
} else {
return nil;
}
}
- (void)removeAllSubviews {
while (self.subviews.count) {
UIView* child = self.subviews.lastObject;
[child removeFromSuperview];
}
}
- (CGPoint)offsetFromView:(UIView*)otherView {
CGFloat x = 0.0f, y = 0.0f;
for (UIView* view = self; view && view != otherView; view = view.superview) {
x += view.left;
y += view.top;
}
return CGPointMake(x, y);
}
@end
@implementation UIView (GestureAction)
- (void)setTapActionWithBlock:(void (^)(void))block
{
UITapGestureRecognizer *gesture = objc_getAssociatedObject(self, &kDTActionHandlerTapGestureKey);
if (!gesture)
{
gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(__handleActionForTapGesture:)];
[self addGestureRecognizer:gesture];
objc_setAssociatedObject(self, &kDTActionHandlerTapGestureKey, gesture, OBJC_ASSOCIATION_RETAIN);
}
objc_setAssociatedObject(self, &kDTActionHandlerTapBlockKey, block, OBJC_ASSOCIATION_COPY);
}
- (void)__handleActionForTapGesture:(UITapGestureRecognizer *)gesture
{
if (gesture.state == UIGestureRecognizerStateRecognized)
{
void(^action)(void) = objc_getAssociatedObject(self, &kDTActionHandlerTapBlockKey);
if (action)
{
action();
}
}
}
- (void)setLongPressActionWithBlock:(void (^)(void))block
{
UILongPressGestureRecognizer *gesture = objc_getAssociatedObject(self, &kDTActionHandlerLongPressGestureKey);
if (!gesture)
{
gesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(__handleActionForLongPressGesture:)];
[self addGestureRecognizer:gesture];
objc_setAssociatedObject(self, &kDTActionHandlerLongPressGestureKey, gesture, OBJC_ASSOCIATION_RETAIN);
}
objc_setAssociatedObject(self, &kDTActionHandlerLongPressBlockKey, block, OBJC_ASSOCIATION_COPY);
}
- (void)__handleActionForLongPressGesture:(UITapGestureRecognizer *)gesture
{
if (gesture.state == UIGestureRecognizerStateBegan)
{
void(^action)(void) = objc_getAssociatedObject(self, &kDTActionHandlerLongPressBlockKey);
if (action)
{
action();
}
}
}
@end
//
// UIView+LineWithAutolayout.h
// ZhengXing
//
// Created by wangyang on 11/6/14.
// Copyright (c) 2014 Wanmei Creative. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIView (LineWithAutolayout)
/**
* @author licong, 16-12-28 19:12:48
*
* alloc一个无固定大小的view,用作分割线
*
* @return 返回一个view
*
* @since 5.8
*/
- (UIView *)addLineWithoutFrame;
/**
* @author licong, 16-12-28 19:12:16
*
* 在指定view(就是self)的最上边缘,加一根与指定view宽度相等的头部边缘线
*
* @return 返回alloc的分割线
*
* @since 5.8
*/
- (UIView *)addTopLine;
/**
* @author licong, 16-12-28 19:12:16
*
* 在view(就是self)的最下边缘,加一根与指定view宽度相等的底部边缘线
*
* @return 返回alloc的分割线
*
* @since 5.8
*/
- (UIView *)addBottomLine;
/**
* @author licong, 16-12-28 19:13:30
*
* 给指定的view(就是self),加一跟中心水平线
*
* @param left 竖直线距离设定的view左边的距离
* @param right 竖直线距离设定的view右边的距离
*
* @return 返回alloc的中心竖直线
*
* @since 5.8
*/
- (UIView *)addCenterHorizontalLineWithLeft:(CGFloat)left right:(CGFloat)right;
/**
* @author licong, 16-12-28 19:12:40
*
* 给指定的view(就是self),加一跟中心竖直线
*
* @param top 竖直线距离设定的view上边的距离
* @param bottom 竖直线距离设定的view下边的距离
*
* @return 返回alloc的中心竖直线
*
* @since 5.8
*/
- (UIView *)addCenterVerticalLineWithTop:(CGFloat)top bottom:(CGFloat)bottom;
/**
* @author licong, 16-12-28 19:12:19
*
* 给指定的view(就是self)的最下边缘,加一根长度可设置的头部边缘线(最长不超过该view的宽度)
*
* @param left 头部边缘线距离设定view左边的距离
* @param right 头部边缘线距离设定view左边的距离
*
* @return 返回长度可设置的头部边缘线
*
* @since 5.8
*/
- (UIView *)addTopLineWithLeft:(CGFloat)left right:(CGFloat)right;
/**
* @author licong, 16-12-28 19:12:16
*
* 给指定的view(就是self)的最下边缘,加一根长度可设置的底部边缘线(最长不超过该view的宽度)
*
* @param left 底部边缘线距离设定view左边缘的距离
* @param right 底部边缘线距离设定view右边缘的距离
*
* @return 返回长度可设置的底部边缘线
*
* @since 5.8
*/
- (UIView *)addBottomLineWithLeft:(CGFloat)left right:(CGFloat)right;
/**
* @author licong, 16-12-29 11:12:02
*
* 给指定的view(就是self),加一根长度可设置的水平线,以Top为Y方向的基准点
*
* @param top 水平线距离设定view上边缘的距离
* @param left 水平线距离设定view左边缘的距离
* @param right 水平线距离设定view右边缘的距离
*
* @return 返回水平线
*
* @since 5.8
*/
- (UIView *)addHorizontalLineWithTop:(CGFloat)top left:(CGFloat)left right:(CGFloat)right;
/**
* @author licong, 16-12-29 11:12:48
*
* 给指定的view(就是self),加一根长度可设置的水平线,以Bottom为Y方向的基准点
*
* @param bottom 水平线距离设定view下边缘的距离
* @param left 水平线距离设定view左边缘的距离
* @param right 水平线距离设定view右边缘的距离
*
* @return 返回水平线
*
* @since 5.8
*/
- (UIView *)addHorizontalLineWithBottom:(CGFloat)bottom left:(CGFloat)left right:(CGFloat)right;
/**
* @author licong, 16-12-29 11:12:48
*
* 给指定的view(就是self),加一根长度可设置的竖直线,以Left为X方向的基准点
*
* @param left 竖直线距离设定view左边缘的距离
* @param top 竖直线距离设定view上边缘的距离
* @param bottom 竖直线距离设定view下边缘的距离
*
* @return 返回竖直线
*
* @since 5.8
*/
- (UIView *)addVerticalLineWithLeft:(CGFloat)left top:(CGFloat)top bottom:(CGFloat)bottom;
/**
* @author licong, 16-12-29 11:12:54
*
* 给指定的view(就是self),加一根长度可设置的竖直线,以Right为X方向的基准点
*
* @param right 竖直线距离设定view右边缘的距离
* @param top 竖直线距离设定view上边缘的距离
* @param bottom 竖直线距离设定view下边缘的距离
*
* @return 返回竖直线
*
* @since 58
*/
- (UIView *)addVerticalLineWithRight:(CGFloat)right top:(CGFloat)top bottom:(CGFloat)bottom;
@end
//
// UIView+LineWithAutolayout.m
// ZhengXing
//
// Created by wangyang on 11/6/14.
// Copyright (c) 2014 Wanmei Creative. All rights reserved.
//
#import "UIView+LineWithAutolayout.h"
#import <Masonry/Masonry.h>
#import <UIColor+GMTheme.h>
@interface OnePixelLine : UIView
@end
@implementation OnePixelLine
@end
@implementation UIView (LineWithAutolayout)
- (UIView *)addLineWithoutFrame{
UIView *line = [OnePixelLine new];
line.backgroundColor = UIColor.separatorLine;
[self addSubview:line];
return line;
}
- (UIView *)addTopLine
{
UIView *line = [self addLineWithoutFrame];
[line mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(0);
make.left.mas_equalTo(0);
make.right.mas_equalTo(0);
make.height.offset(1/[UIScreen mainScreen].scale);
}];
return line;
}
- (UIView *)addBottomLine
{
UIView *line = [self addLineWithoutFrame];
[line mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.mas_equalTo(0);
make.left.mas_equalTo(0);
make.right.mas_equalTo(0);
make.height.offset(1/[UIScreen mainScreen].scale);
}];
return line;
}
- (UIView *)addCenterHorizontalLineWithLeft:(CGFloat)left right:(CGFloat)right{
UIView *line = [self addLineWithoutFrame];
[line mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(0);
make.left.mas_equalTo(left);
make.right.mas_equalTo(right);
make.height.offset(1/[UIScreen mainScreen].scale);
}];
return line;
}
- (UIView *)addCenterVerticalLineWithTop:(CGFloat)top bottom:(CGFloat)bottom{
UIView *line = [self addLineWithoutFrame];
[line mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(top);
make.centerX.mas_equalTo(0);
make.bottom.mas_equalTo(bottom);
make.width.offset(1/[UIScreen mainScreen].scale);
}];
return line;
}
- (UIView *)addTopLineWithLeft:(CGFloat)left right:(CGFloat)right{
UIView *line = [self addLineWithoutFrame];
[line mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(0);
make.left.mas_equalTo(left);
make.right.mas_equalTo(right);
make.height.offset(1/[UIScreen mainScreen].scale);
}];
return line;
}
- (UIView *)addBottomLineWithLeft:(CGFloat)left right:(CGFloat)right{
UIView *line = [self addLineWithoutFrame];
[line mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.mas_equalTo(0);
make.left.mas_equalTo(left);
make.right.mas_equalTo(right);
make.height.offset(1/[UIScreen mainScreen].scale);
}];
return line;
}
- (UIView *)addHorizontalLineWithTop:(CGFloat)top left:(CGFloat)left right:(CGFloat)right{
UIView *line = [self addLineWithoutFrame];
[line mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(top);
make.left.mas_equalTo(left);
make.right.mas_equalTo(right);
make.height.offset(1/[UIScreen mainScreen].scale);
}];
return line;
}
- (UIView *)addHorizontalLineWithBottom:(CGFloat)bottom left:(CGFloat)left right:(CGFloat)right{
UIView *line = [self addLineWithoutFrame];
[line mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.mas_equalTo(bottom);
make.left.mas_equalTo(left);
make.right.mas_equalTo(right);
make.height.offset(1/[UIScreen mainScreen].scale);
}];
return line;
}
- (UIView *)addVerticalLineWithLeft:(CGFloat)left top:(CGFloat)top bottom:(CGFloat)bottom{
UIView *line = [self addLineWithoutFrame];
[line mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(top);
make.left.mas_equalTo(left);
make.bottom.mas_equalTo(bottom);
make.width.offset(1/[UIScreen mainScreen].scale);
}];
return line;
}
- (UIView *)addVerticalLineWithRight:(CGFloat)right top:(CGFloat)top bottom:(CGFloat)bottom{
UIView *line = [self addLineWithoutFrame];
[line mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(top);
make.right.mas_equalTo(right);
make.bottom.mas_equalTo(bottom);
make.width.offset(1/[UIScreen mainScreen].scale);
}];
return line;
}
@end
//
// UIView+SafeArea.h
// Gengmei
//
// Created by wangyang on 2018/6/19.
// Copyright © 2018年 更美互动信息科技有限公司. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIView (SafeArea)
@property (nonatomic, readonly, class) CGFloat safeAreaInsetsBottom;
@end
//
// UIView+SafeArea.m
// Gengmei
//
// Created by wangyang on 2018/6/19.
// Copyright © 2018年 更美互动信息科技有限公司. All rights reserved.
//
#import "UIView+SafeArea.h"
@implementation UIView (SafeArea)
+ (CGFloat)safeAreaInsetsBottom {
if (@available(iOS 11.0, *)) {
return [UIApplication sharedApplication].keyWindow.safeAreaInsets.bottom;
} else {
return 0;
}
}
@end
//
// UIViewController+ChildSwitch.h
// segmentSwitch
//
// Created by wangyang on 5/13/15.
// Copyright (c) 2015 IGIU. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIViewController (ChildControllerSwitch)
#pragma mark - 只读属性
/**
当前显示的controller
*/
@property (nonatomic, strong) UIViewController *currentController;
/**
将childContainer添加到视图中用来显示所有的child
注意:childContainer只有一个子视图:childScrollView,childScrollView装载了所有的child。
*/
@property (nonatomic, strong) IBOutlet UIView *childContainer;
/**
用来横滑切换chile controller。可以使用childScrollView.scrollEnable来禁止。
其contentSize的高为childContainer.height
*/
@property (nonatomic, strong) UIScrollView *childScrollView;
/**
返回该类别所管理的chile view controllers
*/
@property (nonatomic, copy) NSArray *childs;
#pragma mark - 需要配置的属性
/**
childContainer的size,需要手动计算出来
*/
@property (nonatomic, assign) CGSize childContainerSize;
/**
滑动childScrollView,滑动停止,调用该block。典型使用就是通知segment切换到指定位置
*/
@property (nonatomic, copy) void (^childScrollViewDidEndScroll) (NSInteger index);
#pragma mark - 可选属性
/**
switchToChildControllerAtIndex后会调用
*/
@property (nonatomic, copy) void (^didFinishSwitchChild) (void);
#pragma mark - 方法
/**
* @brief 设置第一个要显示的controller
*
*/
- (void)setFirstController:(UIViewController *)controller;
/**
* @brief 添加待显示的controllers
*
*/
- (void)addOtherController:(NSArray *)otherControllers;
/**
设置第一个需要显示的controller及其它待显示的controllers
*/
- (void)setFirstController:(UIViewController *)controller otherController:(NSArray *)otherControllers;
/**
切换到指定位置的controller
*/
- (void)switchToChildControllerAtIndex:(NSUInteger)index;
@end
//
// UIViewController+ChildSwitch.m
// segmentSwitch
//
// Created by wangyang on 5/13/15.
// Copyright (c) 2015 IGIU. All rights reserved.
//
#import "UIViewController+ChildControllerSwitch.h"
#import <objc/runtime.h>
#import <Masonry/Masonry.h>
#import "UIView+Layout.h"
#import "Constant.h"
@interface NSObject (CustomClass)
@end
@implementation NSObject (CustomClass)
@end
@interface ScrollViewDelegate: NSObject <UIScrollViewDelegate>
@property (nonatomic, copy) void (^scrollViewEndScroll) (void);
@end
@implementation ScrollViewDelegate
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
if (self.scrollViewEndScroll) {
self.scrollViewEndScroll();
}
}
@end
@interface UIViewController ()
@property (nonatomic, strong) ScrollViewDelegate *scrollDelegate;
@end
@implementation UIViewController (ChildControllerSwitch)
/**
* set方法是为了适应IB,如果纯代码可以不用set方法
*/
- (void)setChildContainer:(UIView *)childContainer{
objc_setAssociatedObject(self, @selector(childContainer), childContainer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIView *)childContainer{
UIView *childContainer = objc_getAssociatedObject(self, _cmd);
if (!childContainer) {
childContainer = [[UIView alloc] init];
childContainer.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
objc_setAssociatedObject(self, _cmd, childContainer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return childContainer;
}
- (void)setCurrentController:(UIViewController *)currentController{
objc_setAssociatedObject(self, NSSelectorFromString(@"currentController"), currentController, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIViewController *)currentController{
return objc_getAssociatedObject(self, NSSelectorFromString(@"currentController"));
}
- (void)setChildScrollView:(UIScrollView *)childScrollView {
objc_setAssociatedObject(self, @selector(childScrollView), childScrollView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIScrollView *)childScrollView {
UIScrollView *_childScrollView = objc_getAssociatedObject(self, @selector(childScrollView));
if (_childScrollView == nil) {
_childScrollView = [UIScrollView new];
_childScrollView.delegate = self.scrollDelegate;
_childScrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.childContainer addSubview:_childScrollView];
_childScrollView.pagingEnabled = YES;
_childScrollView.scrollsToTop = NO;
_childScrollView.showsHorizontalScrollIndicator = NO;
[_childScrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(UIEdgeInsetsZero);
}];
objc_setAssociatedObject(self, _cmd, _childScrollView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return _childScrollView;
}
- (void)setScrollDelegate:(ScrollViewDelegate *)scrollDelegate {
objc_setAssociatedObject(self, @selector(scrollDelegate), scrollDelegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (ScrollViewDelegate *)scrollDelegate {
ScrollViewDelegate *_scrollDelegate = objc_getAssociatedObject(self, @selector(scrollDelegate));
if (_scrollDelegate == nil) {
_scrollDelegate = [ScrollViewDelegate new];
__weak __typeof(self) weakSelf = self;
_scrollDelegate.scrollViewEndScroll = ^{
[weakSelf prepareChangeController];
};
objc_setAssociatedObject(self, _cmd, _scrollDelegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return _scrollDelegate;
}
- (void)setChildContainerSize:(CGSize)childContainerSize {
NSValue *size = [NSValue valueWithCGSize:childContainerSize];
objc_setAssociatedObject(self, @selector(childContainerSize), size, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
if (self.childs.count != 0) {
#warning 这个高度是否可以直接使用self.height
self.childScrollView.contentSize = CGSizeMake(childContainerSize.width * self.childs.count , childContainerSize.height);
}
}
- (CGSize)childContainerSize {
NSValue *size = objc_getAssociatedObject(self, @selector(childContainerSize));
if (size == nil) {
return CGSizeZero;
} else {
return [size CGSizeValue];
}
}
- (void)setChildScrollViewDidEndScroll:(void (^) (NSInteger))block {
objc_setAssociatedObject(self, @selector(childScrollViewDidEndScroll), block, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (void (^) (NSInteger))childScrollViewDidEndScroll {
id block = objc_getAssociatedObject(self, @selector(childScrollViewDidEndScroll));
return block;
}
- (void)setChilds:(NSArray *)childs {
objc_setAssociatedObject(self, @selector(childs), childs, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSArray *)childs {
NSArray *_childs = objc_getAssociatedObject(self, @selector(childs));
return _childs;
}
- (void)setDidFinishSwitchChild:(void (^) (void))block {
objc_setAssociatedObject(self, @selector(didFinishSwitchChild), block, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (void (^) (void))didFinishSwitchChild {
id block = objc_getAssociatedObject(self, @selector(didFinishSwitchChild));
return block;
}
#pragma mark - 方法
- (void)setFirstController:(UIViewController *)controller {
[self addForwardAppearanceMethods:controller];
self.childContainer.size = self.childContainerSize;
self.childScrollView.size = self.childContainerSize;
controller.view.frame = self.childContainer.bounds;
controller.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self.childScrollView addSubview:controller.view];
self.currentController = controller;
[self addChildViewController:controller];
[self.currentController didMoveToParentViewController:self];
}
- (void)setFirstController:(UIViewController *)controller otherController:(NSArray *)otherControllers {
NSAssert(controller, @"不能设置nil为第一个controller");
NSAssert(self.childContainer.superview, @"self.childContainer must have a superview");
[self setFirstController:controller];
[self addOtherController:otherControllers];
}
- (void)addOtherController:(NSArray *)otherControllers {
NSAssert(self.currentController, @"不能设置nil为第一个controller");
for (UIViewController *other in otherControllers) {
[self addForwardAppearanceMethods:other];
[self addChildViewController:other];
}
self.childs = [[NSArray arrayWithObject:self.currentController] arrayByAddingObjectsFromArray:otherControllers];
CGSize size = CGSizeMake(self.childContainerSize.width * self.childs.count , self.childContainerSize.height);
self.childScrollView.contentSize = size;
}
- (void)addForwardAppearanceMethods:(UIViewController *)controller {
SEL sel = @selector(shouldAutomaticallyForwardAppearanceMethods);
IMP imp = imp_implementationWithBlock(^(){
return NO;
});
class_addMethod([controller class], sel, imp, "B@:");
}
- (void)switchToChildControllerAtIndex:(NSUInteger)index {
self.childScrollView.contentOffset = CGPointMake(index * self.childContainer.bounds.size.width, 0);
/*
比如A -> B -> A,因为A.view被添加到scrollView中就不会被移除,所以当再次回到A->B,或者B->A时,viewWillAppear等4个方法都不会调用
使用 beginAppearanceTransition:animated:、endAppearanceTransition 可以解决这个问题。
另外需要配合 shouldAutomaticallyForwardAppearanceMethods 使用。
beginAppearanceTransition:animated: 设置为YES触发Child View Controller的viewWillAppear;
beginAppearanceTransition:animated: 设置为NO触发Child View Controller的viewWillDisappear;
endAppearanceTransition 触发Child View Controller的viewDidAppear 和viewDidDisappear
*/
UIViewController *to = self.childViewControllers[index];
UIViewController *from = self.currentController;
if (to == from) {
if (self.didFinishSwitchChild) {
self.didFinishSwitchChild();
}
} else {
if (to.view.superview == nil) {
CGRect frame = self.childContainer.bounds;
frame.origin.x = frame.size.width * index;
frame.size = self.childContainer.size;
to.view.frame = frame;
to.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self.childScrollView addSubview:to.view];
[from beginAppearanceTransition:NO animated:NO];
[to didMoveToParentViewController:self];
[from endAppearanceTransition];
} else {
[to beginAppearanceTransition:YES animated:NO];
[from beginAppearanceTransition:NO animated:NO];
[to endAppearanceTransition];
[from endAppearanceTransition];
}
self.currentController = to;
if (self.didFinishSwitchChild) {
self.didFinishSwitchChild();
}
}
}
- (void)prepareChangeController {
int index = self.childScrollView.contentOffset.x / self.childContainer.bounds.size.width;
[self switchToChildControllerAtIndex:index];
if (self.childScrollViewDidEndScroll) {
self.childScrollViewDidEndScroll(index);
}
}
@end
//
// UIColor+GMTheme.h
// Gengmei
// 主题
// Created by Thierry on 1/7/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#define RGBCOLOR_HEX(hexColor) [UIColor colorWithRed: (((hexColor >> 16) & 0xFF))/255.0f \
green: (((hexColor >> 8) & 0xFF))/255.0f \
blue: ((hexColor & 0xFF))/255.0f \
alpha: 1]
NS_ASSUME_NONNULL_BEGIN
@interface UIColor (GMTheme)
/** 医生版主视觉颜色,暂时改为红色,用来区分, (0x3ADBD2) */
@property (nonatomic, class, readonly) UIColor *mainVisual;
/** 医生版辅助颜色, (0xFF7690) */
@property (nonatomic, class, readonly) UIColor *secondaryVisual;
/** 医生版失效颜色, (0xD5D5D5) */
@property (nonatomic, class, readonly) UIColor *disable;
/** 医生版分割线颜色、边框颜色, (0xE5E5E5) */
@property (nonatomic, class, readonly) UIColor *separatorLine;
/** 医生版背景颜色, (0xF5F5F5) */
@property (nonatomic, class, readonly) UIColor *background;
/** 医生版提示背景颜色(黄), (0xF8F4DD) */
@property (nonatomic, class, readonly) UIColor *backgroundTip;
/** 医生版tag背景颜色, (0xF0F0F0) */
@property (nonatomic, class, readonly) UIColor *tagBackground;
/** 一级标题字、主要内容, (0x282828) */
@property (nonatomic, class, readonly) UIColor *headlineText;
/** 正文、普通文字内容, (0x464646) */
@property (nonatomic, class, readonly) UIColor *bodyText;
/** 可点击状态的文字更美绿, (0x4ABAB4) */
@property (nonatomic, class, readonly) UIColor *auxiliaryTextGreen;
/** 文字的更美红, (0xFF7690) */
@property (nonatomic, class, readonly) UIColor *auxiliaryTextRed;
/** 文字的更美黄提示色, (0x9D704F) */
@property (nonatomic, class, readonly) UIColor *auxiliaryTextYellow;
/** 辅助文字色, (0x666666) */
@property (nonatomic, class, readonly) UIColor *auxiliaryTextDark;
/** 辅助文字色, (0x999999) */
@property (nonatomic, class, readonly) UIColor *auxiliaryTextLight;
/** 辅助文字色, (0xcccccc) */
@property (nonatomic, class, readonly) UIColor *auxiliaryTextExtraLight;
/** 目前和MAIN_VISUAL_COLOR一样, (0x3ADBD2) */
@property (nonatomic, class, readonly) UIColor *buttonNormalGreen;
/** (0x1FB2A7) */
@property (nonatomic, class, readonly) UIColor *buttonHighlightGreen;
/** 目前和SECONDARY_VISUAL_COLOR一样, (0xFF7690) */
@property (nonatomic, class, readonly) UIColor *buttonNormalRed;
/** (0xE75873) */
@property (nonatomic, class, readonly) UIColor *buttonHighlightRed;
/** 目前和DISABLE_COLOR一样, (0xD5D5D5) */
@property (nonatomic, class, readonly) UIColor *buttonDisable;
/** 标签选中绿色, (0x24DAE0) */
@property (nonatomic, class, readonly) UIColor *tagSelectedGreen;
/**
用于色值是数字
*/
+ (UIColor *)colorWithHex:(NSInteger)hex;
+ (UIColor *)colorWithHex:(NSInteger)hex alpha:(CGFloat)alpha;
/**
用于色值字符串
*/
+ (UIColor *)colorWithHexString:(NSString *)hexString;
+ (UIColor *)colorWithHexString:(NSString *)hexString alpha:(CGFloat)alpha;
@end
NS_ASSUME_NONNULL_END
//
// UIColor+GMTheme.m
// GMKit
//
// Created by wangyang on 2017/11/8.
//
#import <UIColor+GMTheme.h>
//用户版色值
#ifdef IS_USER
//颜色规范
#define MAIN_VISUAL_COLOR RGBCOLOR_HEX(0x3ADBD2) //主视觉颜色
#define SECONDARY_VISUAL_COLOR RGBCOLOR_HEX(0xFF7690) //辅助颜色
#define SEPARATOR_LINE_COLOR RGBCOLOR_HEX(0xE5E5E5) //分割线颜色、边框颜色
#define BACKGROUND_COLOR RGBCOLOR_HEX(0xF4F3F8) //背景颜色
#define DISABLE_COLOR RGBCOLOR_HEX(0xD5D5D5) //失效颜色
#define BACKGROUND_TIP_COLOR RGBCOLOR_HEX(0xFFFBE4) //提示背景颜色(黄)
#define TAG_BACKGROUND_COLOR RGBCOLOR_HEX(0xF0F0F0) //tag背景颜色
#define TAG_SELECTED_COLOR RGBCOLOR_HEX(0x24DAE0)
//文字颜色
#define HEADLINE_TEXT_COLOR RGBCOLOR_HEX(0x282828) //一级标题字、主要内容
#define BODY_TEXT_COLOR RGBCOLOR_HEX(0x464646) //正文、普通文字内容
#define AUXILIARY_TEXT_GREEN RGBCOLOR_HEX(0x4ABAB4) //可点击状态的文字更美绿
#define AUXILIARY_TEXT_RED RGBCOLOR_HEX(0xFF7690) //文字的更美红
#define AUXILIARY_TEXT_YELLOW RGBCOLOR_HEX(0x9D704F) //文字的更美黄提示色
#define AUXILIARY_TEXT_COLOR_DARK RGBCOLOR_HEX(0x666666) //辅助文字色
#define AUXILIARY_TEXT_COLOR_LIGHT RGBCOLOR_HEX(0x999999) //辅助文字色
#define AUXILIARY_TEXT_COLOR_EXTRA_LIGHT RGBCOLOR_HEX(0xcccccc) //辅助文字色
//按钮颜色
#define BUTTON_NORMAL_GREEN_COLOR RGBCOLOR_HEX(0x3ADBD2) //目前和MAIN_VISUAL_COLOR一样
#define BUTTON_HIGHLIGHT_GREEN_COLOR RGBCOLOR_HEX(0x1FB2A7)
#define BUTTON_NORMAL_RED_COLOR RGBCOLOR_HEX(0xFF7690) //目前和SECONDARY_VISUAL_COLOR一样
#define BUTTON_HIGHLIGHT_RED_COLOR RGBCOLOR_HEX(0xE75873)
#define BUTTON_DISABLE_COLOR RGBCOLOR_HEX(0xD5D5D5) //目前和DISABLE_COLOR一样
//医生版色值,目前未支持
#elif IS_DOCTOR
//颜色规范
#define MAIN_VISUAL_COLOR RGBCOLOR_HEX(0x3ADBD2) //医生版主视觉颜色,暂时改为红色,用来区分
#define SECONDARY_VISUAL_COLOR RGBCOLOR_HEX(0xFF7690) //医生版辅助颜色
#define SEPARATOR_LINE_COLOR RGBCOLOR_HEX(0xE5E5E5) //医生版分割线颜色、边框颜色
#define DISABLE_COLOR RGBCOLOR_HEX(0xD5D5D5) //医生版失效颜色
#define BACKGROUND_COLOR RGBCOLOR_HEX(0xF5F5F5) //医生版背景颜色
#define BACKGROUND_TIP_COLOR RGBCOLOR_HEX(0xF8F4DD) //医生版提示背景颜色(黄)
#define TAG_BACKGROUND_COLOR RGBCOLOR_HEX(0xF0F0F0) //医生版tag背景颜色
#define TAG_SELECTED_COLOR RGBCOLOR_HEX(0x24DAE0) //tag标签选中颜色
//文字颜色
#define HEADLINE_TEXT_COLOR RGBCOLOR_HEX(0x282828) //一级标题字、主要内容
#define BODY_TEXT_COLOR RGBCOLOR_HEX(0x464646) //正文、普通文字内容
#define AUXILIARY_TEXT_GREEN RGBCOLOR_HEX(0x4ABAB4) //可点击状态的文字更美绿
#define AUXILIARY_TEXT_RED RGBCOLOR_HEX(0xFF7690) //文字的更美红
#define AUXILIARY_TEXT_YELLOW RGBCOLOR_HEX(0x9D704F) //文字的更美黄提示色
#define AUXILIARY_TEXT_COLOR_DARK RGBCOLOR_HEX(0x666666) //辅助文字色
#define AUXILIARY_TEXT_COLOR_LIGHT RGBCOLOR_HEX(0x999999) //辅助文字色
#define AUXILIARY_TEXT_COLOR_EXTRA_LIGHT RGBCOLOR_HEX(0xcccccc) //辅助文字色
//按钮颜色
#define BUTTON_NORMAL_GREEN_COLOR RGBCOLOR_HEX(0x3ADBD2) //目前和MAIN_VISUAL_COLOR一样
#define BUTTON_HIGHLIGHT_GREEN_COLOR RGBCOLOR_HEX(0x1FB2A7)
#define BUTTON_NORMAL_RED_COLOR RGBCOLOR_HEX(0xFF7690) //目前和SECONDARY_VISUAL_COLOR一样
#define BUTTON_HIGHLIGHT_RED_COLOR RGBCOLOR_HEX(0xE75873)
#define BUTTON_DISABLE_COLOR RGBCOLOR_HEX(0xD5D5D5) //目前和DISABLE_COLOR一样
#else //这里的默认色值可以随意,默认填的是用户板的色值
//颜色规范
#define MAIN_VISUAL_COLOR RGBCOLOR_HEX(0x3ADBD2) //主视觉颜色
#define SECONDARY_VISUAL_COLOR RGBCOLOR_HEX(0xFF7690) //辅助颜色
#define SEPARATOR_LINE_COLOR RGBCOLOR_HEX(0xE5E5E5) //分割线颜色、边框颜色
#define BACKGROUND_COLOR RGBCOLOR_HEX(0xF4F3F8) //背景颜色
#define DISABLE_COLOR RGBCOLOR_HEX(0xD5D5D5) //失效颜色
#define BACKGROUND_TIP_COLOR RGBCOLOR_HEX(0xFFFBE4) //提示背景颜色(黄)
#define TAG_BACKGROUND_COLOR RGBCOLOR_HEX(0xF0F0F0) //tag背景颜色
#define TAG_SELECTED_COLOR RGBCOLOR_HEX(0x24DAE0) //tag标签选中颜色
//文字颜色
#define HEADLINE_TEXT_COLOR RGBCOLOR_HEX(0x282828) //一级标题字、主要内容
#define BODY_TEXT_COLOR RGBCOLOR_HEX(0x464646) //正文、普通文字内容
#define AUXILIARY_TEXT_GREEN RGBCOLOR_HEX(0x4ABAB4) //可点击状态的文字更美绿
#define AUXILIARY_TEXT_RED RGBCOLOR_HEX(0xFF7690) //文字的更美红
#define AUXILIARY_TEXT_YELLOW RGBCOLOR_HEX(0x9D704F) //文字的更美黄提示色
#define AUXILIARY_TEXT_COLOR_DARK RGBCOLOR_HEX(0x666666) //辅助文字色
#define AUXILIARY_TEXT_COLOR_LIGHT RGBCOLOR_HEX(0x999999) //辅助文字色
#define AUXILIARY_TEXT_COLOR_EXTRA_LIGHT RGBCOLOR_HEX(0xcccccc) //辅助文字色
//按钮颜色
#define BUTTON_NORMAL_GREEN_COLOR RGBCOLOR_HEX(0x3ADBD2) //目前和MAIN_VISUAL_COLOR一样
#define BUTTON_HIGHLIGHT_GREEN_COLOR RGBCOLOR_HEX(0x1FB2A7)
#define BUTTON_NORMAL_RED_COLOR RGBCOLOR_HEX(0xFF7690) //目前和SECONDARY_VISUAL_COLOR一样
#define BUTTON_HIGHLIGHT_RED_COLOR RGBCOLOR_HEX(0xE75873)
#define BUTTON_DISABLE_COLOR RGBCOLOR_HEX(0xD5D5D5) //目前和DISABLE_COLOR一样
#endif
@implementation UIColor (GMTheme)
/**
用于色值是数字
*/
+ (UIColor *)colorWithHex:(NSInteger)hex{
return [UIColor colorWithHex:hex alpha:1.0];
}
+ (UIColor *)colorWithHex:(NSInteger)hex alpha:(CGFloat)alpha{
CGFloat r = ((hex & 0xFF0000) >> 16) / 255.0;
CGFloat g = ((hex & 0x00FF00) >> 8) / 255.0;
CGFloat b = ((hex & 0x0000FF) >> 0) / 255.0;
return [UIColor colorWithRed:r green:g blue:b alpha:alpha];
}
/**
用于色值字符串
*/
+ (UIColor *)colorWithHexString:(NSString *)hexString{
return [UIColor colorWithHexString:hexString alpha:1.0];
}
+ (UIColor *)colorWithHexString:(NSString *)hexString alpha:(CGFloat)alpha{
unsigned int hex = 0;
NSScanner * scanner = [NSScanner scannerWithString:hexString];
if([scanner scanHexInt:&hex]){
return [UIColor colorWithHex:(NSInteger)hex alpha:alpha];
}else{
return [[UIColor alloc]init];
}
}
/**
色值库里的各种色值
*/
+ (UIColor *)mainVisual{
return MAIN_VISUAL_COLOR;
}
+ (UIColor *)secondaryVisual{
return SECONDARY_VISUAL_COLOR;
}
+ (UIColor *)disable{
return DISABLE_COLOR;
}
+ (UIColor *)separatorLine{
return SEPARATOR_LINE_COLOR;
}
+ (UIColor *)background{
return BACKGROUND_COLOR;
}
+ (UIColor *)backgroundTip{
return BACKGROUND_TIP_COLOR;
}
+ (UIColor *)tagBackground{
return TAG_BACKGROUND_COLOR;
}
+ (UIColor *)headlineText{
return HEADLINE_TEXT_COLOR;
}
+ (UIColor *)bodyText{
return BODY_TEXT_COLOR;
}
+ (UIColor *)auxiliaryTextGreen{
return AUXILIARY_TEXT_GREEN;
}
+ (UIColor *)auxiliaryTextRed{
return AUXILIARY_TEXT_RED;
}
+ (UIColor *)auxiliaryTextYellow{
return AUXILIARY_TEXT_YELLOW;
}
+ (UIColor *)auxiliaryTextDark{
return AUXILIARY_TEXT_COLOR_DARK;
}
+ (UIColor *)auxiliaryTextLight{
return AUXILIARY_TEXT_COLOR_LIGHT;
}
+ (UIColor *)auxiliaryTextExtraLight{
return AUXILIARY_TEXT_COLOR_EXTRA_LIGHT;
}
+ (UIColor *)buttonNormalGreen{
return BUTTON_NORMAL_GREEN_COLOR;
}
+ (UIColor *)buttonHighlightGreen{
return BUTTON_HIGHLIGHT_GREEN_COLOR;
}
+ (UIColor *)buttonNormalRed{
return BUTTON_NORMAL_RED_COLOR;
}
+ (UIColor *)buttonHighlightRed{
return BUTTON_HIGHLIGHT_RED_COLOR;
}
+ (UIColor *)buttonDisable{
return BUTTON_DISABLE_COLOR;
}
+ (UIColor *)tagSelectedGreen {
return TAG_SELECTED_COLOR;
}
@end
//
// GMConstant.h
// GMKit
//
// Created by wangyang on 2017/11/8.
//
#import <Foundation/Foundation.h>
#define MAINSCREEN_FRAME [[UIScreen mainScreen] bounds]
#define MAINSCREEN_WIDTH MAINSCREEN_FRAME.size.width
#define MAINSCREEN_HEIGHT MAINSCREEN_FRAME.size.height
#define ONE_PIXEL (1/[UIScreen mainScreen].scale)
#define APP_VERSION [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]
#define APP_BUILD_VERSION [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]
@interface Constant: NSObject
@property (nonatomic, readonly, class) CGRect screenBounds;
@property (nonatomic, readonly, class) CGFloat screenWidth;
@property (nonatomic, readonly, class) CGFloat statusBarHeight;
@property (nonatomic, readonly, class) CGFloat screenHeight;
@property (nonatomic, readonly, class) CGFloat onePixel;
@property (nonatomic, readonly, class) CGFloat deviceScale;
@property (nonatomic, readonly, class) NSString* appName;
@property (nonatomic, readonly, class) NSString* appVersion;
@property (nonatomic, readonly, class) NSString* appBuildVersion;
/*
appHome下面有Document、Libray、tmp等目录。注意与appBundle区分
*/
@property (nonatomic, readonly, class) NSString* appHome;
@property (nonatomic, readonly, class) NSString* appTemp;
@property (nonatomic, readonly, class) NSString* appDocument;
// 主应用所在目录
@property (nonatomic, readonly, class) NSString* appBundle;
@end
//
// GMConstant.m
// GMKit
//
// Created by wangyang on 2017/11/8.
//
#import "Constant.h"
@implementation Constant
+ (CGRect)screenBounds {
return [[UIScreen mainScreen] bounds];
}
+ (CGFloat)screenWidth {
return [[UIScreen mainScreen] bounds].size.width;
}
+ (CGFloat)statusBarHeight{
return [UIApplication sharedApplication].statusBarFrame.size.height;
}
+ (CGFloat)screenHeight {
return [[UIScreen mainScreen] bounds].size.height;
}
+ (CGFloat)onePixel {
return 1/[UIScreen mainScreen].scale;
}
+ (CGFloat)deviceScale {
return [UIScreen mainScreen].scale;
}
+ (NSString *)appName {
return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"];
}
+ (NSString *)appVersion {
return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
}
+ (NSString *)appBuildVersion {
return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
}
+ (NSString *)appHome {
return NSHomeDirectory();
}
+ (NSString *)appTemp {
return NSTemporaryDirectory();
}
+ (NSString *)appDocument {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
}
+ (NSString *)appBundle {
return [NSBundle mainBundle].resourcePath;
}
@end
//
// SystemVersion.h
// GMKit
//
// Created by wangyang on 2017/11/8.
//
#import <Foundation/Foundation.h>
#define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options: NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options: NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options: NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options: NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options: NSNumericSearch] != NSOrderedDescending)
@interface SystemVersion : NSObject
+ (BOOL)equalTo:(NSString *)version;
+ (BOOL)greaterThan:(NSString *)version;
+ (BOOL)greaterThanOrEqualTo:(NSString *)version;
+ (BOOL)lessThan:(NSString *)version;
+ (BOOL)lessThanOrEqualTo:(NSString *)version;
@end
//
// SystemVersion.m
// GMKit
//
// Created by wangyang on 2017/11/8.
//
#import "SystemVersion.h"
@implementation SystemVersion
+ (BOOL)equalTo:(NSString *)version {
return [[[UIDevice currentDevice] systemVersion] compare:version options: NSNumericSearch] == NSOrderedSame;
}
+ (BOOL)greaterThan:(NSString *)version {
return [[[UIDevice currentDevice] systemVersion] compare:version options: NSNumericSearch] == NSOrderedDescending;
}
+ (BOOL)greaterThanOrEqualTo:(NSString *)version {
return [[[UIDevice currentDevice] systemVersion] compare:version options: NSNumericSearch] != NSOrderedAscending;
}
+ (BOOL)lessThan:(NSString *)version {
return [[[UIDevice currentDevice] systemVersion] compare:version options: NSNumericSearch] == NSOrderedAscending;
}
+ (BOOL)lessThanOrEqualTo:(NSString *)version {
return [[[UIDevice currentDevice] systemVersion] compare:version options: NSNumericSearch] != NSOrderedDescending;
}
@end
// The MIT License (MIT)
//
// Copyright (c) 2015-2016 forkingdog ( https://github.com/forkingdog )
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#import <UIKit/UIKit.h>
/// "UINavigation+FDFullscreenPopGesture" extends UINavigationController's swipe-
/// to-pop behavior in iOS 7+ by supporting fullscreen pan gesture. Instead of
/// screen edge, you can now swipe from any place on the screen and the onboard
/// interactive pop transition works seamlessly.
///
/// Adding the implementation file of this category to your target will
/// automatically patch UINavigationController with this feature.
@interface UINavigationController (FDFullscreenPopGesture)
/// The gesture recognizer that actually handles interactive pop.
@property (nonatomic, strong, readonly) UIPanGestureRecognizer *fd_fullscreenPopGestureRecognizer;
/// A view controller is able to control navigation bar's appearance by itself,
/// rather than a global way, checking "fd_prefersNavigationBarHidden" property.
/// Default to YES, disable it if you don't want so.
@property (nonatomic, assign) BOOL fd_viewControllerBasedNavigationBarAppearanceEnabled;
@end
/// Allows any view controller to disable interactive pop gesture, which might
/// be necessary when the view controller itself handles pan gesture in some
/// cases.
@interface UIViewController (FDFullscreenPopGesture)
/// Whether the interactive pop gesture is disabled when contained in a navigation
/// stack.
@property (nonatomic, assign) BOOL fd_interactivePopDisabled;
/// Indicate this view controller prefers its navigation bar hidden or not,
/// checked when view controller based navigation bar's appearance is enabled.
/// Default to NO, bars are more likely to show.
@property (nonatomic, assign) BOOL fd_prefersNavigationBarHidden;
/// Max allowed initial distance to left edge when you begin the interactive pop
/// gesture. 0 by default, which means it will ignore this limit.
@property (nonatomic, assign) CGFloat fd_interactivePopMaxAllowedInitialDistanceToLeftEdge;
@end
//
// GMAnnotation.h
// Gengmei
//
// Created by Thierry on 4/25/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@interface GMAnnotation : NSObject<MKAnnotation>
@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;
-(id) initWithCoordinate:(CLLocationCoordinate2D) coords;
@end
//
// GMAnnotation.m
// Gengmei
//
// Created by Thierry on 4/25/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import "GMAnnotation.h"
@implementation GMAnnotation
-(id) initWithCoordinate:(CLLocationCoordinate2D) coords
{
if (self = [super init]) {
self.coordinate = coords;
}
return self;
}
@end
//
// GMButton.h
// Gengmei
//
// Created by Thierry on 12/26/14.
// Copyright (c) 2014 Wanmeichuangyi. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
//渐变按钮渐变方向
typedef NS_ENUM(NSUInteger, GMGradientType) {
GMGradientTypeTopToBottom = 0, //从上到小
GMGradientTypeLeftToRight = 1, //从左到右
GMGradientTypeLeftUpToRightLow = 2, //左上到右下
GMGradientTypeRightUpToLeftLow = 3, //右上到左下
};
//见设计稿(UI组件化->组件_按钮.sketch)
typedef NS_ENUM(NSUInteger, GMButtonType) {
GMButtonTypeGreen, //绿色无边框直角矩形
GMButtonTypeGreenRoundCorner, //绿色带6px的圆角无边框矩形
GMButtonTypeGreenSemicircle, //绿色半圆无边框矩形
GMButtonTypeGreenRoundCornerBorder, //绿色、6px圆角、1px的有边框的矩形
GMButtonTypeGreenSemicircleBorder, //绿色、半圆、1px的有边框的矩形
GMButtonTypeGreenRoundCornerGradient, //绿色、6px圆角、无边框的渐变矩形
GMButtonTypeGreenSemicircleGradient, //绿色、半圆、无边框的渐变矩形
GMButtonTypeRed, //红色无边框直角矩形
GMButtonTypeRedRoundCorner, //红色带6px的圆角无边框矩形
GMButtonTypeRedSemicircle, //红色半圆无边框矩形
GMButtonTypeRedRoundCornerBorder, //红色、6px圆角、1px的有边框的的矩形
GMButtonTypeRedRoundCornerGradient, //红色、6px圆角、无边框的渐变矩形
GMButtonTypeRedSemicircleGradient, //红色、半圆、无边框的渐变矩形
GMButtonTypeGraySemicircleBorder, //灰色、半圆、1px的有边框的矩形
};
@interface GMButton : UIButton
/**
* @author licong, 16-12-30 17:12:55
*
* 是否支持Button自适应热区,Apple人机交互指南建议,可点击控件的热区最好是44*44,默认是NO,不支持
*
* @since 5.8
*/
@property (nonatomic, assign) BOOL enableAdaptive;
/**
* @author licong, 16-12-30 17:12:31
*
* 自适应热区宽,默认是 44
*
* @since 5.8
*/
@property (nonatomic, assign) float adaptiveHotAreaWidth;
/**
* @author licong, 16-12-30 17:12:09
*
* 自适应热区高,默认是 44
*
* @since 5.8
*/
@property (nonatomic, assign) float adaptiveHotAreaHeight;
/**
* @author licong, 16-12-30 17:12:30
*
* 初始化方法
*
* @since 5.8
*/
- (void)setup __attribute__((objc_requires_super));
/**
* @author licong, 16-12-30 17:12:46
*
* 创建一个button,并设置好它的title、backgroundColor、size、titleColor
*
* @param title title
* @param bgColor backgroundColor
* @param size 大小
* @param titleColor title标题
*
* @return 返回创建好的button
*
* @since 5.8
*/
+ (instancetype)buttonWithTitle:(nullable NSString *)title
backgroundColor:(nullable UIColor *)bgColor
titleFontSize:(CGFloat)size
titleColor:(nullable UIColor *)titleColor;
/**
* @author licong
*
* UI组件化后自定制Button
*
* @param customType 工厂模式下的button类型
*
* @return 返回创建好的button
*
* @since 6.2.0
*/
+ (instancetype)buttonWithCustomType:(GMButtonType)customType;
/**
* @author licong, 16-12-30 17:12:29
*
* 根据Button的状态设置对应的背景颜色
*
* @param backgroundColor button的背景颜色
* @param state button的controlState
*
* @since 5.8
*/
- (void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state;
@end
NS_ASSUME_NONNULL_END
This diff is collapsed.
//
// GMCollectionView
// Gengmei
//
// Created by Thierry on 1/9/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface GMCollectionView : UICollectionView
@end
@interface UICollectionView (Reuse)
- (void)registerHeader:(Class)headerClass NS_SWIFT_NAME(register(header:));
- (void)registerFooter:(Class)footerClass NS_SWIFT_NAME(register(footer:));
- (void)registerCell:(Class)cellClass NS_SWIFT_NAME(register(cell:));
- (__kindof UICollectionViewCell *)dequeueCell:(Class)cellClass forIndexPath:(NSIndexPath *)indexPath NS_SWIFT_NAME(dequeue(cell:for:));
- (__kindof UICollectionReusableView *)dequeueHeader:(Class)headerClass forIndexPath:(NSIndexPath *)indexPath NS_SWIFT_NAME(dequeue(header:for:));
- (__kindof UICollectionReusableView *)dequeueFooter:(Class)footerClass forIndexPath:(NSIndexPath *)indexPath NS_SWIFT_NAME(dequeue(footer:for:));
@end
//
// GMCollectionView
// Gengmei
//
// Created by Thierry on 1/9/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import "GMCollectionView.h"
@implementation GMCollectionView
@end
@implementation UICollectionView (Reuse)
- (void)registerHeader:(Class)headerClass {
[self registerClass:headerClass forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:NSStringFromClass(headerClass)];
}
- (void)registerFooter:(Class)footerClass {
[self registerClass:footerClass forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:NSStringFromClass(footerClass)];
}
- (void)registerCell:(Class)cellClass {
[self registerClass:cellClass forCellWithReuseIdentifier:NSStringFromClass(cellClass)];
}
- (UICollectionViewCell *)dequeueCell:(Class)cellClass forIndexPath:(NSIndexPath *)indexPath {
return [self dequeueReusableCellWithReuseIdentifier:NSStringFromClass(cellClass) forIndexPath:indexPath];
}
- (UICollectionReusableView *)dequeueHeader:(Class)headerClass forIndexPath:(NSIndexPath *)indexPath {
return [self dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:NSStringFromClass(headerClass) forIndexPath:indexPath];
}
- (UICollectionReusableView *)dequeueFooter:(Class)footerClass forIndexPath:(NSIndexPath *)indexPath {
return [self dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:NSStringFromClass(footerClass) forIndexPath:indexPath];
}
@end
//
// GMSimpleCell.h
// Gengmei
// 简单的Collection Cell(图片+文字)
// Created by Thierry on 1/7/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "GMImageView.h"
#import "GMLabel.h"
#import "GMReuseIdentifier.h"
@interface GMCollectionViewCell : UICollectionViewCell <GMReuseIdentifier>
- (void)setup;
@end
@interface UICollectionReusableView (Reusable) <GMReuseIdentifier>
+ (NSString *)defaultReuseIdentifier;
@end
//
// GMSimpleCell.m
// Gengmei
//
// Created by Thierry on 1/7/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import "GMCollectionViewCell.h"
#import "GMFont.h"
#import <Constant.h>
#import <UIColor+GMTheme.h>
#define CELL_HEIGHT self.contentView.frame.size.height
#define CELL_WIDTH self.contentView.frame.size.width
@implementation GMCollectionViewCell
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
}
- (void)awakeFromNib{
[super awakeFromNib];
[self setup];
}
- (void)setup{
self.clipsToBounds = YES;
}
@end
@implementation UICollectionReusableView (Reusable)
+ (NSString *)defaultReuseIdentifier {
return NSStringFromClass(self.class);
}
@end
//
// GMControl.h
// Gengmei
//
// Created by wangyang on 9/14/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface GMControl : UIControl
/**
* @brief 不需要重写 init 方法,如果代码里调用了 init 方法,SDK 会自动调用 initWithFrame
*
*/
- (void)setup __attribute__((objc_requires_super));
@end
//
// GMControl.m
// Gengmei
//
// Created by wangyang on 9/14/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import "GMControl.h"
@implementation GMControl
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder{
self = [super initWithCoder:aDecoder];
[self setup];
return self;
}
- (void)setup{
}
@end
//
// GMDatePicker.h
// ZhengXing
//
// Created by Sean Lee on 11/19/14.
// Copyright (c) 2014 Wanmei Creative. All rights reserved.
//
#import <UIKit/UIKit.h>
@protocol GMDatePickerDelegate <NSObject>
/**
* @author licong, 16-01-08 15:01:24
*
* 弹出DatePicker
*
* @since 5.8.0
*/
- (void)openPicker;
@end
@interface GMDatePickerView : UIView<UIGestureRecognizerDelegate>
@property (nonatomic, strong) UIView * contentView;
@property (nonatomic, strong) UIDatePicker *picker;
@property (nonatomic, assign) id<GMDatePickerDelegate> delegate;
@property (nonatomic, strong) NSString * leftButtonTitle;
@property (nonatomic, strong) NSString * titleLabelTitle;
@property (nonatomic, copy) void (^ confirmButtonClickBolck) (NSDate * selecteDate);
-(void)show;
-(void)hide;
@end
//
// GMDatePicker.m
// ZhengXing
//
// Created by Sean Lee on 11/19/14.
// Copyright (c) 2014 Wanmei Creative. All rights reserved.
//
#import "GMDatePickerView.h"
#import "GMFont.h"
#import <Masonry/Masonry.h>
#import <Constant.h>
#import <UIColor+GMTheme.h>
#define DATAPICKER_HEIGHT
@interface GMDatePickerView ()
@property (nonatomic,strong)UIButton * leftButton;
@property (nonatomic,strong)UILabel * titleLabel;
@property (nonatomic,strong)UIButton * rightButton;
@end
@implementation GMDatePickerView
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor colorWithWhite:0 alpha:.6];
self.hidden = YES;
[self createDatePicker];
}
return self;
}
- (void)createDatePicker{
_contentView = [[UIView alloc]initWithFrame:CGRectZero];
_contentView.frame = CGRectMake(0, [[UIScreen mainScreen] bounds].size.width, self.frame.size.width, 255);
_contentView.backgroundColor = UIColor.whiteColor;
[self addSubview:_contentView];
_picker = [[UIDatePicker alloc]initWithFrame:CGRectMake(0, 39, [[UIScreen mainScreen] bounds].size.width, 216)];
_picker.backgroundColor = UIColor.whiteColor;
_picker.datePickerMode = UIDatePickerModeDate;
//2037-12-31 23:59:59的时间戳
_picker.maximumDate = [NSDate dateWithTimeIntervalSince1970:2145887999];
[_picker setDate:[NSDate date] animated:NO];
[_picker addTarget:self action:@selector(didPickerSelected:) forControlEvents:UIControlEventValueChanged];
[_contentView addSubview:_picker];
_picker.layer.borderWidth = 1;
_picker.layer.borderColor = [UIColor separatorLine].CGColor;
_leftButton = [UIButton buttonWithType:UIButtonTypeCustom];
_leftButton.tag = 1;
_leftButton.hidden = YES;
[_contentView addSubview:_leftButton];
[_leftButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(_contentView.mas_left).with.offset(16);
make.top.equalTo(_contentView.mas_top).offset(4);
}];
[_leftButton.titleLabel setFont:[UIFont gmFont:16]];
[_leftButton setTitleColor:[UIColor mainVisual] forState:UIControlStateNormal];
[_leftButton addTarget:self action:@selector(confirmButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
_titleLabel = [[UILabel alloc]init];
_titleLabel.hidden = YES;
_titleLabel.font = [UIFont gmFont:17];
[_titleLabel setTextColor:UIColor.blackColor];
[_contentView addSubview:_titleLabel];
[_titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(_contentView);
make.top.equalTo(_leftButton.mas_top).with.offset(6);
}];
_rightButton = [UIButton buttonWithType:UIButtonTypeCustom];
_rightButton.tag = 2;
[_contentView addSubview:_rightButton];
[_rightButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(_contentView.mas_right).with.offset(-16);
make.top.equalTo(_contentView.mas_top).offset(4);
}];
[_rightButton setTitleColor:[UIColor mainVisual] forState:UIControlStateNormal];
[_rightButton setTitle:@"确定" forState:UIControlStateNormal];
[_rightButton.titleLabel setFont:[UIFont gmFont:16]];
[_rightButton addTarget:self action:@selector(confirmButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];
tapGesture.delegate = self;
[self addGestureRecognizer:tapGesture];
}
- (void)setLeftButtonTitle:(NSString *)leftButtonTitle{
_leftButtonTitle= leftButtonTitle;
_leftButton.hidden = NO;
[_leftButton setTitle:leftButtonTitle forState:UIControlStateNormal];
}
- (void)setTitleLabelTitle:(NSString *)titleLabelTitle{
_titleLabelTitle = titleLabelTitle;
_titleLabel.hidden = NO;
_titleLabel.text = titleLabelTitle;
}
- (void)didPickerSelected:(id)sender{
if (self.confirmButtonClickBolck) {
self.confirmButtonClickBolck(_picker.date);
}
}
- (void)confirmButtonClicked:(id)sender{
UIButton * button = (UIButton *)sender;
if (button.tag ==1) {
if (self.confirmButtonClickBolck) {
self.confirmButtonClickBolck(nil);
}
}else if(button.tag == 2){
if (self.confirmButtonClickBolck) {
self.confirmButtonClickBolck(_picker.date);
}
}
[self hide];
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
if([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]])
{
CGPoint touch = [gestureRecognizer locationInView:self];
if(!CGRectContainsPoint(_contentView.frame, touch))
{
return YES;
}
return NO;
}
return YES;
}
- (void)tap:(UITapGestureRecognizer *)recognizer
{
if ([self.delegate respondsToSelector:@selector(openPicker)]) {
[self.delegate openPicker];
}
}
-(void)show
{
[_picker setDate:[NSDate date] animated:NO];
[UIView animateWithDuration:0.2 delay:0.0f options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.contentView.frame = CGRectMake(0, MAINSCREEN_HEIGHT - 255, MAINSCREEN_WIDTH, self.contentView.frame.size.height);
} completion:^(BOOL finished) {
}];
}
-(void)hide
{
[UIView animateWithDuration:0.2 delay:0.0f options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.contentView.frame = CGRectMake(0, MAINSCREEN_HEIGHT, MAINSCREEN_WIDTH, self.contentView.frame.size.height);
self.backgroundColor = [UIColor colorWithWhite:0 alpha:0];
} completion:^(BOOL finished) {
self.hidden = YES;
self.backgroundColor = [UIColor colorWithWhite:0 alpha:.3];
}];
}
@end
//
// GMEmptyView.h
// Gengmei
//
// Created by Terminator on 15/10/16.
// Copyright © 2015年 Wanmeichuangyi. All rights reserved.
//
#import "GMView.h"
@class GMButton;
typedef NS_ENUM(NSUInteger, GMEmptyViewType) {
GMEmptyViewTypeEmpty,
GMEmptyViewTypeException
};
@protocol GMEmptyViewDelegate <NSObject>
- (void)emptyViewDidClickReload;
@end
@interface GMEmptyView : UIView
@property (nonatomic, strong) UIImageView *tipIcon;
@property (nonatomic, strong) UILabel *tipLabel;
@property (nonatomic, strong) GMButton *tipButton;
@property (nonatomic, assign) GMEmptyViewType type;
@property (nonatomic, weak) id<GMEmptyViewDelegate> delegate;
@end
//
// GMEmptyView.m
// Gengmei
//
// Created by Terminator on 15/10/16.
// Copyright © 2015年 Wanmeichuangyi. All rights reserved.
//
#import "GMEmptyView.h"
#import <Masonry/Masonry.h>
#import "GMButton.h"
#import "GMFont.h"
#import "UIView+Layout.h"
#import <UIColor+GMTheme.h>
#import <Constant.h>
@implementation GMEmptyView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
}
- (void)awakeFromNib{
[super awakeFromNib];
[self setup];
}
- (void)setup{
self.backgroundColor = UIColor.whiteColor;
_tipIcon = [UIImageView new];
_tipLabel = [UILabel new];
_tipButton = [GMButton buttonWithCustomType:GMButtonTypeRedSemicircleGradient];
_tipButton.frame = CGRectMake(0, 0, 10, 10); //给一个默认的rect,让系统调用DrawRect方法
[self addSubview:_tipIcon];
[_tipIcon addSubview:_tipLabel];
[self addSubview:_tipButton];
_tipLabel.numberOfLines = 2;
_tipLabel.preferredMaxLayoutWidth = 300;
_tipLabel.textColor = UIColor.bodyText;
_tipLabel.font = [UIFont gmFont:15];
_tipLabel.textAlignment = NSTextAlignmentCenter;
_tipButton.hidden = YES;
[_tipButton setTitle:@"重新加载" forState:UIControlStateNormal];
_tipButton.titleLabel.font = [UIFont gmFont:16];
[_tipButton setTitleColor:UIColor.bodyText forState:UIControlStateNormal];
[_tipButton addTarget:self action:@selector(reloadBtnTap) forControlEvents:UIControlEventTouchUpInside];
// 剩下的位置信息将在layoutSubViews在指定
[_tipLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(_tipIcon.mas_bottom).offset(-15);
make.centerX.mas_equalTo(self);
}];
[_tipButton mas_remakeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self);
make.width.mas_equalTo(150);
make.height.mas_equalTo(33);
}];
}
- (void)setType:(GMEmptyViewType)type{
_type = type;
switch (self.type) {
case GMEmptyViewTypeEmpty:{
_tipButton.hidden = YES;
_tipIcon.image = [UIImage imageNamed:@"empty"];
_tipLabel.text = @"此处太寂寥,社区等你撩";
break;
}
case GMEmptyViewTypeException:{
_tipButton.hidden = NO;
_tipIcon.image = [UIImage imageNamed:@"network_failed"];
_tipLabel.text = @"原谅我一看到美人就不淡定";
}
default:
break;
}
}
- (void)layoutSubviews {
[super layoutSubviews];
// 在即将显示时,通过判断emptyView.y的坐标来优化subviews的坐标,以达到UI的要求
CGRect emptyViewFrameInWindow = [self.superview convertRect:self.frame toView:[UIApplication sharedApplication].keyWindow];
CGRect newTipIconFrameInWindow = CGRectMake(0, 0, 175, 199);
newTipIconFrameInWindow.origin.x = (MAINSCREEN_WIDTH - newTipIconFrameInWindow.size.width) / 2;
/*
以下坐标均相对于window
按照设计图
如果emptyViewFrameInWindow.y <= 64,那么tipIcon.y = 155
如果emptyViewFrameInWindow.y > 64 && y < 140,那么tipIcon.y = 185
另外测试时发现标签详情页的头部更多,所有else分支也成为了一种可能
如果emptyViewFrameInWindow.y > 140,那么tipIcon.y = 220
*/
// 按照设计图总结出来,
if (emptyViewFrameInWindow.origin.y <= 64) {
// 正常空间
newTipIconFrameInWindow.origin.y = 155;
} else if (emptyViewFrameInWindow.origin.y > 64.0 && emptyViewFrameInWindow.origin.y <= 140){
// 需要更多空间
newTipIconFrameInWindow.origin.y = 185;
} else {
newTipIconFrameInWindow.origin.y = 220;
}
CGRect newTipIconFrame = [[UIApplication sharedApplication].keyWindow convertRect:newTipIconFrameInWindow toView:self];
newTipIconFrameInWindow.origin.y = newTipIconFrame.origin.y;
_tipIcon.frame = newTipIconFrameInWindow;
_tipButton.top = _tipIcon.bottom + 15;
}
- (void)reloadBtnTap {
if ([self.delegate respondsToSelector:@selector(emptyViewDidClickReload)]) {
[self.delegate emptyViewDidClickReload];
}
}
@end
//
// gmFont.h
// Gengmei
//
// Created by Thierry on 2/9/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import <UIKit/UIKit.h>
//#define [UIFont gmFont:size] [UIFont gm_gmFont:size]
//#define gmBoldFont(size) [UIFont gm_boldgmFont:size]
//#define gmLightFont(size) [UIFont gm_lightgmFont:size]
@interface UIFont (gmFont)
+ (UIFont *)gmFont:(NSInteger)size;
+ (UIFont *)gmBoldFont:(NSInteger)size;
+ (UIFont *)gmLightFont:(NSInteger)size;
@end
#pragma mark - 对于swift代码,创建SwiftFont.swift,将下面内容拷贝进去
/*
public func [UIFont gmFont:_ size: Int] -> UIFont {
return UIFont.gm_font(withSize: size)
}
public func gmBoldFont(_ size: Int) -> UIFont {
return UIFont.gm_boldFont(withSize: size)
}
public func gmLightFont(_ size: Int) -> UIFont {
return UIFont.gm_lightFont(withSize: size)
}
*/
//
// gmFont.m
// Gengmei
//
// Created by Thierry on 2/9/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import "GMFont.h"
#import "SystemVersion.h"
/*
Family:'PingFang SC'
font:'PingFangSC-Medium'
font:'PingFangSC-Semibold'
font:'PingFangSC-Light'
font:'PingFangSC-Ultralight'
font:'PingFangSC-Regular'
font:'PingFangSC-Thin'
*/
@implementation UIFont (gmFont)
+ (UIFont *)gmFont:(NSInteger)size {
if (@available(iOS 9.0, *)) {
return [UIFont fontWithName:@"PingFangSC-Regular" size:size];
} else {
return [UIFont systemFontOfSize:size];
}
}
+ (UIFont *)gmBoldFont:(NSInteger)size {
if (@available(iOS 9.0, *)) {
return [UIFont fontWithName:@"PingFangSC-Medium" size:size];
} else {
return [UIFont boldSystemFontOfSize:size];
}
}
+ (UIFont *)gmLightFont:(NSInteger)size {
if (@available(iOS 9.0, *)) {
return [UIFont fontWithName:@"PingFangSC-Light" size:size];
} else {
return [UIFont systemFontOfSize:size];
}
}
@end
//
// GMHightlightLabel.h
// Gengmei
//
// Created by wangyang on 6/11/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import <GMKit/GMLabel.h>
NS_ASSUME_NONNULL_BEGIN
/**
* @brief 设置font,textColor,及GMHightlightLabel特有的lineHeight、hightlightColor以配置要显示的字符串属性
*/
@interface GMHighlightLabel : GMLabel
/**
* @brief 对齐方式
*/
@property (nonatomic, assign) NSTextAlignment aligment;
/**
* @brief 行高
*/
@property (nonatomic, assign) CGFloat lineHeight;
/**
* @brief 默认是 MAIN_VISUL_COLOR
*/
@property (nonatomic, strong) UIColor *hightlightColor;
/**
* @brief 默认是 MAIN_VISUL_COLOR
*/
@property (nonatomic, strong) UIColor *normalColor;
/**
* @brief 带高亮标志的原始字符串
*
*/
@property (nonatomic, copy) NSString *originalHightlightText;
/**
* @brief 默认不加粗
*/
@property (nonatomic, strong) UIFont *hightlightFont;
/**
* @author licong, 16-12-30 18:12:58
*
* 创建一个高亮lable
*
* @param color label颜色
* @param font title的font大小
*
* @return 一个高亮lable
*
* @since 5.8
*/
+ (GMHighlightLabel *)hightLabelTextColor:(UIColor *)color andFont:(CGFloat)font;
@end
NS_ASSUME_NONNULL_END
//
// GMHightlightLabel.m
// Gengmei
//
// Created by wangyang on 6/11/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import "GMHighlightLabel.h"
#import "GMFont.h"
#import <Constant.h>
#import <UIColor+GMTheme.h>
@implementation GMHighlightLabel
- (void)setOriginalHightlightText:(NSString *)originalHightlightText{
_originalHightlightText = originalHightlightText;
if (_originalHightlightText.length == 0) {
self.attributedText = nil;
return;
}
if (!_hightlightColor) {
_hightlightColor = [UIColor mainVisual];
}
if (!_normalColor) {
_normalColor = [UIColor bodyText];
}
NSMutableAttributedString *attString = [self parseString:_originalHightlightText];
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
style.lineSpacing = _lineHeight;
style.lineBreakMode = NSLineBreakByTruncatingTail;
style.alignment = _aligment;
// 如果有高亮,attString不为空,那只加一个NSParagraphStyleAttributeName属性
if (self.lineHeight > 0 && attString.length > 0) {
[attString addAttribute:NSParagraphStyleAttributeName value:style range:NSMakeRange(0, attString.length)];
}
// 如果没有走到正则里面,说明没有需要高亮的内容,设置普通颜色就好
else if (attString.length == 0) {
NSAttributedString *subString = [[NSAttributedString alloc] initWithString:_originalHightlightText attributes:@{NSFontAttributeName : self.font, NSForegroundColorAttributeName:_normalColor, NSParagraphStyleAttributeName:style}];
[attString appendAttributedString:subString];
}
self.attributedText = attString;
}
- (NSMutableAttributedString *)parseString:(NSString *)originalString{
NSError *error;
NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:@"([\\w\\W]*)<ems>([\\w\\W]+)<\\/ems>([\\w\\W]*)" options:0 error:&error];
if (error) {
self.attributedText = nil;
}
NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] init];
[expression enumerateMatchesInString:originalString options:0 range:NSMakeRange(0, originalString.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
// 根据NSTextCheckingResult的rangeAtIndex方法文档,result至少会有一个range,这个range是匹配它自身全部的,所以正则匹配的其它range是从1开始的
// <ems></ems>将string分隔为string1, string2, string3,分别对应前中后
NSString *string1 = [originalString substringWithRange:[result rangeAtIndex:1]];
NSAttributedString *attrString1 = [self parseString:string1];
if (attrString1.length > 0) {
[attString appendAttributedString:attrString1];
}else{
NSAttributedString *subString = [[NSAttributedString alloc] initWithString:string1 attributes:@{NSFontAttributeName : self.font, NSForegroundColorAttributeName:_normalColor}];
[attString appendAttributedString:subString];
}
NSString *string2 = [originalString substringWithRange:[result rangeAtIndex:2]];
NSAttributedString *attrString2 = [self parseString:string2];
if (attrString2.length > 0) {
[attString appendAttributedString:attrString2];
}else{
if (self.hightlightFont != nil) {
NSAttributedString *subString = [[NSAttributedString alloc] initWithString:string2 attributes:@{NSFontAttributeName : self.hightlightFont, NSForegroundColorAttributeName:_hightlightColor}];
[attString appendAttributedString:subString];
} else {
NSAttributedString *subString = [[NSAttributedString alloc] initWithString:string2 attributes:@{NSFontAttributeName : self.font, NSForegroundColorAttributeName:_hightlightColor}];
[attString appendAttributedString:subString];
}
}
NSString *string3 = [originalString substringWithRange:[result rangeAtIndex:3]];
NSAttributedString *attrString3 = [self parseString:string3];
if (attrString3.length > 0) {
[attString appendAttributedString:attrString3];
}else{
NSAttributedString *subString = [[NSAttributedString alloc] initWithString:string3 attributes:@{NSFontAttributeName : self.font, NSForegroundColorAttributeName:_normalColor}];
[attString appendAttributedString:subString];
}
}];
return attString;
}
+ (GMHighlightLabel *)hightLabelTextColor:(UIColor *)color andFont:(CGFloat)font {
GMHighlightLabel *label = [[GMHighlightLabel alloc] init];
label.backgroundColor = UIColor.whiteColor;
label.textColor = color;
label.font = [UIFont gmFont:font];
label.hightlightColor = [UIColor mainVisual];
label.hightlightFont = [UIFont gmBoldFont:font];
return label;
}
@end
//
// GMImageView.h
// Gengmei
//
// Created by Thierry on 2/12/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <SDWebImage/SDAnimatedImageView+WebCache.h>
@interface GMImageView : UIImageView
- (void)setImageWithUrlString:(NSString *)urlString placeHolder:(NSString *)placeHolder;
@end
//
// GMImageView.m
// Gengmei
//
// Created by Thierry on 2/12/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import "GMImageView.h"
#import <SDWebImage/UIImageView+WebCache.h>
#import "UIView+Layout.h"
#import <Constant.h>
#import <UIColor+GMTheme.h>
@implementation GMImageView
- (instancetype)initWithImage:(nullable UIImage *)image {
self = [super initWithImage:image];
[self setup];
return self;
}
- (instancetype)initWithImage:(nullable UIImage *)image highlightedImage:(nullable UIImage *)highlightedImage {
self = [super initWithImage:image highlightedImage:highlightedImage];
[self setup];
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
[self setup];
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
[self setup];
return self;
}
- (void)setup {
self.layer.masksToBounds = YES;
}
- (void)setImageWithUrlString:(NSString *)urlString placeHolder:(NSString *)placeHolder{
NSURL *url = [NSURL URLWithString:urlString];
if (placeHolder!=nil && ![placeHolder isEqualToString:@""]) {
[self sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:placeHolder]];
}else{
[self sd_setImageWithURL:url];
}
}
@end
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
//
// GMLoadingView.h
// loadingAnimation
//
// Created by wangyang on 12/23/14.
// Copyright (c) 2014 WY. All rights reserved.
//
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSUInteger, GMLoadingViewType) {
GMLoadingViewTypeGray,
GMLoadingViewTypeGreenLarge,
GMLoadingViewTypeGreenSmall
};
@interface GMLoadingView : UIView
+ (instancetype)loadingViewWithType:(GMLoadingViewType)type;
- (void)begingAnimation;
- (void)endAnimation;
@end
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
//
// GMRateView.h
// Gengmei
//
// Created by Thierry on 1/22/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface GMRateView : UIView
@property (nonatomic,assign) NSInteger rate;
- (void)initView;
@end
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
//
// GMTopSearchButton.h
// Gengmei
//
// Created by wangyang on 4/27/15.
// Copyright (c) 2015 Wanmeichuangyi. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "GMButton.h"
@interface GMTopSearchButton : GMButton
@end
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment