Commit f722fb2b authored by 李震's avatar 李震

提高版本号

parent 81c8fb80
//
// Dictionary+GM.swift
// Gengmei
//
// Created by Thierry on 16/6/15.
// Copyright © 2016年 更美互动信息科技有限公司. All rights reserved.
//
import Foundation
public extension Dictionary {
func merge(_ dict: Dictionary) -> Dictionary {
var mutableCopy = self
for (key, value) in dict {
// If both dictionaries have a value for same key, the value of the other dictionary is used.
mutableCopy[key] = value
}
return mutableCopy
}
}
//
// NSDictionary+LogCategory.h
//
//
// Created by liulujie on 18/1/10.
// Copyright © 2018年 RedSoft. All rights reserved.
//
#import <Foundation/Foundation.h>
// 如果需要关掉兼容中文的打印,把下面的宏注释掉即可
#define UseLogChinese
@interface NSArray (Log)
@end
@interface NSDictionary (Log)
@end
//
// NSDictionary+LogCategory.m
//
//
// Created by liulujie on 18/1/10.
// Copyright © 2018年 RedSoft. All rights reserved.
//
#import "LogCategory.h"
#import <objc/runtime.h>
@implementation NSArray (Log)
#ifdef UseLogChinese
- (NSString *)debugDescription {
return [NSString stringWithFormat:@"<%@ %p> %@", NSStringFromClass([self class]), self, [self descriptionWithLocale:nil]];
}
- (NSString *)description {
return [NSString stringWithFormat:@"<%@ %p> %@", NSStringFromClass([self class]), self, [self descriptionWithLocale:nil]];
}
- (NSString *)descriptionWithLocale:(id)locale {
NSMutableString * string = [NSMutableString string];
[string appendString:@"[\n"];
NSUInteger count = self.count;
[self enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSString * temp = nil;
if ([obj respondsToSelector:@selector(descriptionWithLocale:)]) {
temp = [obj performSelector:@selector(descriptionWithLocale:) withObject:locale];
temp = [temp stringByReplacingOccurrencesOfString:@"\n" withString:@"\n\t"];
} else {
temp = [obj performSelector:@selector(description) withObject:nil];
if ([obj isKindOfClass:[NSString class]]) {
temp = [NSString stringWithFormat:@"\"%@\"", temp];
}
}
[string appendFormat:@"\t%@", temp];
if (idx+1 != count) {
[string appendString:@","];
}
[string appendString:@"\n"];
}];
[string appendString:@"]"];
return string;
}
#endif
@end
@implementation NSDictionary (Log)
#ifdef UseLogChinese
- (NSString *)debugDescription {
return [NSString stringWithFormat:@"<%@ %p> %@", NSStringFromClass([self class]), self, [self descriptionWithLocale:nil]];
}
- (NSString *)description {
return [NSString stringWithFormat:@"<%@ %p> %@", NSStringFromClass([self class]), self, [self descriptionWithLocale:nil]];
}
- (NSString *)descriptionWithLocale:(id)locale {
NSMutableString * string = [NSMutableString string];
[string appendString:@"{\n"];
NSUInteger count = self.allKeys.count;
for (id key in self.allKeys) {
NSInteger index = [self.allKeys indexOfObject:key];
id value = [self objectForKey:key];
NSString * temp = nil;
if ([value respondsToSelector:@selector(descriptionWithLocale:)]) {
temp = [value performSelector:@selector(descriptionWithLocale:) withObject:locale];
temp = [temp stringByReplacingOccurrencesOfString:@"\n" withString:@"\n\t"];
} else {
temp = [value performSelector:@selector(description) withObject:nil];
if ([value isKindOfClass:[NSString class]]) {
temp = [NSString stringWithFormat:@"\"%@\"", temp];
}
}
[string appendFormat:@"\t%@ = %@", key, temp];
if (index+1 != count) {
[string appendString:@";"];
}
[string appendString:@"\n"];
}
[string appendString:@"}"];
return string;
}
#endif
@end
//
// NSArray+GM.h
// Gengmei
//
// Created by wangyang on 2018/4/9.
// Copyright © 2018年 更美互动信息科技有限公司. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSArray (GM)
// 循环对比数组中的元素,遇到第一个符合条件的就删除,并停止遍历
- (NSArray *)arrayFromDeleteCondition:(BOOL (^)(id object))compare;
- (NSArray *)mapObjectsUsingBlock:(id (^)(id obj, NSUInteger idx))block;
@end
@interface NSMutableArray (GM)
// 循环对比数组中的元素,遇到第一个符合条件的就删除,并停止遍历
- (void)deleteCondition:(BOOL (^)(id object))compare;
@end
//
// NSArray+GM.m
// Gengmei
//
// Created by wangyang on 2018/4/9.
// Copyright © 2018年 更美互动信息科技有限公司. All rights reserved.
//
#import "NSArray+GM.h"
@implementation NSArray (GM)
- (NSArray *)arrayFromDeleteCondition:(BOOL (^)(id object))compare {
NSMutableArray *array;
if ([self isMemberOfClass:[NSMutableArray class]]) {
array = (NSMutableArray *)self;
} else {
array = [self mutableCopy];
}
NSInteger deleteIndex = -1;
for (int i = 0; i < array.count; i++) {
if (compare(array[i])) {
deleteIndex = i;
break;
}
}
if (deleteIndex != -1) {
[array removeObjectAtIndex:deleteIndex];
}
return array;
}
// 对于不想添加到结果中的情况,就返回 nil
- (NSArray *)mapObjectsUsingBlock:(id (^)(id obj, NSUInteger idx))block {
NSMutableArray *result = [NSMutableArray array];
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
id value = block(obj, idx);
if (value) {
[result addObject:value];
}
}];
return result;
}
@end
@implementation NSMutableArray (GM)
- (void)deleteCondition:(BOOL (^)(id object))compare {
NSInteger deleteIndex = -1;
for (int i = 0; i < self.count; i++) {
if (compare(self[i])) {
deleteIndex = i;
break;
}
}
if (deleteIndex != -1) {
[self removeObjectAtIndex:deleteIndex];
}
}
@end
//
// NSDate+Category.h
// FoJiao
//
// Created by yh on 15/8/31.
// Copyright (c) 2015年 ZSC. All rights reserved.
//
#import <Foundation/Foundation.h>
#define D_MINUTE 60
#define D_HOUR 3600
#define D_DAY 86400
#define D_WEEK 604800
#define D_YEAR 31556926
@interface NSDate (Category)
- (NSString *)timeIntervalDescription;//距离当前的时间间隔描述
- (NSString *)minuteDescription;/*精确到分钟的日期描述*/
- (NSString *)formattedTime;
- (NSString *)formattedDateDescription;//格式化日期描述
- (double)timeIntervalSince1970InMilliSecond;
+ (NSDate *)dateWithTimeIntervalInMilliSecondSince1970:(double)timeIntervalInMilliSecond;
+ (NSString *)dateStringWithTimeIntervalInMilliSecondSince1970:(double)timeIntervalInMilliSecond;
+ (NSString *)dateStringWithTimeIntervalInMilliSecondSince1970:(double)timeIntervalInMilliSecond format:(NSString *)format;
+ (NSString *)formattedTimeFromTimeInterval:(long long)time;
// Relative dates from the current date
+ (NSDate *) dateTomorrow;
+ (NSDate *) dateYesterday;
+ (NSDate *) dateWithDaysFromNow: (NSInteger) days;
+ (NSDate *) dateWithDaysBeforeNow: (NSInteger) days;
+ (NSDate *) dateWithHoursFromNow: (NSInteger) dHours;
+ (NSDate *) dateWithHoursBeforeNow: (NSInteger) dHours;
+ (NSDate *) dateWithMinutesFromNow: (NSInteger) dMinutes;
+ (NSDate *) dateWithMinutesBeforeNow: (NSInteger) dMinutes;
// Comparing dates
//- (BOOL) isEqualToDateIgnoringTime: (NSDate *) aDate;
- (BOOL) isToday;
- (BOOL) isTomorrow;
- (BOOL) isYesterday;
- (BOOL) isSameWeekAsDate: (NSDate *) aDate;
- (BOOL) isThisWeek;
- (BOOL) isNextWeek;
- (BOOL) isLastWeek;
- (BOOL) isSameMonthAsDate: (NSDate *) aDate;
- (BOOL) isThisMonth;
- (BOOL) isSameYearAsDate: (NSDate *) aDate;
- (BOOL) isThisYear;
- (BOOL) isNextYear;
- (BOOL) isLastYear;
- (BOOL) isEarlierThanDate: (NSDate *) aDate;
- (BOOL) isLaterThanDate: (NSDate *) aDate;
- (BOOL) isInFuture;
- (BOOL) isInPast;
// Date roles
- (BOOL) isTypicallyWorkday;
- (BOOL) isTypicallyWeekend;
// Adjusting dates
- (NSDate *) dateByAddingDays: (NSInteger) dDays;
- (NSDate *) dateBySubtractingDays: (NSInteger) dDays;
- (NSDate *) dateByAddingHours: (NSInteger) dHours;
- (NSDate *) dateBySubtractingHours: (NSInteger) dHours;
- (NSDate *) dateByAddingMinutes: (NSInteger) dMinutes;
- (NSDate *) dateBySubtractingMinutes: (NSInteger) dMinutes;
- (NSDate *) dateAtStartOfDay;
// Retrieving intervals
- (NSInteger) minutesAfterDate: (NSDate *) aDate;
- (NSInteger) minutesBeforeDate: (NSDate *) aDate;
- (NSInteger) hoursAfterDate: (NSDate *) aDate;
- (NSInteger) hoursBeforeDate: (NSDate *) aDate;
- (NSInteger) daysAfterDate: (NSDate *) aDate;
- (NSInteger) daysBeforeDate: (NSDate *) aDate;
- (NSInteger)distanceInDaysToDate:(NSDate *)anotherDate;
// Decomposing dates
@property (readonly) NSInteger nearestHour;
@property (readonly) NSInteger hour;
@property (readonly) NSInteger minute;
@property (readonly) NSInteger seconds;
@property (readonly) NSInteger day;
@property (readonly) NSInteger month;
@property (readonly) NSInteger week;
@property (readonly) NSInteger weekday;
@property (readonly) NSInteger nthWeekday; // e.g. 2nd Tuesday of the month == 2
@property (readonly) NSInteger year;
@end
/************************************************************
* * EaseMob CONFIDENTIAL
* __________________
* Copyright (C) 2013-2014 EaseMob Technologies. All rights reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of EaseMob Technologies.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from EaseMob Technologies.
*/
#import <Foundation/Foundation.h>
@interface NSDateFormatter (Category)
+ (id)dateFormatter;
+ (id)dateFormatterWithFormat:(NSString *)dateFormat;
+ (id)defaultDateFormatter;/*yyyy-MM-dd HH:mm:ss*/
@end
/************************************************************
* * EaseMob CONFIDENTIAL
* __________________
* Copyright (C) 2013-2014 EaseMob Technologies. All rights reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of EaseMob Technologies.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from EaseMob Technologies.
*/
#import "NSDateFormatter+Category.h"
@implementation NSDateFormatter (Category)
+ (id)dateFormatter
{
return [[self alloc] init];
}
+ (id)dateFormatterWithFormat:(NSString *)dateFormat
{
NSDateFormatter *dateFormatter = [[self alloc] init];
dateFormatter.dateFormat = dateFormat;
return dateFormatter;
}
+ (id)defaultDateFormatter
{
return [self dateFormatterWithFormat:@"yyyy-MM-dd HH:mm:ss"];
}
@end
//
// NSDictionary+GM.h
// Gengmei
//
// Created by Mikasa on 2019/8/8.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
NS_ASSUME_NONNULL_BEGIN
@interface NSDictionary (GM)
- (BOOL)dictContainsKey:(NSString *)key;
@end
NS_ASSUME_NONNULL_END
//
// NSDictionary+GM.m
// Gengmei
//
// Created by Mikasa on 2019/8/8.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#import "NSDictionary+GM.h"
@implementation NSDictionary (GM)
- (BOOL)dictContainsKey:(NSString *)key {
if ([self.allKeys containsObject:key]) {
return YES;
}
return NO;
}
@end
//
// NSDictionary+json.h
// Gengmei
//
// Created by Q14 on 2019/5/8.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSDictionary (json)
/**
* JSON字符串转NSDictionary
*
* @param jsonString JSON字符串
*
* @return NSDictionary
*/
+ (NSDictionary *)dictionaryWithJsonString:(NSString *)jsonString;
/**
* 字典转JSON字符串
*
* @param dic 字典
*
* @return JSON字符串
*/
+ (NSString *)dictionaryToJson:(NSDictionary *)dic;
@end
NS_ASSUME_NONNULL_END
//
// NSDictionary+json.m
// Gengmei
//
// Created by Q14 on 2019/5/8.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#import "NSDictionary+json.h"
@implementation NSDictionary (json)
/**
* JSON字符串转NSDictionary
*
* @param jsonString JSON字符串
*
* @return NSDictionary
*/
+ (NSDictionary *)dictionaryWithJsonString:(NSString *)jsonString {
if (jsonString == nil) {
return nil;
}
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
if(error) {
NSLog(@"json解析失败:%@",error);
return nil;
}
return dic;
}
/**
* 字典转JSON字符串
*
* @param dic 字典
*
* @return JSON字符串
*/
+ (NSString *)dictionaryToJson:(NSDictionary *)dic {
NSError *parseError = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:&parseError];
return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
@end
//
// NSJSONSerialization+GM.swift
// Gengmei
//
// Created by licong on 16/8/25.
// Copyright © 2016年 更美互动信息科技有限公司. All rights reserved.
//
import Foundation
@objc public extension JSONSerialization {
class func JSONString(_ object: AnyObject) -> String? {
guard let data = try? JSONSerialization.data(withJSONObject: object, options: .prettyPrinted),
let string = String(data: data, encoding: String.Encoding.utf8) else { return nil }
return string
}
}
//
// NSMutableAttributedString+Attachment.h
// Gengmei
//
// Created by wangyang on 2018/8/7.
// Copyright © 2018年 更美互动信息科技有限公司. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSMutableAttributedString (Attachment)
/**
需求:http://wiki.wanmeizhensuo.com/pages/viewpage.action?pageId=9767058#space-menu-link-content
一些卡片标题有置顶标识。
*/
- (void)addFeedIsTopAttachment;
/**
http://wiki.wanmeizhensuo.com/pages/viewpage.action?pageId=11609153
*/
- (void)addDiaryMatchAttachment;
/**
标题前方添加标识(默认为拼团)
*/
- (NSAttributedString *)addGroupBuyIsFrontAttachment:(NSString *)iconName;
- (NSAttributedString *)addGroupBuyIsFrontAttachment:(NSString *)iconName attachmentBounds:(CGRect)attachmentBounds;
@end
//
// NSMutableAttributedString+Attachment.m
// Gengmei
//
// Created by wangyang on 2018/8/7.
// Copyright © 2018年 更美互动信息科技有限公司. All rights reserved.
//
#import "NSMutableAttributedString+Attachment.h"
#import "NSString+GM.h"
@implementation NSMutableAttributedString (Attachment)
- (void)addFeedIsTopAttachment {
NSTextAttachment* textAttachment = [[NSTextAttachment alloc] init];
textAttachment.image = [UIImage imageNamed:@"feed_is_top"];
textAttachment.bounds = CGRectMake(0, -1, 13, 13); // 微调图片位置
NSAttributedString *imageAttachment = [NSAttributedString attributedStringWithAttachment:textAttachment];
// 给最后一个字符尾部添加字符水平间距,以符合设计要求:箭头与文字的间距为8个点
[self addAttribute:NSKernAttributeName value:@(8) range:NSMakeRange(self.string.length - 1, 1)];
[self insertAttributedString:imageAttachment atIndex:self.string.length];
}
- (void)addDiaryMatchAttachment {
NSTextAttachment* textAttachment = [[NSTextAttachment alloc] init];
textAttachment.image = [UIImage imageNamed:@"diary_match"];//diary_match//feed_is_top
textAttachment.bounds = CGRectMake(0, -2, 31, 16); // 微调图片位置
NSAttributedString *imageAttachment = [NSAttributedString attributedStringWithAttachment:textAttachment];
// 给最后一个字符尾部添加字符水平间距,以符合设计要求:箭头与文字的间距为8个点
[self addAttribute:NSKernAttributeName value:@(8) range:NSMakeRange(self.string.length - 1, 1)];
[self insertAttributedString:imageAttachment atIndex:self.string.length];
}
- (NSAttributedString *)addGroupBuyIsFrontAttachment:(NSString *)iconName {
[self addGroupBuyIsFrontAttachment:iconName attachmentBounds:CGRectMake(0, -1, 25, 13)];
// [self addAttribute:NSKernAttributeName value:@(20) range:NSMakeRange(0, 1)];
return self;
}
- (NSAttributedString *)addGroupBuyIsFrontAttachment:(NSString *)iconName attachmentBounds:(CGRect)attachmentBounds {
NSMutableAttributedString *textAttrStr = [[NSMutableAttributedString alloc] init];
NSTextAttachment* textAttachment = [[NSTextAttachment alloc] init];
textAttachment.image = [UIImage imageNamed:iconName.isNonEmpty ? iconName : @"groupBuy_icon"];
textAttachment.bounds = CGRectMake(attachmentBounds.origin.x, attachmentBounds.origin.y, attachmentBounds.size.width, attachmentBounds.size.height); // 微调图片位置
NSAttributedString *imageAttachment = [NSAttributedString attributedStringWithAttachment:textAttachment];
[textAttrStr appendAttributedString:imageAttachment];
//标签后添加空格
[textAttrStr appendAttributedString:[[NSAttributedString alloc] initWithString:@" "]];
// 给最后一个字符尾部添加字符水平间距,以符合设计要求:箭头与文字的间距为8个点
[self insertAttributedString:textAttrStr atIndex:0];
return self;
}
@end
//
// NSObject+GMDate.h
// Gengmei
//
// Created by lizhen on 2019/2/15.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#include <mach/mach_time.h>
@interface NSObject (GMDate)
/** NSDate->时间戳 */
- (CGFloat)getDateTime:(NSDate *)Date;
/** NSDate->时间字符串 */
- (NSString *)getDateToString:(NSDate *)Date;
/** 时间戳->字符串 */
- (NSString *)getDateStringWithTimeStr:(float)time;
/** 字符串时间—>时间戳 */
- (CGFloat)timeStringToTimeFloat:(NSString *)time;
/** 计算两个 NSDate 相差天数 */
- (NSString *)getTimeFrom:(NSDate *)fromDate to:(NSDate *)toDate;
/** 字符串->日期 */
- (NSDate *)getDateWithString:(NSString *)str;
/** 时间戳->NSDate */
- (NSDate *)getDateWithFloat:(float)time;
uint64_t GetPIDTimeInNanoseconds(uint64_t start,uint64_t end);
@end
//
// NSObject+GMDate.m
// Gengmei
//
// Created by lizhen on 2019/2/15.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#import "NSObject+GMDate.h"
#include <assert.h>
#include <CoreServices/CoreServices.h>
#include <mach/mach.h>
#include <unistd.h>
@implementation NSObject (GMDate)
#pragma mark - NSDate转化为时间戳
- (CGFloat)getDateTime:(NSDate *)Date {
//获取选择的时间戳
NSDate *date = [Date dateByAddingTimeInterval:0];
NSTimeInterval time = [date timeIntervalSince1970];// *1000 是精确到毫秒,不乘就是精确到秒
return time;
}
#pragma mark - NSDate->时间字符串
- (NSString *)getDateToString:(NSDate *)Date {
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
// 设定时间格式,这里可以设置成自己需要的格式
[formatter setDateFormat:@"yyyy/MM/dd"];
NSString *time = [formatter stringFromDate:Date];
return time;
}
#pragma mark - 时间戳转字符串
- (NSString *)getDateStringWithTimeStr:(float)time {
// 时间戳转时间,时间戳为13位是精确到毫秒的,10位精确到秒
NSDate *detailDate = [NSDate dateWithTimeIntervalSince1970:time];
NSString *currentDateStr = [self getDateToString:detailDate];
return currentDateStr;
}
#pragma mark - 字符串时间—>时间戳
- (CGFloat)timeStringToTimeFloat:(NSString *)time {
// 转换为时间戳
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy/MM/dd"];
NSDate *date = [formatter dateFromString:time];
return [self getDateTime:date];
}
#pragma mark - 计算两个 NSDate 相差天数
- (NSString *)getTimeFrom:(NSDate *)fromDate to:(NSDate *)toDate {
//计算两个中间差值(秒)
NSTimeInterval time = [toDate timeIntervalSinceDate:fromDate];
//开始时间和结束时间的中间相差的时间
int days;
days = ((int)time)/(3600*24); //一天是24小时*3600秒
NSString *dateValue = [NSString stringWithFormat:@"%i",days];
return dateValue;
}
#pragma mark - 字符串转日期
- (NSDate *)getDateWithString:(NSString *)str {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = @"yyyy/MM/dd";
[dateFormatter setMonthSymbols:[NSArray arrayWithObjects:@"01",@"02",@"03",@"04",@"05",@"06",@"07",@"08",@"09",@"10",@"11",@"12", nil]];
NSDate * ValueDate = [dateFormatter dateFromString:str];
return ValueDate;
}
#pragma mark - 时间戳->NSDate
- (NSDate *)getDateWithFloat:(float)time {
if (time <= 0) {
return nil;
}
NSString *timeStr = [self getDateStringWithTimeStr:time];
NSDate *date = [self getDateWithString:timeStr];
return date;
}
uint64_t GetPIDTimeInNanoseconds(uint64_t start,uint64_t end)
{
uint64_t elapsed;
uint64_t elapsedNano;
static mach_timebase_info_data_t sTimebaseInfo;
// Start the clock.
// start = mach_absolute_time();
// Call getpid. This will produce inaccurate results because
// we're only making a single system call. For more accurate
// results you should call getpid multiple times and average
// the results.
(void) getpid();
// Stop the clock.
// end = mach_absolute_time();
// Calculate the duration.
elapsed = end - start;
// Convert to nanoseconds.
// If this is the first time we've run, get the timebase.
// We can use denom == 0 to indicate that sTimebaseInfo is
// uninitialised because it makes no sense to have a zero
// denominator is a fraction.
if ( sTimebaseInfo.denom == 0 ) {
(void) mach_timebase_info(&sTimebaseInfo);
}
// Do the maths. We hope that the multiplication doesn't
// overflow; the price you pay for working in fixed point.
elapsedNano = elapsed * sTimebaseInfo.numer / sTimebaseInfo.denom;
return elapsedNano/1000000;
}
@end
//
// NSString+Base64.h
// GMAlpha
//
// Created by ioszhb on 2019/1/18.
// Copyright © 2019 Gengmei. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSString (Base64)
- (NSString *)encodeString:(NSString *)string;
- (NSString *)decodeString:(NSString *)string;
//base64编码
- (NSString *)str_base64Encode;
//base64解码
- (NSString *)str_base64Decode;
@end
NS_ASSUME_NONNULL_END
//
// NSString+Base64.m
// GMAlpha
//
// Created by ioszhb on 2019/1/18.
// Copyright © 2019 Gengmei. All rights reserved.
//
#import "NSString+Base64.h"
@implementation NSString (Base64)
//base64编码
- (NSString *)encodeString:(NSString *)string
{
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
NSString *encodedStr = [data base64EncodedStringWithOptions:0];
return encodedStr;
}
//base64解码
- (NSString *)decodeString:(NSString *)string
{
NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:0];
NSString *decodedStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return decodedStr;
}
//base64编码
- (NSString *)str_base64Encode
{
NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
NSString *encodedStr = [data base64EncodedStringWithOptions:0];
return encodedStr;
}
//base64解码
- (NSString *)str_base64Decode
{
NSData *data = [[NSData alloc] initWithBase64EncodedString:self options:0];
NSString *decodedStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return decodedStr;
}
@end
//
// NSString+IconFont.h
// Gengmei
//
// Created by lizhen on 2018/5/25.
// Copyright © 2018年 更美互动信息科技有限公司. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSString (IconFont)
/**
替换字符串中指定字体为iconfont
@param oldString 要替换的字符串
@param newString 替换后的字符串
@param font 文字字体
@param textColor 文字颜色
@param lineSpace 行间距
*/
- (NSMutableAttributedString *)replaceString:(NSArray<NSString *> *)oldArray
withStrings:(NSArray<NSString *> *)newArray
font:(UIFont *)font
textColor:(UIColor *)textColor
lineSpace:(NSInteger)lineSpace;
@end
@interface NSString (IconFontFactory)
// 美购详情页中使用
- (NSMutableAttributedString *)welfareDetailNameWithFontSize:(NSInteger)size
textColor:(UIColor *)textColor;
// 其它各处的美购标题使用
- (NSMutableAttributedString *)welfareNameWithFontSize:(NSInteger)size
textColor:(UIColor *)textColor
lineSpace:(NSInteger)lineSpace;
- (NSMutableAttributedString *)customDetailNameWithFontSize:(UIFont *)font
textColor:(UIColor *)textColor
lineSpace:(NSInteger)lineSpace;
@end
//
// NSString+IconFont.m
// Gengmei
//
// Created by lizhen on 2018/5/25.
// Copyright © 2018年 更美互动信息科技有限公司. All rights reserved.
//
#import "NSString+IconFont.h"
#import "NSAttributedString+GMSize.h"
#define RGBFCOLOR_HEX(hexColor) [UIColor colorWithRed: (((hexColor >> 16) & 0xFF))/255.0f \
green: (((hexColor >> 8) & 0xFF))/255.0f \
blue: ((hexColor & 0xFF))/255.0f \
alpha: 1]
@implementation NSString (IconFont)
- (NSMutableAttributedString *)replaceString:(NSArray<NSString *> *)oldArray
withStrings:(NSArray<NSString *> *)newArray
font:(UIFont *)font
textColor:(UIColor *)textColor
lineSpace:(NSInteger)lineSpace {
NSString *contentString = [self copy];
NSMutableArray *rangeArray = [NSMutableArray array];
for (NSInteger i = 0; i < oldArray.count; i++) {
NSInteger number = [[self mutableCopy] replaceOccurrencesOfString:oldArray[i] withString:newArray[i] options:NSCaseInsensitiveSearch range:NSMakeRange(0, self.length)];
NSRange range = NSMakeRange(0, 0);
for (NSInteger j = 0; j < number; j++) {
if ([contentString containsString:oldArray[i]]) {
//记录range,为替换成icomoon
range = [contentString rangeOfString:oldArray[i]];
contentString = [contentString stringByReplacingOccurrencesOfString:oldArray[i] withString:newArray[i] options:NSCaseInsensitiveSearch range:range];
NSValue *value = [NSValue valueWithRange:range];
[rangeArray addObject:value];
}
}
}
NSDictionary *attributeDic = @{NSForegroundColorAttributeName: textColor, NSFontAttributeName: font};
NSMutableAttributedString *content = [[NSMutableAttributedString alloc] initWithString:contentString attributes:attributeDic];
for (NSInteger k = 0; k < rangeArray.count; k++) {
//通过range遍历, 替换为icomoon
[content setAttributes:@{NSFontAttributeName : [UIFont fontWithName:@"icomoon" size:font.pointSize]} range:[rangeArray[k] rangeValue]];
}
[content addLineSpace:lineSpace];
return content;
}
@end
// BRACKETS 即 brackets,中括号的意思
#define CHINESE_BRACKETS @[@"【", @"】"]
#define ICON_FONT_BRACKETS @[@"\U0000e901", @"\U0000e902"]
@implementation NSString (IconFontFactory)
- (NSMutableAttributedString *)welfareDetailNameWithFontSize:(NSInteger)size
textColor:(UIColor *)textColor {
NSMutableAttributedString *content = [self replaceString:CHINESE_BRACKETS
withStrings:ICON_FONT_BRACKETS
font:[UIFont fontWithName:@"PingFangSC-Medium" size:size]
textColor:textColor ?: RGBFCOLOR_HEX(0x282828)
lineSpace:0];
return content;
}
- (NSMutableAttributedString *)welfareNameWithFontSize:(NSInteger)size
textColor:(UIColor *)textColor
lineSpace:(NSInteger)lineSpace {
NSMutableAttributedString *content = [self replaceString:CHINESE_BRACKETS withStrings:ICON_FONT_BRACKETS font:[UIFont fontWithName:@"PingFangSC-Regular" size:size] textColor:textColor ?: RGBFCOLOR_HEX(0x282828) lineSpace:lineSpace];
return content;
}
- (NSMutableAttributedString *)customDetailNameWithFontSize:(UIFont *)font
textColor:(UIColor *)textColor
lineSpace:(NSInteger)lineSpace {
NSMutableAttributedString *content = [self replaceString:CHINESE_BRACKETS withStrings:ICON_FONT_BRACKETS font:font textColor:textColor ?: RGBFCOLOR_HEX(0x282828) lineSpace:lineSpace];
return content;
}
@end
//
// NSString+RegularString.h
// Gengmei
//
// Created by 汪俊 on 2018/2/1.
// Copyright © 2018年 更美互动信息科技有限公司. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSString (RegularString)
- (NSString *)regularPattern:(NSArray *)keys;
/** 数量转换 */
- (NSString *)numberToString;
/** 转换
<1w,显示具体数字
>=1w,显示1w+
以每一w为单位递增2w+、3w+、4w+
*/
- (NSString *)numberToWString;
/** 转换
<=99,显示具体数字
>99,显示99+
*/
- (NSString *)numberTo99String;
@end
//
// NSString+RegularString.m
// Gengmei
//
// Created by 汪俊 on 2018/2/1.
// Copyright © 2018年 更美互动信息科技有限公司. All rights reserved.
//
#import "NSString+RegularString.h"
@implementation NSString (RegularString)
/**
关键字 正则判断
*/
- (NSString *)regularPattern:(NSArray *)keys{
NSMutableString *pattern = [[NSMutableString alloc]initWithString:@"(?i)"];
for (NSString *key in keys) {
[pattern appendFormat:@"%@|",key];
}
return pattern;
}
- (NSString *)numberToString {
NSInteger num = self.integerValue;
if (num > 0 && num < 10000) {
return self;
} else if (num >= 10000) {
return [NSString stringWithFormat:@"%ld.%.0f万", num / 10000, ceilf(num % 10000 / 1000.0)];
} else {
return @"0";
}
}
- (NSString *)numberToWString {
NSInteger num = self.integerValue;
if (num > 0 && num < 10000) {
return self;
} else if (num >= 10000) {
return [NSString stringWithFormat:@"%ldw+", num / 10000];
} else {
return @"";
}
}
- (NSString *)numberTo99String {
NSInteger num = self.integerValue;
if (num > 0 && num < 100) {
return self;
} else if (num > 99) {
return [NSString stringWithFormat:@"99+"];
} else {
return @"";
}
}
@end
//
// String+GM.swift
// Gengmei
//
// Created by wangyang on 2017/12/21.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
import Foundation
// MARK: - 字符串截取
extension String {
// 截取字符串从开始到index
func substring(to index: Int) -> String {
guard let end_Index = validEndIndex(original: index) else {
return self
}
return String(self[startIndex..<end_Index])
}
// 截取字符串从index到结束
func substring(from index: Int) -> String {
guard let start_index = validStartIndex(original: index) else {
return self
}
return String(self[start_index..<endIndex])
}
// 切割字符串(区间范围 前闭后开)
func sliceString(_ range: CountableRange<Int>) -> String {
guard
let startIndex = validStartIndex(original: range.lowerBound),
let endIndex = validEndIndex(original: range.upperBound),
startIndex <= endIndex
else {
return ""
}
return String(self[startIndex..<endIndex])
}
// 切割字符串(区间范围 前闭后闭)
func sliceString(_ range: CountableClosedRange<Int>) -> String {
guard
let start_Index = validStartIndex(original: range.lowerBound),
let end_Index = validEndIndex(original: range.upperBound),
startIndex <= endIndex
else {
return ""
}
if endIndex.encodedOffset <= end_Index.encodedOffset {
return String(self[start_Index..<endIndex])
}
return String(self[start_Index...end_Index])
}
// 校验字符串位置 是否合理,并返回String.Index
func validIndex(original: Int) -> String.Index {
switch original {
case ...startIndex.encodedOffset : return startIndex
case endIndex.encodedOffset... : return endIndex
default : return index(startIndex, offsetBy: original)
}
}
// 校验是否是合法的起始位置
func validStartIndex(original: Int) -> String.Index? {
guard original <= endIndex.encodedOffset else { return nil }
return validIndex(original: original)
}
// 校验是否是合法的结束位置
func validEndIndex(original: Int) -> String.Index? {
guard original >= startIndex.encodedOffset else { return nil }
return validIndex(original: original)
}
}
//
// 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
//
// 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
//
// 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
//
// 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;
UIBezierPath *path = [UIBezierPath bezierPathWithRect:shadowFrame];
self.layer.shadowPath = path.CGPath;
}
@end
//
// GMTableViewCell+Layout.h
// Gengmei
//
// Created by wangyang on 2017/7/19.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
#define EDGE 20.0
#define CONTENT_WIDTH [GMTableViewCell contentWidth]
#define MARGIN_TOP 15
#define MARGIN_BOTTOM 20.5
#define TITLE_LINESPACING 0 // title/content行间距
#define MARGIN_TITLE_VIDEO 15 // title与视频(一张大图)间距
#define MARGIN_CONTENT_VIDEO 16 // content与视频(一张大图)间距
#define MARGIN_TITLE_CONTENT 4
#define MARGIN_USERINFO_CONTENT 12 // userInfoView与content间距/userInfoView与title间距
#define MARGIN_USERINFO_IMAGE 16 // userInfoView与图片间距
#define IMAGE_TOP 20
#define IMAGE_WIDTH 155
#define TITLE_SIZE 18
#define CONTENT_SIZE 14
#define TITLE_MAXHEIGHT 76
#define CONTENT_MAXHEIGHT 40
#define TITLE_RIGHT_IMAGE 12
#import "GMTableViewCell.h"
@interface GMTableViewCell (Layout)
+ (CGSize)cellImageSize;
+ (CGFloat)contentWidth;
- (void)useEdgeBottomLine;
@end
//
// GMTableViewCell+Layout.m
// Gengmei
//
// Created by wangyang on 2017/7/19.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
#import "GMTableViewCell+Layout.h"
#import <Masonry/Masonry.h>
#define IMAGE_COUNT 3
#define IMAGE_SPACE 10
@implementation GMTableViewCell (Layout)
+ (CGSize)cellImageSize {
CGFloat imageWidth = ceil(([self contentWidth] - (IMAGE_COUNT - 1 ) * IMAGE_SPACE) / IMAGE_COUNT);
CGFloat imageHeight = imageWidth;
return CGSizeMake(imageWidth, imageHeight);
}
+ (CGFloat)contentWidth {
return UIScreen.mainScreen.bounds.size.width - EDGE * 2;
}
- (void)useEdgeBottomLine {
[self.bottomLine mas_updateConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(20);
make.right.mas_equalTo(-20);
}];
[self.contentView bringSubviewToFront:self.bottomLine];
}
@end
//
// NSObject+EasySubClass.h
// Gengmei
//
// Created by wangyang on 2019/9/5.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/**
利用运行时创建 subclass,以方便调试 UI 时区分基础的 UIView,UILabel 等基础视图
*/
@interface NSObject (EasySubClass)
+ (instancetype)initWithSubclassName:(NSString *)clsName;
@end
NS_ASSUME_NONNULL_END
//
// NSObject+EasySubClass.m
// Gengmei
//
// Created by wangyang on 2019/9/5.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#import "NSObject+EasySubClass.h"
#import <objc/runtime.h>
@implementation NSObject (EasySubClass)
+ (instancetype)initWithSubclassName:(NSString *)clsName {
const char *subclassName = clsName.UTF8String;
Class subclass = objc_getClass(subclassName);
if (subclass == nil) {
subclass = objc_allocateClassPair(self, subclassName, 0);
if (subclass == nil) {
return [self new];
}
objc_registerClassPair(subclass);
}
return [subclass new];
}
@end
//
// UIAlertController+GM.swift
// GMKit
//
// Created by wangyang on 16/7/7.
// Copyright © 2016年 licong. All rights reserved.
//
import Foundation
// 因为
@objc public extension UIAlertController {
@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)
}
@objc static func showCustomAlert(withTitle title: String?, message: String?) -> UIAlertController {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
UIApplication.shared.keyWindow?.rootViewController?.present(alert, animated: true, completion: nil)
return alert
}
@objc static func showCustomActionSheet(withTitle title: String?, message: String?) -> UIAlertController {
let alert = UIAlertController(title: title, message: message, preferredStyle: .actionSheet)
UIApplication.shared.keyWindow?.rootViewController?.present(alert, animated: true, completion: nil)
return alert
}
@objc func addAction(_ title: String, actionHandler:(() -> Void)?) {
let action = UIAlertAction(title: title, style: .default) { (_) in
actionHandler?()
}
addAction(action)
}
@objc static func alert(_ title: String, leftTitle: String?, rightTitle: String?, leftAlterAction: (() -> Void)?, rightAlertAction: (() -> Void)?) -> UIAlertController {
let alertController = UIAlertController(title: title, message: "", preferredStyle: UIAlertController.Style.alert)
var leftAction: UIAlertAction
var rightAction: UIAlertAction
if let leftTitle = leftTitle {
leftAction = UIAlertAction(title: leftTitle, style: UIAlertAction.Style.default) { (_) -> Void in
if let action = leftAlterAction { action() }
}
alertController.addAction(leftAction)
}
if let rightTitle = rightTitle {
rightAction = UIAlertAction(title: rightTitle, style: UIAlertAction.Style.default) { (_) -> Void in
if let action = rightAlertAction { action() }
}
alertController.addAction(rightAction)
}
return alertController
}
}
//
// UIImage+Extension.swift
// Gengmei
//
// Created by 汪俊 on 2017/2/15.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
import Foundation
@objc public extension UIImage {
/// 转为和屏幕scale一致的image
func screenScaleImage() -> UIImage? {
guard let imageData = self.pngData() else { return nil }
guard let scaleImage = UIImage(data: imageData, scale: UIScreen.main.scale) else { return nil }
return scaleImage
}
}
//
// UIImage+GIFImages.h
// Gengmei
//
// Created by wangyang on 2017/11/2.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface GMGIF: NSObject
@property (nonatomic, copy, readonly) NSArray<UIImage *> *images;
@property (nonatomic, assign, readonly) NSTimeInterval duration;
- (nullable instancetype)initWithName:(NSString *)name;
@end
NS_ASSUME_NONNULL_END
//
// UIImage+GIFImages.m
// Gengmei
//
// Created by wangyang on 2017/11/2.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
#import "UIImage+GIFImages.h"
@interface GMGIF ()
@property (nonatomic, copy) NSArray<UIImage *> *images;
@property (nonatomic, assign) NSTimeInterval duration;
@end
@implementation GMGIF
- (instancetype)initWithName:(NSString *)name {
self = [super init];
NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"];
NSData *data = [NSData dataWithContentsOfFile:path];
if (!data) {
return nil;
}
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
size_t count = CGImageSourceGetCount(source);
NSMutableArray *images = [NSMutableArray array];
NSTimeInterval duration = 0.0f;
for (size_t i = 0; i < count; i++) {
CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);
if (!image) {
continue;
}
duration += [GMGIF sd_frameDurationAtIndex:i source:source];
[images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]];
CGImageRelease(image);
}
if (!duration) {
duration = (1.0f / 10.0f) * count;
}
CFRelease(source);
if (images.count == 0) {
NSLog(@"gif中没有图片");
return nil;
}
self.images = images;
self.duration = duration;
return self;
}
+ (float)sd_frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source {
float frameDuration = 0.1f;
CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil);
NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties;
NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary];
NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime];
if (delayTimeUnclampedProp) {
frameDuration = [delayTimeUnclampedProp floatValue];
}
else {
NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime];
if (delayTimeProp) {
frameDuration = [delayTimeProp floatValue];
}
}
// Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
// We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
// a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>
// for more information.
if (frameDuration < 0.011f) {
frameDuration = 0.100f;
}
CFRelease(cfFrameProperties);
return frameDuration;
}
@end
//
// UIImage+GMloadImage.h
// Gengmei
//
// Created by 刘鹿杰的mac on 2019/5/6.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIImage (GMloadImage)
// 下载图片
+ (UIImage *)loadOriginalImageWithString:(id )string;
@end
NS_ASSUME_NONNULL_END
//
// UIImage+GMloadImage.m
// Gengmei
//
// Created by 刘鹿杰的mac on 2019/5/6.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#import "UIImage+GMloadImage.h"
@implementation UIImage (GMloadImage)
+ (UIImage *)loadOriginalImageWithString:(id )string{
UIImage* image = nil;
if ([string isKindOfClass:[UIImage class]]){
image = (UIImage *)string;
} else if ([string isKindOfClass:[NSString class]]) {
NSString *url = (NSString *)string;
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:1.5];
NSURLResponse *response = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
image = [UIImage imageWithData: data];
//如果远程的图片下载不下来,则使用默认图
if (image == nil) {
image = [UIImage imageNamed:@"icon"];
}
}
return image;
}
@end
/*
File: UIImage+ImageEffects.h
Abstract: This is a category of UIImage that adds methods to apply blur and tint effects to an image. This is the code you’ll want to look out to find out how to use vImage to efficiently calculate a blur.
Version: 1.0
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2013 Apple Inc. All Rights Reserved.
Copyright © 2013 Apple Inc. All rights reserved.
WWDC 2013 License
NOTE: This Apple Software was supplied by Apple as part of a WWDC 2013
Session. Please refer to the applicable WWDC 2013 Session for further
information.
IMPORTANT: This Apple software is supplied to you by Apple Inc.
("Apple") in consideration of your agreement to the following terms, and
your use, installation, modification or redistribution of this Apple
software constitutes acceptance of these terms. If you do not agree with
these terms, please do not use, install, modify or redistribute this
Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a non-exclusive license, under
Apple's copyrights in this original Apple software (the "Apple
Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES
NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE
IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
EA1002
5/3/2013
*/
@import UIKit;
@interface UIImage (ImageEffects)
- (UIImage *)applyLightEffect;
- (UIImage *)applyLightEffect2;
- (UIImage *)applyLightEffectcolor:(float)color alf:(float)alf radiu:(float)radiu Factor:(float)Factor;
- (UIImage *)applyExtraLightEffect;
- (UIImage *)applyDarkEffect;
- (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor;
- (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage;
@end
This diff is collapsed.
//
// resize.swift
// Gengmei
//
// Created by licong on 2017/4/28.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
import UIKit
@objc public extension UIImage {
///对指定图片中心进行拉伸
static func stretchByCenter(name: String) -> UIImage {
var normal = UIImage(named: name)!
let imageWidth = normal.size.width * 0.5
let imageHeight = normal.size.height * 0.5
normal = normal.resizableImage(withCapInsets: UIEdgeInsets(top: imageHeight, left: imageWidth, bottom: imageHeight, right: imageWidth), resizingMode: .stretch)
return normal
}
}
//
// UIImage+water.h
// Gengmei
//
// Created by Q14 on 2019/7/25.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIImage (water)
+ (UIImage *)wterImageWithImage:(UIImage *)image waterImage:(UIImage *)waterImage waterImageRect:(CGRect)rect;
+ (UIImage *)waterMarkWithImage:(UIImage *)bgImage andMarkImageName:(UIImage *)waterImage;
@end
NS_ASSUME_NONNULL_END
//
// UIImage+water.m
// Gengmei
//
// Created by Q14 on 2019/7/25.
// Copyright © 2019 更美互动信息科技有限公司. All rights reserved.
//
#import "UIImage+water.h"
@implementation UIImage (water)
// 给图片添加图片水印
+ (UIImage *)wterImageWithImage:(UIImage *)image waterImage:(UIImage *)waterImage waterImageRect:(CGRect)rect {
//开启上下文
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
//绘制背景图片
[image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
//绘制水印图片到当前上下文
[waterImage drawInRect:rect];
//从上下文中获取新图片
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
//关闭图形上下文
UIGraphicsEndImageContext();
//返回图片
return newImage;
}
+ (UIImage *)waterMarkWithImage:(UIImage *)bgImage andMarkImageName:(UIImage *)waterImage {
// bgImag.size = [UIImage getScreenImageSize:bgImage];
UIGraphicsBeginImageContextWithOptions(bgImage.size, NO, 0.0);
[bgImage drawInRect:CGRectMake(0, 0, bgImage.size.width, bgImage.size.height)];
CGFloat margin = 24;
CGFloat waterW = waterImage.size.width;
CGFloat waterH = waterImage.size.height;
CGFloat scale = bgImage.size.width/UIScreen.mainScreen.bounds.size.width;
CGFloat waterX = bgImage.size.width - waterW*scale - margin*scale;
CGFloat waterY = bgImage.size.height - waterH*scale - margin*scale;
[waterImage drawInRect:CGRectMake(waterX, waterY, waterW*scale, waterH*scale)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
+ (CGSize)getScreenImageSize:(UIImage *)image {
CGFloat scale1 = image.size.height / image.size.width;
return CGSizeMake(UIScreen.mainScreen.bounds.size.width, UIScreen.mainScreen.bounds.size.width*scale1);
}
@end
//
// UITextView+LengthLimit.h
// Gengmei
//
// Created by wangyang on 2017/3/9.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
#import <UIKit/UIKit.h>
/**
UITextView 输入之字数限制. http://blog.csdn.net/fengsh998/article/details/45421107
*/
@interface UITextView (LimitBase)
@property(nonatomic, assign) NSInteger maxTextLength;
@property(nonatomic, readonly, assign) NSInteger textLength;
@end
@interface UITextView (SimpleLimit)
/**
对字数进行简单限制。该方法可以就对绝大部分需求。例如需求只限制最大长度,没有提示性交互,没有特殊字符过滤时,使用该方法即可以
在 UITextViewDelegate textViewDidChange中调用
*/
- (void)s_textViewDidChange;
@end
@interface UITextView (ComplexLimit)
/**
对字数进行复杂限制。如果需求有在输入时的交互提示,有特殊字符过滤时,需要使用下面方法。需要配合 c_textViewDidChange 同时使用
在 UITextViewDelegate textView:shouldChangeTextInRange:replacementText: 调用并返回
*/
- (BOOL)c_shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;
/**
对字数进行复杂限制。需要配合 c_shouldChangeTextInRange:replacementText 同时使用
在 UITextViewDelegate textViewDidChange中调用
*/
- (void)c_textViewDidChange;
@end
//
// UITextView+LengthLimit.m
// Gengmei
//
// Created by wangyang on 2017/3/9.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
#import "UITextView+LengthLimit.h"
#import <objc/runtime.h>
@implementation UITextView (LimitBase)
- (NSInteger)maxTextLength {
NSNumber *length = objc_getAssociatedObject(self, @selector(maxTextLength));
return length.integerValue;
}
- (void)setMaxTextLength:(NSInteger)maxTextLength {
objc_setAssociatedObject(self, @selector(maxTextLength), @(maxTextLength), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSInteger)textLength {
NSNumber *length = objc_getAssociatedObject(self, @selector(textLength));
return length.integerValue;
}
- (void)setTextLength:(NSInteger)textLength {
objc_setAssociatedObject(self, @selector(textLength), @(textLength), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
@implementation UITextView (SimpleLimit)
- (void)s_textViewDidChange {
NSString *toBeString = self.text;
UITextRange *selectedRange = [self markedTextRange];
UITextPosition *position = [self positionFromPosition:selectedRange.start offset:0];
NSInteger length = self.textLength;
// 没有高亮选择的字,则对已输入的文字进行字数统计和限制
if (!position){
if (toBeString.length > self.maxTextLength){
NSRange rangeIndex = [toBeString rangeOfComposedCharacterSequenceAtIndex:self.maxTextLength];
if (rangeIndex.length == 1){
self.text = [toBeString substringToIndex:self.maxTextLength];
} else{
NSRange rangeRange = [toBeString rangeOfComposedCharacterSequencesForRange:NSMakeRange(0, self.maxTextLength)];
self.text = [toBeString substringWithRange:rangeRange];
}
length = self.text.length;
} else {
NSString *selectedText = [self textInRange:selectedRange];
length = self.text.length - selectedText.length;
}
}
if (length > self.maxTextLength) {
self.textLength = self.maxTextLength;
} else {
self.textLength = length;
}
}
@end
@implementation UITextView (ComplexLimit)
- (BOOL)c_shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if (text.length==0) { //Delete any cases
if(range.length > 1){
//Delete whole word
}
else if(range.length == 1){
//Delete single letter
}
else if(range.length == 0){
//Tap delete key when textField empty
}
return YES;
}
UITextRange *selectedRange = [self markedTextRange];
//获取高亮部分
UITextPosition *pos = [self positionFromPosition:selectedRange.start offset:0];
//获取高亮部分内容
// NSString * selectedtext = [self textInRange:selectedRange];
//如果有高亮且当前字数开始位置小于最大限制时允许输入
if (selectedRange && pos) {
NSInteger startOffset = [self offsetFromPosition:self.beginningOfDocument toPosition:selectedRange.start];
NSInteger endOffset = [self offsetFromPosition:self.beginningOfDocument toPosition:selectedRange.end];
NSRange offsetRange = NSMakeRange(startOffset, endOffset - startOffset);
if (offsetRange.location < self.maxTextLength) {
return YES;
}
else
{
return NO;
}
}
NSString *comcatstr = [self.text stringByReplacingCharactersInRange:range withString:text];
NSInteger canInputLen = self.maxTextLength - comcatstr.length;
if (canInputLen >= 0)
{
return YES;
}
else
{
NSInteger len = text.length + canInputLen;
//防止当text.length + caninputlen < 0时,使得rg.length为一个非法最大正数出错
NSRange rg = {0,MAX(len,0)};
if (rg.length > 0)
{
NSString *s = @"";
//判断是否只普通的字符或asc码(对于中文和表情返回NO)
BOOL asc = [text canBeConvertedToEncoding:NSASCIIStringEncoding];
if (asc) {
s = [text substringWithRange:rg];//因为是ascii码直接取就可以了不会错
}
else
{
__block NSInteger idx = 0;
__block NSString *trimString = @"";//截取出的字串
//使用字符串遍历,这个方法能准确知道每个emoji是占一个unicode还是两个
[text enumerateSubstringsInRange:NSMakeRange(0, [text length])
options:NSStringEnumerationByComposedCharacterSequences
usingBlock: ^(NSString* substring, NSRange substringRange, NSRange enclosingRange, BOOL* stop) {
NSInteger steplen = substring.length;
if (idx >= rg.length) {
*stop = YES; //取出所需要就break,提高效率
return ;
}
trimString = [trimString stringByAppendingString:substring];
idx = idx + steplen;//这里变化了,使用了字串占的长度来作为步长
}];
s = trimString;
}
//rang是指从当前光标处进行替换处理(注意如果执行此句后面返回的是YES会触发didchange事件)
[self setText:[self.text stringByReplacingCharactersInRange:range withString:s]];
//既然是超出部分截取了,那一定是最大限制了。
self.textLength = self.maxTextLength;
}
return NO;
}
}
- (void)c_textViewDidChange
{
UITextRange *selectedRange = [self markedTextRange];
//获取高亮部分
UITextPosition *pos = [self positionFromPosition:selectedRange.start offset:0];
//如果在变化中是高亮部分在变,就不要计算字符了
if (selectedRange && pos) {
return;
}
NSString *nsTextContent = self.text;
NSInteger existTextNum = nsTextContent.length;
if (existTextNum > self.maxTextLength)
{
//截取到最大位置的字符(由于超出截部分在should时被处理了所在这里这了提高效率不再判断)
NSString *s = [nsTextContent substringToIndex:self.maxTextLength];
[self setText:s];
self.textLength = self.maxTextLength;
} else {
self.textLength = existTextNum;
}
}
@end
//
// UIView+CornerRadius.h
// Gengmei
//
// Created by wangyang on 2017/12/7.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIView (CornerRadius)
/**
通过添加一个额外UIImageView来完成圆角
确保在 self 被addSubview之后再调用该方法
*/
- (void)addCornerRadius5;
/**
设置圆角
@param cornerRadii 半径
@param corners 圆角位置
*/
- (void)containerRectCorner:(CGSize)cornerRadii byRoundingCorners:(UIRectCorner)corners;
@end
//
// UIView+CornerRadius.m
// Gengmei
//
// Created by wangyang on 2017/12/7.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
#import "UIView+CornerRadius.h"
#import <Masonry/Masonry.h>
@implementation UIView (CornerRadius)
- (void)addCornerRadius5 {
UIImageView *mask = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"diaryCoverMask"]];
mask.userInteractionEnabled = NO;
[self.superview addSubview:mask];
[mask mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
}
- (void)containerRectCorner:(CGSize)cornerRadii byRoundingCorners:(UIRectCorner)corners {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:cornerRadii];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
@end
//
// UIView+Layer.swift
// Gengmei
//
// Created by wangyang on 2017/6/7.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
import UIKit
@objc public extension UIView {
func setCornerRadius(_ radisu: CGFloat) {
layer.cornerRadius = radisu
clipsToBounds = true
}
}
//
// UIView+LikeAnimation.h
// test
//
// Created by wangyang on 16/9/21.
// Copyright © 2016年 北京更美互动信息科技有限公司. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIView (LikeAnimation)
- (void)addLikeAnimationWithFrame:(CGRect)frame NS_SWIFT_NAME(addLikeAnimation(withFrame:));
- (void)addLikeAnimationFrom:(CGPoint)point;
@end
//
// UIView+LikeAnimation.m
// test
//
// Created by wangyang on 16/9/21.
// Copyright © 2016年 北京更美互动信息科技有限公司. All rights reserved.
//
#import "UIView+LikeAnimation.h"
@implementation UIView (LikeAnimation)
- (void)addLikeAnimationWithFrame:(CGRect)frame {
UIImageView *likeView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"topic_zan_pink"]];
likeView.frame = frame;
[likeView addLikeAnimationFrom:likeView.center];
[self addSubview:likeView];
}
- (void)addLikeAnimationFrom:(CGPoint)point {
CGFloat totalTime = 1;
// 放大
CABasicAnimation *scaleBig = [CABasicAnimation animationWithKeyPath:@"transform"];
scaleBig.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
scaleBig.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(2.5, 2.5, 1.0)];
scaleBig.removedOnCompletion = YES;
scaleBig.beginTime = 0;
scaleBig.duration = 0.5 * totalTime;
scaleBig.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
// 缩小
CABasicAnimation *scaleSmall = [CABasicAnimation animationWithKeyPath:@"transform"];
scaleSmall.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(2.5, 2.5, 1.0)];
scaleSmall.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.5, 1.5, 1.0)];
scaleSmall.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
scaleSmall.removedOnCompletion = YES;
scaleSmall.beginTime = 0.5 * totalTime;
scaleSmall.duration = 0.5 * totalTime;
// 渐隐
CABasicAnimation *alphaAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
alphaAnimation.fromValue = @1;
alphaAnimation.toValue = @0.25;
alphaAnimation.removedOnCompletion = YES;
alphaAnimation.beginTime = 0.5 * totalTime;
alphaAnimation.duration = 0.5 * totalTime;
// 旋转
CABasicAnimation *rotate =
[CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotate.fromValue = [NSNumber numberWithFloat:0]; // 开始时的角度
rotate.toValue = [NSNumber numberWithFloat:M_PI_4]; // 结束时的角度
rotate.beginTime = 0;
rotate.duration = 0.5 * totalTime;
rotate.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
rotate.removedOnCompletion = NO;
rotate.fillMode = kCAFillModeForwards;
// 路径
UIBezierPath *movePath = [UIBezierPath bezierPath];
[movePath moveToPoint:point];
[movePath addQuadCurveToPoint:CGPointMake(point.x + 35, point.y - 43) controlPoint:CGPointMake(point.x + 27, point.y - 115)];
CAKeyframeAnimation * posAnim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
posAnim.path = movePath.CGPath;
posAnim.removedOnCompletion = YES;
// 组合动画
CAAnimationGroup *group = [CAAnimationGroup animation];
group.animations = [NSArray arrayWithObjects:scaleBig, scaleSmall, posAnim, rotate, alphaAnimation, nil];
group.duration = 1 * totalTime;
group.autoreverses = NO;
group.repeatCount = 1;
[self.layer addAnimation:group forKey:nil];
[self performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:1 * totalTime inModes:[NSArray arrayWithObject:NSRunLoopCommonModes]];
}
@end
//
// UIView+PointInside.swift
// Gengmei
//
// Created by wangyang on 2017/10/30.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
import Foundation
@objc public extension UIView {
/// 为view竖直方向增加一些热区
func gm_point(inside point: CGPoint, with event: UIEvent?) -> Bool {
if bounds.height > 35 {
return bounds.contains(point)
}
let heightDelta = 35 - bounds.size.height
let maxBounds = bounds.insetBy(dx: 0, dy: -0.5 * heightDelta)
return maxBounds.contains(point)
}
}
//
// UIView+ScreenshotImage.swift
// Gengmei
//
// Created by wangyang on 2017/3/23.
// Copyright © 2017年 更美互动信息科技有限公司. All rights reserved.
//
import Foundation
@objc public extension UIView {
func screenshot() -> UIImage {
if self is UIScrollView {
let scrollView = self as! UIScrollView
let savedContentOffset = scrollView.contentOffset
let savedFrame = scrollView.frame
// 使用scale才可以创建出符合屏幕分辨率的图片
// UIGraphicsBeginImageContext(scrollView.contentSize)
UIGraphicsBeginImageContextWithOptions(scrollView.contentSize, false, UIScreen.main.scale)
scrollView.contentOffset = .zero
frame = CGRect(x: 0, y: 0, width: scrollView.contentSize.width, height: scrollView.contentSize.height)
layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
scrollView.contentOffset = savedContentOffset
scrollView.frame = savedFrame
return image!
}
// UIGraphicsBeginImageContext(self.bounds.size)
UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, UIScreen.main.scale)
layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
}
//
// UIView+TileSubviews.h
// Gengmei
//
// Created by wangyang on 2016/10/26.
// Copyright © 2016年 更美互动信息科技有限公司. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIView (TileSubviews)
/**
按照参数设置好每个subview的frame,并返回view的总体高度,该高度包含padding的top与bottom
|----------------------------------|
| padding.top |
| |--------------| |-------| |
| | Label | | Image | |
| | | | | |
| |--------------| |-------| |
| padding.bottom |
|----------------------------------|
@param views 待摆放的subviews
@param padding 父视图与subviews整体的间距
@param spacing 每个subview之间的水平、竖直方向的间距
@param maxWidth 父view的最大宽度,包含padding的left与right
@param caculater 计算每个subview的大小, 可以为nil,将自动使用每个view.intrinsicContentSize
@return view的总体高度
*/
- (CGFloat)layoutSubviews:(NSArray<UIView *> *)views
padding:(UIEdgeInsets)padding
spacing:(CGPoint)spacing
maxWidth:(CGFloat)maxWidth
subviewSize:(CGSize (^ __nullable)(NSUInteger idx))caculater;
- (CGFloat)layoutSubviews:(NSArray<UIView *> *)views
padding:(UIEdgeInsets)padding
spacing:(CGPoint)spacing
maxWidth:(CGFloat)maxWidth
singleLine:(BOOL)singleLine
subviewSize:(CGSize (^ __nullable)(NSUInteger idx))caculater;
@end
NS_ASSUME_NONNULL_END
//
// UIView+TileSubviews.m
// Gengmei
//
// Created by wangyang on 2016/10/26.
// Copyright © 2016年 更美互动信息科技有限公司. All rights reserved.
//
#import "UIView+TileSubviews.h"
#import "UIView+Layout.h"
@implementation UIView (TileSubviews)
- (CGFloat)layoutSubviews:(NSArray<UIView *> *)views
padding:(UIEdgeInsets)padding
spacing:(CGPoint)spacing
maxWidth:(CGFloat)maxWidth
subviewSize:(CGSize (^)(NSUInteger idx))caculater {
__block CGFloat allHeight = 0;
__block UIView *preView;
[views enumerateObjectsUsingBlock:^(UIView * obj, NSUInteger idx, BOOL *stop) {
UIView *item = views[idx];
CGSize size = item.intrinsicContentSize;
if (caculater) {
size = caculater(idx);
}
views[idx].size = size;
if (idx == 0) {
item.left = padding.left;
item.top = padding.top;
preView = item;
} else {
//如果当前button超出了屏幕,则换行
NSInteger totleW = preView.right + spacing.x + size.width + padding.right;
if (totleW > maxWidth) {
item.left = padding.left;
item.top = preView.bottom + spacing.y;
}else{
item.left = preView.right + spacing.x;
item.top = preView.top;
}
}
preView = item;
}];
allHeight = preView.bottom + padding.bottom;
return allHeight;
}
- (CGFloat)layoutSubviews:(NSArray<UIView *> *)views
padding:(UIEdgeInsets)padding
spacing:(CGPoint)spacing
maxWidth:(CGFloat)maxWidth
singleLine:(BOOL)singleLine
subviewSize:(CGSize (^)(NSUInteger idx))caculater {
__block CGFloat allHeight = 0;
__block UIView *preView;
[views enumerateObjectsUsingBlock:^(UIView * obj, NSUInteger idx, BOOL *stop) {
UIView *item = views[idx];
CGSize size = item.intrinsicContentSize;
if (caculater) {
size = caculater(idx);
}
views[idx].size = size;
if (idx == 0) {
item.left = padding.left;
item.top = padding.top;
preView = item;
} else {
//如果当前button超出了屏幕,则换行
NSInteger totleW = preView.right + spacing.x + size.width + padding.right;
if (totleW > maxWidth) {
if (singleLine) {
[item removeFromSuperview];
} else {
item.left = padding.left;
item.top = preView.bottom + spacing.y;
preView = item;
}
}else{
item.left = preView.right + spacing.x;
item.top = preView.top;
preView = item;
}
}
}];
allHeight = preView.bottom + padding.bottom;
return allHeight;
}
@end
/*
* This file is part of the SDWebImage package.
* (c) Olivier Poitrey <rs@dailymotion.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
#import "SDWebImageCompat.h"
/**
These following class are provided to use `UIGraphicsImageRenderer` with polyfill, which allows write cross-platform(AppKit/UIKit) code and avoid runtime version check.
Compared to `UIGraphicsBeginImageContext`, `UIGraphicsImageRenderer` use dynamic bitmap from your draw code to generate CGContext, not always use ARGB8888, which is more performant on RAM usage.
Which means, if you draw CGImage/CIImage which contains grayscale only, the underlaying bitmap context use grayscale, it's managed by system and not a fixed type. (actually, the `kCGContextTypeAutomatic`)
For usage, See more in Apple's documentation: https://developer.apple.com/documentation/uikit/uigraphicsimagerenderer
For UIKit on iOS/tvOS 10+, these method just use the same `UIGraphicsImageRenderer` API.
For others (macOS/watchOS or iOS/tvOS 10-), these method use the `SDImageGraphics.h` to implements the same behavior (but without dynamic bitmap support)
*/
typedef void (^SDGraphicsImageDrawingActions)(CGContextRef _Nonnull context);
typedef NS_ENUM(NSInteger, SDGraphicsImageRendererFormatRange) {
SDGraphicsImageRendererFormatRangeUnspecified = -1,
SDGraphicsImageRendererFormatRangeAutomatic = 0,
SDGraphicsImageRendererFormatRangeExtended,
SDGraphicsImageRendererFormatRangeStandard
};
/// A set of drawing attributes that represent the configuration of an image renderer context.
@interface SDGraphicsImageRendererFormat : NSObject
/// The display scale of the image renderer context.
/// The default value is equal to the scale of the main screen.
@property (nonatomic) CGFloat scale;
/// A Boolean value indicating whether the underlying Core Graphics context has an alpha channel.
/// The default value is NO.
@property (nonatomic) BOOL opaque;
/// Specifying whether the bitmap context should use extended color.
/// For iOS 12+, the value is from system `preferredRange` property
/// For iOS 10-11, the value is from system `prefersExtendedRange` property
/// For iOS 9-, the value is `.standard`
@property (nonatomic) SDGraphicsImageRendererFormatRange preferredRange;
/// Init the default format. See each properties's default value.
- (nonnull instancetype)init;
/// Returns a new format best suited for the main screen’s current configuration.
+ (nonnull instancetype)preferredFormat;
@end
/// A graphics renderer for creating Core Graphics-backed images.
@interface SDGraphicsImageRenderer : NSObject
/// Creates an image renderer for drawing images of a given size.
/// @param size The size of images output from the renderer, specified in points.
/// @return An initialized image renderer.
- (nonnull instancetype)initWithSize:(CGSize)size;
/// Creates a new image renderer with a given size and format.
/// @param size The size of images output from the renderer, specified in points.
/// @param format A SDGraphicsImageRendererFormat object that encapsulates the format used to create the renderer context.
/// @return An initialized image renderer.
- (nonnull instancetype)initWithSize:(CGSize)size format:(nonnull SDGraphicsImageRendererFormat *)format;
/// Creates an image by following a set of drawing instructions.
/// @param actions A SDGraphicsImageDrawingActions block that, when invoked by the renderer, executes a set of drawing instructions to create the output image.
/// @note You should not retain or use the context outside the block, it's non-escaping.
/// @return A UIImage object created by the supplied drawing actions.
- (nonnull UIImage *)imageWithActions:(nonnull NS_NOESCAPE SDGraphicsImageDrawingActions)actions;
@end
/*
* This file is part of the SDWebImage package.
* (c) Olivier Poitrey <rs@dailymotion.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
#import "SDGraphicsImageRenderer.h"
#import "SDImageGraphics.h"
@interface SDGraphicsImageRendererFormat ()
#if SD_UIKIT
@property (nonatomic, strong) UIGraphicsImageRendererFormat *uiformat API_AVAILABLE(ios(10.0), tvos(10.0));
#endif
@end
@implementation SDGraphicsImageRendererFormat
@synthesize scale = _scale;
@synthesize opaque = _opaque;
@synthesize preferredRange = _preferredRange;
#pragma mark - Property
- (CGFloat)scale {
#if SD_UIKIT
if (@available(iOS 10.0, tvOS 10.10, *)) {
return self.uiformat.scale;
} else {
return _scale;
}
#else
return _scale;
#endif
}
- (void)setScale:(CGFloat)scale {
#if SD_UIKIT
if (@available(iOS 10.0, tvOS 10.10, *)) {
self.uiformat.scale = scale;
} else {
_scale = scale;
}
#else
_scale = scale;
#endif
}
- (BOOL)opaque {
#if SD_UIKIT
if (@available(iOS 10.0, tvOS 10.10, *)) {
return self.uiformat.opaque;
} else {
return _opaque;
}
#else
return _opaque;
#endif
}
- (void)setOpaque:(BOOL)opaque {
#if SD_UIKIT
if (@available(iOS 10.0, tvOS 10.10, *)) {
self.uiformat.opaque = opaque;
} else {
_opaque = opaque;
}
#else
_opaque = opaque;
#endif
}
- (SDGraphicsImageRendererFormatRange)preferredRange {
#if SD_UIKIT
if (@available(iOS 10.0, tvOS 10.10, *)) {
if (@available(iOS 12.0, tvOS 12.0, *)) {
return (SDGraphicsImageRendererFormatRange)self.uiformat.preferredRange;
} else {
BOOL prefersExtendedRange = self.uiformat.prefersExtendedRange;
if (prefersExtendedRange) {
return SDGraphicsImageRendererFormatRangeExtended;
} else {
return SDGraphicsImageRendererFormatRangeStandard;
}
}
} else {
return _preferredRange;
}
#else
return _preferredRange;
#endif
}
- (void)setPreferredRange:(SDGraphicsImageRendererFormatRange)preferredRange {
#if SD_UIKIT
if (@available(iOS 10.0, tvOS 10.10, *)) {
if (@available(iOS 12.0, tvOS 12.0, *)) {
self.uiformat.preferredRange = (UIGraphicsImageRendererFormatRange)preferredRange;
} else {
switch (preferredRange) {
case SDGraphicsImageRendererFormatRangeExtended:
self.uiformat.prefersExtendedRange = YES;
break;
case SDGraphicsImageRendererFormatRangeStandard:
self.uiformat.prefersExtendedRange = NO;
default:
// Automatic means default
break;
}
}
} else {
_preferredRange = preferredRange;
}
#else
_preferredRange = preferredRange;
#endif
}
- (instancetype)init {
self = [super init];
if (self) {
#if SD_UIKIT
if (@available(iOS 10.0, tvOS 10.10, *)) {
UIGraphicsImageRendererFormat *uiformat = [[UIGraphicsImageRendererFormat alloc] init];
self.uiformat = uiformat;
} else {
#endif
#if SD_WATCH
CGFloat screenScale = [WKInterfaceDevice currentDevice].screenScale;
#elif SD_UIKIT
CGFloat screenScale = [UIScreen mainScreen].scale;
#elif SD_MAC
CGFloat screenScale = [NSScreen mainScreen].backingScaleFactor;
#endif
self.scale = screenScale;
self.opaque = NO;
self.preferredRange = SDGraphicsImageRendererFormatRangeStandard;
#if SD_UIKIT
}
#endif
}
return self;
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability"
- (instancetype)initForMainScreen {
self = [super init];
if (self) {
#if SD_UIKIT
if (@available(iOS 10.0, tvOS 10.0, *)) {
UIGraphicsImageRendererFormat *uiformat;
// iOS 11.0.0 GM does have `preferredFormat`, but iOS 11 betas did not (argh!)
if ([UIGraphicsImageRenderer respondsToSelector:@selector(preferredFormat)]) {
uiformat = [UIGraphicsImageRendererFormat preferredFormat];
} else {
uiformat = [UIGraphicsImageRendererFormat defaultFormat];
}
self.uiformat = uiformat;
} else {
#endif
#if SD_WATCH
CGFloat screenScale = [WKInterfaceDevice currentDevice].screenScale;
#elif SD_UIKIT
CGFloat screenScale = [UIScreen mainScreen].scale;
#elif SD_MAC
CGFloat screenScale = [NSScreen mainScreen].backingScaleFactor;
#endif
self.scale = screenScale;
self.opaque = NO;
self.preferredRange = SDGraphicsImageRendererFormatRangeStandard;
#if SD_UIKIT
}
#endif
}
return self;
}
#pragma clang diagnostic pop
+ (instancetype)preferredFormat {
SDGraphicsImageRendererFormat *format = [[SDGraphicsImageRendererFormat alloc] initForMainScreen];
return format;
}
@end
@interface SDGraphicsImageRenderer ()
@property (nonatomic, assign) CGSize size;
@property (nonatomic, strong) SDGraphicsImageRendererFormat *format;
#if SD_UIKIT
@property (nonatomic, strong) UIGraphicsImageRenderer *uirenderer API_AVAILABLE(ios(10.0), tvos(10.0));
#endif
@end
@implementation SDGraphicsImageRenderer
- (instancetype)initWithSize:(CGSize)size {
return [self initWithSize:size format:SDGraphicsImageRendererFormat.preferredFormat];
}
- (instancetype)initWithSize:(CGSize)size format:(SDGraphicsImageRendererFormat *)format {
NSParameterAssert(format);
self = [super init];
if (self) {
self.size = size;
self.format = format;
#if SD_UIKIT
if (@available(iOS 10.0, tvOS 10.0, *)) {
UIGraphicsImageRendererFormat *uiformat = format.uiformat;
self.uirenderer = [[UIGraphicsImageRenderer alloc] initWithSize:size format:uiformat];
}
#endif
}
return self;
}
- (UIImage *)imageWithActions:(NS_NOESCAPE SDGraphicsImageDrawingActions)actions {
NSParameterAssert(actions);
#if SD_UIKIT
if (@available(iOS 10.0, tvOS 10.0, *)) {
UIGraphicsImageDrawingActions uiactions = ^(UIGraphicsImageRendererContext *rendererContext) {
if (actions) {
actions(rendererContext.CGContext);
}
};
return [self.uirenderer imageWithActions:uiactions];
} else {
#endif
SDGraphicsBeginImageContextWithOptions(self.size, self.format.opaque, self.format.scale);
CGContextRef context = SDGraphicsGetCurrentContext();
if (actions) {
actions(context);
}
UIImage *image = SDGraphicsGetImageFromCurrentImageContext();
SDGraphicsEndImageContext();
return image;
#if SD_UIKIT
}
#endif
}
@end
Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
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.
<img src="http://snapkit.io/images/banner.jpg" alt="" />
SnapKit is a DSL to make Auto Layout easy on both iOS and OS X.
[![Build Status](https://travis-ci.org/SnapKit/SnapKit.svg)](https://travis-ci.org/SnapKit/SnapKit)
[![Platform](https://img.shields.io/cocoapods/p/SnapKit.svg?style=flat)](https://github.com/SnapKit/SnapKit)
[![Cocoapods Compatible](https://img.shields.io/cocoapods/v/SnapKit.svg)](https://cocoapods.org/pods/SnapKit)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
#### ⚠️ **To use with Swift 3.x please ensure you are using >= 3.0.0** ⚠️
#### ⚠️ **To use with Swift 4.x please ensure you are using >= 4.0.0** ⚠️
## Contents
- [Requirements](#requirements)
- [Migration Guides](#migration-guides)
- [Communication](#communication)
- [Installation](#installation)
- [Usage](#usage)
- [Credits](#credits)
- [License](#license)
## Requirements
- iOS 8.0+ / Mac OS X 10.11+ / tvOS 9.0+
- Xcode 9.0+
- Swift 3.0+
## Communication
- If you **need help**, use [Stack Overflow](http://stackoverflow.com/questions/tagged/snapkit). (Tag 'snapkit')
- If you'd like to **ask a general question**, use [Stack Overflow](http://stackoverflow.com/questions/tagged/snapkit).
- If you **found a bug**, open an issue.
- If you **have a feature request**, open an issue.
- If you **want to contribute**, submit a pull request.
## Installation
### CocoaPods
[CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command:
```bash
$ gem install cocoapods
```
> CocoaPods 1.1.0+ is required to build SnapKit 4.0.0+.
To integrate SnapKit into your Xcode project using CocoaPods, specify it in your `Podfile`:
```ruby
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '10.0'
use_frameworks!
target '<Your Target Name>' do
pod 'SnapKit', '~> 4.0.0'
end
```
Then, run the following command:
```bash
$ pod install
```
### Carthage
[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.
You can install Carthage with [Homebrew](http://brew.sh/) using the following command:
```bash
$ brew update
$ brew install carthage
```
To integrate SnapKit into your Xcode project using Carthage, specify it in your `Cartfile`:
```ogdl
github "SnapKit/SnapKit" ~> 4.0.0
```
Run `carthage update` to build the framework and drag the built `SnapKit.framework` into your Xcode project.
### Manually
If you prefer not to use either of the aforementioned dependency managers, you can integrate SnapKit into your project manually.
---
## Usage
### Quick Start
```swift
import SnapKit
class MyViewController: UIViewController {
lazy var box = UIView()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(box)
box.snp.makeConstraints { (make) -> Void in
make.width.height.equalTo(50)
make.center.equalTo(self.view)
}
}
}
```
### Resources
- [Documentation](http://snapkit.io/docs/)
- [F.A.Q.](http://snapkit.io/faq/)
## Credits
- Robert Payne ([@robertjpayne](https://twitter.com/robertjpayne))
- Many other contributors
## License
SnapKit is released under the MIT license. See LICENSE for details.
This diff is collapsed.
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// 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.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
internal struct ConstraintAttributes : OptionSet, ExpressibleByIntegerLiteral {
typealias IntegerLiteralType = UInt
internal init(rawValue: UInt) {
self.rawValue = rawValue
}
internal init(_ rawValue: UInt) {
self.init(rawValue: rawValue)
}
internal init(nilLiteral: ()) {
self.rawValue = 0
}
internal init(integerLiteral rawValue: IntegerLiteralType) {
self.init(rawValue: rawValue)
}
internal private(set) var rawValue: UInt
internal static var allZeros: ConstraintAttributes { return 0 }
internal static func convertFromNilLiteral() -> ConstraintAttributes { return 0 }
internal var boolValue: Bool { return self.rawValue != 0 }
internal func toRaw() -> UInt { return self.rawValue }
internal static func fromRaw(_ raw: UInt) -> ConstraintAttributes? { return self.init(raw) }
internal static func fromMask(_ raw: UInt) -> ConstraintAttributes { return self.init(raw) }
// normal
internal static var none: ConstraintAttributes { return 0 }
internal static var left: ConstraintAttributes { return 1 }
internal static var top: ConstraintAttributes { return 2 }
internal static var right: ConstraintAttributes { return 4 }
internal static var bottom: ConstraintAttributes { return 8 }
internal static var leading: ConstraintAttributes { return 16 }
internal static var trailing: ConstraintAttributes { return 32 }
internal static var width: ConstraintAttributes { return 64 }
internal static var height: ConstraintAttributes { return 128 }
internal static var centerX: ConstraintAttributes { return 256 }
internal static var centerY: ConstraintAttributes { return 512 }
internal static var lastBaseline: ConstraintAttributes { return 1024 }
@available(iOS 8.0, OSX 10.11, *)
internal static var firstBaseline: ConstraintAttributes { return 2048 }
@available(iOS 8.0, *)
internal static var leftMargin: ConstraintAttributes { return 4096 }
@available(iOS 8.0, *)
internal static var rightMargin: ConstraintAttributes { return 8192 }
@available(iOS 8.0, *)
internal static var topMargin: ConstraintAttributes { return 16384 }
@available(iOS 8.0, *)
internal static var bottomMargin: ConstraintAttributes { return 32768 }
@available(iOS 8.0, *)
internal static var leadingMargin: ConstraintAttributes { return 65536 }
@available(iOS 8.0, *)
internal static var trailingMargin: ConstraintAttributes { return 131072 }
@available(iOS 8.0, *)
internal static var centerXWithinMargins: ConstraintAttributes { return 262144 }
@available(iOS 8.0, *)
internal static var centerYWithinMargins: ConstraintAttributes { return 524288 }
// aggregates
internal static var edges: ConstraintAttributes { return 15 }
internal static var size: ConstraintAttributes { return 192 }
internal static var center: ConstraintAttributes { return 768 }
@available(iOS 8.0, *)
internal static var margins: ConstraintAttributes { return 61440 }
@available(iOS 8.0, *)
internal static var centerWithinMargins: ConstraintAttributes { return 786432 }
internal var layoutAttributes:[LayoutAttribute] {
var attrs = [LayoutAttribute]()
if (self.contains(ConstraintAttributes.left)) {
attrs.append(.left)
}
if (self.contains(ConstraintAttributes.top)) {
attrs.append(.top)
}
if (self.contains(ConstraintAttributes.right)) {
attrs.append(.right)
}
if (self.contains(ConstraintAttributes.bottom)) {
attrs.append(.bottom)
}
if (self.contains(ConstraintAttributes.leading)) {
attrs.append(.leading)
}
if (self.contains(ConstraintAttributes.trailing)) {
attrs.append(.trailing)
}
if (self.contains(ConstraintAttributes.width)) {
attrs.append(.width)
}
if (self.contains(ConstraintAttributes.height)) {
attrs.append(.height)
}
if (self.contains(ConstraintAttributes.centerX)) {
attrs.append(.centerX)
}
if (self.contains(ConstraintAttributes.centerY)) {
attrs.append(.centerY)
}
if (self.contains(ConstraintAttributes.lastBaseline)) {
attrs.append(.lastBaseline)
}
#if os(iOS) || os(tvOS)
if (self.contains(ConstraintAttributes.firstBaseline)) {
attrs.append(.firstBaseline)
}
if (self.contains(ConstraintAttributes.leftMargin)) {
attrs.append(.leftMargin)
}
if (self.contains(ConstraintAttributes.rightMargin)) {
attrs.append(.rightMargin)
}
if (self.contains(ConstraintAttributes.topMargin)) {
attrs.append(.topMargin)
}
if (self.contains(ConstraintAttributes.bottomMargin)) {
attrs.append(.bottomMargin)
}
if (self.contains(ConstraintAttributes.leadingMargin)) {
attrs.append(.leadingMargin)
}
if (self.contains(ConstraintAttributes.trailingMargin)) {
attrs.append(.trailingMargin)
}
if (self.contains(ConstraintAttributes.centerXWithinMargins)) {
attrs.append(.centerXWithinMargins)
}
if (self.contains(ConstraintAttributes.centerYWithinMargins)) {
attrs.append(.centerYWithinMargins)
}
#endif
return attrs
}
}
internal func + (left: ConstraintAttributes, right: ConstraintAttributes) -> ConstraintAttributes {
return left.union(right)
}
internal func +=(left: inout ConstraintAttributes, right: ConstraintAttributes) {
left.formUnion(right)
}
internal func -=(left: inout ConstraintAttributes, right: ConstraintAttributes) {
left.subtract(right)
}
internal func ==(left: ConstraintAttributes, right: ConstraintAttributes) -> Bool {
return left.rawValue == right.rawValue
}
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// 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.
#if os(iOS) || os(tvOS)
import UIKit
public typealias ConstraintInterfaceLayoutDirection = UIUserInterfaceLayoutDirection
#else
import AppKit
public typealias ConstraintInterfaceLayoutDirection = NSUserInterfaceLayoutDirection
#endif
public struct ConstraintConfig {
public static var interfaceLayoutDirection: ConstraintInterfaceLayoutDirection = .leftToRight
}
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// 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.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
public protocol ConstraintConstantTarget {
}
extension CGPoint: ConstraintConstantTarget {
}
extension CGSize: ConstraintConstantTarget {
}
extension ConstraintInsets: ConstraintConstantTarget {
}
extension ConstraintConstantTarget {
internal func constraintConstantTargetValueFor(layoutAttribute: LayoutAttribute) -> CGFloat {
if let value = self as? CGFloat {
return value
}
if let value = self as? Float {
return CGFloat(value)
}
if let value = self as? Double {
return CGFloat(value)
}
if let value = self as? Int {
return CGFloat(value)
}
if let value = self as? UInt {
return CGFloat(value)
}
if let value = self as? CGSize {
if layoutAttribute == .width {
return value.width
} else if layoutAttribute == .height {
return value.height
} else {
return 0.0
}
}
if let value = self as? CGPoint {
#if os(iOS) || os(tvOS)
switch layoutAttribute {
case .left, .right, .leading, .trailing, .centerX, .leftMargin, .rightMargin, .leadingMargin, .trailingMargin, .centerXWithinMargins:
return value.x
case .top, .bottom, .centerY, .topMargin, .bottomMargin, .centerYWithinMargins, .lastBaseline, .firstBaseline:
return value.y
case .width, .height, .notAnAttribute:
return 0.0
}
#else
switch layoutAttribute {
case .left, .right, .leading, .trailing, .centerX:
return value.x
case .top, .bottom, .centerY, .lastBaseline, .firstBaseline:
return value.y
case .width, .height, .notAnAttribute:
return 0.0
}
#endif
}
if let value = self as? ConstraintInsets {
#if os(iOS) || os(tvOS)
switch layoutAttribute {
case .left, .leftMargin, .centerX, .centerXWithinMargins:
return value.left
case .top, .topMargin, .centerY, .centerYWithinMargins, .lastBaseline, .firstBaseline:
return value.top
case .right, .rightMargin:
return -value.right
case .bottom, .bottomMargin:
return -value.bottom
case .leading, .leadingMargin:
return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? value.left : value.right
case .trailing, .trailingMargin:
return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? -value.right : -value.left
case .width:
return -(value.left + value.right)
case .height:
return -(value.top + value.bottom)
case .notAnAttribute:
return 0.0
}
#else
switch layoutAttribute {
case .left, .centerX:
return value.left
case .top, .centerY, .lastBaseline, .firstBaseline:
return value.top
case .right:
return -value.right
case .bottom:
return -value.bottom
case .leading:
return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? value.left : value.right
case .trailing:
return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? -value.right : -value.left
case .width:
return -(value.left + value.right)
case .height:
return -(value.top + value.bottom)
case .notAnAttribute:
return 0.0
}
#endif
}
return 0.0
}
}
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// 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.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
public protocol ConstraintDSL {
var target: AnyObject? { get }
func setLabel(_ value: String?)
func label() -> String?
}
extension ConstraintDSL {
public func setLabel(_ value: String?) {
objc_setAssociatedObject(self.target as Any, &labelKey, value, .OBJC_ASSOCIATION_COPY_NONATOMIC)
}
public func label() -> String? {
return objc_getAssociatedObject(self.target as Any, &labelKey) as? String
}
}
private var labelKey: UInt8 = 0
public protocol ConstraintBasicAttributesDSL : ConstraintDSL {
}
extension ConstraintBasicAttributesDSL {
// MARK: Basics
public var left: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.left)
}
public var top: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.top)
}
public var right: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.right)
}
public var bottom: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.bottom)
}
public var leading: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.leading)
}
public var trailing: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.trailing)
}
public var width: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.width)
}
public var height: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.height)
}
public var centerX: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerX)
}
public var centerY: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerY)
}
public var edges: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.edges)
}
public var size: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.size)
}
public var center: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.center)
}
}
public protocol ConstraintAttributesDSL : ConstraintBasicAttributesDSL {
}
extension ConstraintAttributesDSL {
// MARK: Baselines
@available(*, deprecated:3.0, message:"Use .lastBaseline instead")
public var baseline: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.lastBaseline)
}
@available(iOS 8.0, OSX 10.11, *)
public var lastBaseline: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.lastBaseline)
}
@available(iOS 8.0, OSX 10.11, *)
public var firstBaseline: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.firstBaseline)
}
// MARK: Margins
@available(iOS 8.0, *)
public var leftMargin: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.leftMargin)
}
@available(iOS 8.0, *)
public var topMargin: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.topMargin)
}
@available(iOS 8.0, *)
public var rightMargin: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.rightMargin)
}
@available(iOS 8.0, *)
public var bottomMargin: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.bottomMargin)
}
@available(iOS 8.0, *)
public var leadingMargin: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.leadingMargin)
}
@available(iOS 8.0, *)
public var trailingMargin: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.trailingMargin)
}
@available(iOS 8.0, *)
public var centerXWithinMargins: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerXWithinMargins)
}
@available(iOS 8.0, *)
public var centerYWithinMargins: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerYWithinMargins)
}
@available(iOS 8.0, *)
public var margins: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.margins)
}
@available(iOS 8.0, *)
public var centerWithinMargins: ConstraintItem {
return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerWithinMargins)
}
}
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// 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.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
public class ConstraintDescription {
internal let item: LayoutConstraintItem
internal var attributes: ConstraintAttributes
internal var relation: ConstraintRelation? = nil
internal var sourceLocation: (String, UInt)? = nil
internal var label: String? = nil
internal var related: ConstraintItem? = nil
internal var multiplier: ConstraintMultiplierTarget = 1.0
internal var constant: ConstraintConstantTarget = 0.0
internal var priority: ConstraintPriorityTarget = 1000.0
internal lazy var constraint: Constraint? = {
guard let relation = self.relation,
let related = self.related,
let sourceLocation = self.sourceLocation else {
return nil
}
let from = ConstraintItem(target: self.item, attributes: self.attributes)
return Constraint(
from: from,
to: related,
relation: relation,
sourceLocation: sourceLocation,
label: self.label,
multiplier: self.multiplier,
constant: self.constant,
priority: self.priority
)
}()
// MARK: Initialization
internal init(item: LayoutConstraintItem, attributes: ConstraintAttributes) {
self.item = item
self.attributes = attributes
}
}
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// 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.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
public protocol ConstraintInsetTarget: ConstraintConstantTarget {
}
extension Int: ConstraintInsetTarget {
}
extension UInt: ConstraintInsetTarget {
}
extension Float: ConstraintInsetTarget {
}
extension Double: ConstraintInsetTarget {
}
extension CGFloat: ConstraintInsetTarget {
}
extension ConstraintInsets: ConstraintInsetTarget {
}
extension ConstraintInsetTarget {
internal var constraintInsetTargetValue: ConstraintInsets {
if let amount = self as? ConstraintInsets {
return amount
} else if let amount = self as? Float {
return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount))
} else if let amount = self as? Double {
return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount))
} else if let amount = self as? CGFloat {
return ConstraintInsets(top: amount, left: amount, bottom: amount, right: amount)
} else if let amount = self as? Int {
return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount))
} else if let amount = self as? UInt {
return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount))
} else {
return ConstraintInsets(top: 0, left: 0, bottom: 0, right: 0)
}
}
}
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// 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.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
#if os(iOS) || os(tvOS)
public typealias ConstraintInsets = UIEdgeInsets
#else
public typealias ConstraintInsets = NSEdgeInsets
#endif
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// 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.
#if os(iOS) || os(tvOS)
import UIKit
#else
import AppKit
#endif
public final class ConstraintItem {
internal weak var target: AnyObject?
internal let attributes: ConstraintAttributes
internal init(target: AnyObject?, attributes: ConstraintAttributes) {
self.target = target
self.attributes = attributes
}
internal var layoutConstraintItem: LayoutConstraintItem? {
return self.target as? LayoutConstraintItem
}
}
public func ==(lhs: ConstraintItem, rhs: ConstraintItem) -> Bool {
// pointer equality
guard lhs !== rhs else {
return true
}
// must both have valid targets and identical attributes
guard let target1 = lhs.target,
let target2 = rhs.target,
target1 === target2 && lhs.attributes == rhs.attributes else {
return false
}
return true
}
//
// SnapKit
//
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
//
// 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.
#if os(iOS) || os(tvOS)
import UIKit
#endif
@available(iOS 9.0, OSX 10.11, *)
public extension ConstraintLayoutGuide {
public var snp: ConstraintLayoutGuideDSL {
return ConstraintLayoutGuideDSL(guide: self)
}
}
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