修复工具类及删除代码
This commit is contained in:
@@ -72,7 +72,7 @@ struct _R {
|
||||
var mewRoomTopLineColor: RswiftResources.ColorResource { .init(name: "mewRoomTopLineColor", path: [], bundle: bundle) }
|
||||
}
|
||||
|
||||
/// This `_R.image` struct is generated, and contains static references to 138 images.
|
||||
/// This `_R.image` struct is generated, and contains static references to 145 images.
|
||||
struct image {
|
||||
let bundle: Foundation.Bundle
|
||||
|
||||
@@ -484,6 +484,27 @@ struct _R {
|
||||
/// Image `mew_tabbar_party_select`.
|
||||
var mew_tabbar_party_select: RswiftResources.ImageResource { .init(name: "mew_tabbar_party_select", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
|
||||
|
||||
/// Image `mewbg1`.
|
||||
var mewbg1: RswiftResources.ImageResource { .init(name: "mewbg1", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
|
||||
|
||||
/// Image `mewbg2`.
|
||||
var mewbg2: RswiftResources.ImageResource { .init(name: "mewbg2", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
|
||||
|
||||
/// Image `mewbg3`.
|
||||
var mewbg3: RswiftResources.ImageResource { .init(name: "mewbg3", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
|
||||
|
||||
/// Image `mewbg4`.
|
||||
var mewbg4: RswiftResources.ImageResource { .init(name: "mewbg4", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
|
||||
|
||||
/// Image `mewbg5`.
|
||||
var mewbg5: RswiftResources.ImageResource { .init(name: "mewbg5", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
|
||||
|
||||
/// Image `mewbg6`.
|
||||
var mewbg6: RswiftResources.ImageResource { .init(name: "mewbg6", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
|
||||
|
||||
/// Image `mewbg7`.
|
||||
var mewbg7: RswiftResources.ImageResource { .init(name: "mewbg7", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
|
||||
|
||||
/// Image `mine_setting_modif_pay_pwd_hidden`.
|
||||
var mine_setting_modif_pay_pwd_hidden: RswiftResources.ImageResource { .init(name: "mine_setting_modif_pay_pwd_hidden", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -17,43 +17,40 @@
|
||||
<rect key="frame" x="0.0" y="0.0" width="390" height="844"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="mew_home_bg" translatesAutoresizingMaskIntoConstraints="NO" id="PNT-qz-0tc">
|
||||
<rect key="frame" x="0.0" y="0.0" width="390" height="844"/>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="mew_home_bg" translatesAutoresizingMaskIntoConstraints="NO" id="PNT-qz-0tc">
|
||||
<rect key="frame" x="0.0" y="0.0" width="390" height="812"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
</imageView>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="mew_launch_logo.png" translatesAutoresizingMaskIntoConstraints="NO" id="VtB-hS-Aga">
|
||||
<rect key="frame" x="75" y="202" width="240" height="128"/>
|
||||
</imageView>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="mew_home_header_bg.png" translatesAutoresizingMaskIntoConstraints="NO" id="pcR-pR-yML">
|
||||
<rect key="frame" x="-195" y="410.66666666666669" width="780" height="22.666666666666686"/>
|
||||
<rect key="frame" x="143" y="216.33333333333337" width="104" height="104"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="VtB-hS-Aga" secondAttribute="height" multiplier="1:1" id="gGd-yw-Znm"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="音萌" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="O9G-IL-eNc">
|
||||
<rect key="frame" x="156" y="338" width="78" height="38"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="38" id="bZc-Tk-rMk"/>
|
||||
</constraints>
|
||||
<rect key="frame" x="170.66666666666666" y="335.33333333333326" width="48.666666666666657" height="28.666666666666742"/>
|
||||
<fontDescription key="fontDescription" name=".AppleSystemUIFont" family=".AppleSystemUIFont" pointSize="24"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="mew_home_header_bg.png" translatesAutoresizingMaskIntoConstraints="NO" id="pcR-pR-yML">
|
||||
<rect key="frame" x="65" y="384" width="260" height="23"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="23" id="907-SS-CEZ"/>
|
||||
<constraint firstAttribute="width" constant="260" id="BL9-9g-QbG"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||
<constraints>
|
||||
<constraint firstItem="PNT-qz-0tc" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="2Af-vd-7mS"/>
|
||||
<constraint firstItem="PNT-qz-0tc" firstAttribute="trailing" secondItem="Ze5-6b-2t3" secondAttribute="trailing" id="2rZ-NH-CFA"/>
|
||||
<constraint firstItem="pcR-pR-yML" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="40d-ES-7x9"/>
|
||||
<constraint firstItem="PNT-qz-0tc" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="8i9-19-ffT"/>
|
||||
<constraint firstItem="pcR-pR-yML" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="Bbp-O2-he9"/>
|
||||
<constraint firstItem="O9G-IL-eNc" firstAttribute="top" secondItem="VtB-hS-Aga" secondAttribute="bottom" constant="8" id="C1v-tZ-ssN"/>
|
||||
<constraint firstAttribute="bottom" secondItem="PNT-qz-0tc" secondAttribute="bottom" id="FWY-h9-AIl"/>
|
||||
<constraint firstItem="VtB-hS-Aga" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" constant="155" id="RIh-sk-IRP"/>
|
||||
<constraint firstItem="VtB-hS-Aga" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="75" id="TA9-Cj-DIF"/>
|
||||
<constraint firstItem="pcR-pR-yML" firstAttribute="top" secondItem="O9G-IL-eNc" secondAttribute="bottom" constant="34.666666666666686" id="Wmn-XW-ctP"/>
|
||||
<constraint firstItem="O9G-IL-eNc" firstAttribute="top" secondItem="VtB-hS-Aga" secondAttribute="bottom" constant="8" symbolic="YES" id="YwX-o4-XxA"/>
|
||||
<constraint firstItem="O9G-IL-eNc" firstAttribute="centerX" secondItem="pcR-pR-yML" secondAttribute="centerX" id="fIG-io-kLL"/>
|
||||
<constraint firstItem="O9G-IL-eNc" firstAttribute="centerX" secondItem="VtB-hS-Aga" secondAttribute="centerX" id="iRv-yQ-Bjr"/>
|
||||
<constraint firstItem="O9G-IL-eNc" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" constant="338" id="vAL-vM-0fV"/>
|
||||
<constraint firstItem="O9G-IL-eNc" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="156" id="yCJ-6y-9ev"/>
|
||||
<constraint firstItem="O9G-IL-eNc" firstAttribute="top" secondItem="VtB-hS-Aga" secondAttribute="bottom" constant="15" id="DRl-U2-hWc"/>
|
||||
<constraint firstItem="VtB-hS-Aga" firstAttribute="width" secondItem="Ze5-6b-2t3" secondAttribute="width" multiplier="100/375" id="LVF-8C-zU8"/>
|
||||
<constraint firstItem="O9G-IL-eNc" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="R0b-K1-xkx"/>
|
||||
<constraint firstItem="pcR-pR-yML" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="TGk-ow-WN9"/>
|
||||
<constraint firstItem="VtB-hS-Aga" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="bottom" multiplier="208/812" id="Zdw-5S-0cS"/>
|
||||
<constraint firstItem="pcR-pR-yML" firstAttribute="top" secondItem="O9G-IL-eNc" secondAttribute="bottom" constant="20" id="bhu-cy-Bhp"/>
|
||||
<constraint firstItem="VtB-hS-Aga" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="iqs-BQ-ie6"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</viewController>
|
||||
@@ -64,7 +61,7 @@
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="mew_home_bg" width="375" height="812"/>
|
||||
<image name="mew_home_header_bg.png" width="780" height="69"/>
|
||||
<image name="mew_home_header_bg.png" width="520" height="46"/>
|
||||
<image name="mew_launch_logo.png" width="576" height="576"/>
|
||||
<systemColor name="systemBackgroundColor">
|
||||
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
|
@@ -1,59 +0,0 @@
|
||||
//
|
||||
// Api.h
|
||||
// mew-ios
|
||||
//
|
||||
// Created by 触海 on 2023/11/6.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MewHttpRequestHelper.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface Api : NSObject
|
||||
|
||||
/**
|
||||
route : 接口路径
|
||||
method : http 请求方法(POST、GET等)
|
||||
completion : 网络请求完成的回调
|
||||
... : 可变参数,第一个为 __FUNCTION__ ,接下来依次为该接口的协议参数
|
||||
*/
|
||||
+ (void)makeRequest:(NSString *)route method:(MewHttpRequestHelperMethod)method completion:(MewHttpRequestHelperCompletion)completion, ...;
|
||||
|
||||
|
||||
/// 获取用户信息
|
||||
/// @param completion 请求完成
|
||||
/// @param uid 用户id
|
||||
+ (void)Mew_GetUserInfo:(MewHttpRequestHelperCompletion)completion uid:(NSString *)uid;
|
||||
|
||||
/// 获取手机号的验证码
|
||||
/// @param completion 请求完成
|
||||
/// @param mobile 手机号
|
||||
/// @param type 类型 请看XPEunm中的枚举
|
||||
+ (void)Mew_PhoneSmsCode:(MewHttpRequestHelperCompletion)completion mobile:(NSString *)mobile type:(NSString *)type;
|
||||
|
||||
|
||||
/// 批量验证
|
||||
/// @param complection 完成
|
||||
/// @param transcationIdStr 需要验证的数据
|
||||
+ (void)Mew_RequestCheckTranscationIds:(MewHttpRequestHelperCompletion)complection
|
||||
transcationIdStr:(NSString *)transcationIdStr;
|
||||
|
||||
/// 补全用户资料
|
||||
/// @param complection 完成
|
||||
/// @param userInfo 需要更新的用户信息
|
||||
+ (void)Mew_CompleteUserInfo:(MewHttpRequestHelperCompletion)complection
|
||||
userInfo:(NSDictionary *)userInfo;
|
||||
|
||||
/// 获取用户钱包余额信息
|
||||
/// @param complection 完成
|
||||
/// @param uid 用户uid
|
||||
/// @param ticket ticketg
|
||||
|
||||
+ (void)Mew_GetUserWalletInfo:(MewHttpRequestHelperCompletion)complection
|
||||
uid:(NSString *)uid
|
||||
ticket:(NSString *)ticket;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,89 +0,0 @@
|
||||
//
|
||||
// Api.m
|
||||
// mew-ios
|
||||
//
|
||||
// Created by 触海 on 2023/11/6.
|
||||
//
|
||||
|
||||
#import "Api.h"
|
||||
@implementation Api
|
||||
|
||||
+ (void)makeRequest:(NSString *)route method:(MewHttpRequestHelperMethod)method completion:(MewHttpRequestHelperCompletion)completion, ... {
|
||||
va_list arg_lists;
|
||||
va_start(arg_lists, completion);
|
||||
|
||||
// 获取第一个参数 __FUNCTION__ ,然后解析出来 key 。
|
||||
const char *functionName = va_arg(arg_lists, const char *);
|
||||
NSString *fn = [[NSString alloc] initWithUTF8String:functionName];
|
||||
// NSLog 一下 __FUNCTION__ 就知道为什么这么截取了。
|
||||
NSRange blankRange = [fn rangeOfString:@":"];
|
||||
NSUInteger start = blankRange.location + 1;
|
||||
NSUInteger length;
|
||||
if ((start + 2) < fn.length) {
|
||||
length = fn.length - start - 2;
|
||||
} else if ((start + 1) < fn.length) {
|
||||
length = fn.length -start - 1;
|
||||
} else {
|
||||
length = fn.length -start;
|
||||
}
|
||||
|
||||
NSString *fromatParamKeys = [fn substringWithRange:NSMakeRange(start, length)];
|
||||
// 构造请求的 NSMutableDictionary *params 。
|
||||
NSMutableDictionary *params = [NSMutableDictionary dictionary];
|
||||
|
||||
NSArray *paramKeys = [fromatParamKeys componentsSeparatedByString:@":"];
|
||||
NSEnumerator *enumerator = [paramKeys objectEnumerator];
|
||||
NSString *value = nil;
|
||||
while((value = va_arg(arg_lists, NSString*))){
|
||||
[params setValue:value forKey:enumerator.nextObject];
|
||||
};
|
||||
va_end(arg_lists);
|
||||
|
||||
[MewHttpRequestHelper request:route method:method params:params completion:completion];
|
||||
}
|
||||
|
||||
/// 获取用户信息
|
||||
+ (void)Mew_GetUserInfo:(MewHttpRequestHelperCompletion)completion uid:(NSString *)uid {
|
||||
NSString *getUrl = [MewEncryptManager mewAESDecryptText:@"KEMxFkjgYfZuaj0tYsUeqQ=="];///user/get
|
||||
[self makeRequest:getUrl method:MewHttpRequestHelperMethodGET completion:completion, __FUNCTION__, uid, nil];
|
||||
}
|
||||
|
||||
/// 批量验证
|
||||
/// @param complection 完成
|
||||
/// @param transcationIdStr 需要验证的数据
|
||||
+ (void)Mew_RequestCheckTranscationIds:(MewHttpRequestHelperCompletion)complection
|
||||
transcationIdStr:(NSString *)transcationIdStr {
|
||||
NSString *getUrl = [MewEncryptManager mewAESDecryptText:@"AC1UrTdJJWq1b8dtUCnP4zFOik6EzK85rr1GEjLv2Kk="];///verify/checkIOSChargeRecord
|
||||
[self makeRequest:getUrl method:MewHttpRequestHelperMethodPOST completion:complection, __FUNCTION__,transcationIdStr, nil];
|
||||
}
|
||||
|
||||
/// 获取手机号的验证码
|
||||
/// @param completion 请求完成
|
||||
/// @param mobile 手机号
|
||||
/// @param type 类型 请看XPEunm中的枚举
|
||||
+ (void)Mew_PhoneSmsCode:(MewHttpRequestHelperCompletion)completion mobile:(NSString *)mobile type:(NSString *)type {
|
||||
NSString *getUrl = [MewEncryptManager mewAESDecryptText:@"2Hx71goXCYG6r1fVVkSHsA=="];///sms/getCode
|
||||
[self makeRequest:getUrl method:MewHttpRequestHelperMethodPOST completion:completion, __FUNCTION__, mobile, type, nil];
|
||||
}
|
||||
|
||||
/// 补全用户资料
|
||||
/// @param complection 完成
|
||||
/// @param userInfo 需要更新的用户信息
|
||||
+ (void)Mew_CompleteUserInfo:(MewHttpRequestHelperCompletion)complection
|
||||
userInfo:(NSDictionary *)userInfo {
|
||||
NSString *getUrl = [MewEncryptManager mewAESDecryptText:@"6A7+MXSz6a7RbsOb9Ls+mA=="];///user/v2/update
|
||||
[MewHttpRequestHelper request:getUrl method:MewHttpRequestHelperMethodPOST params:userInfo completion:complection];
|
||||
}
|
||||
|
||||
|
||||
/// 获取用户钱包余额信息
|
||||
/// @param complection 完成
|
||||
/// @param uid 用户uid
|
||||
/// @param ticket ticketg
|
||||
+ (void)Mew_GetUserWalletInfo:(MewHttpRequestHelperCompletion)complection
|
||||
uid:(NSString *)uid
|
||||
ticket:(NSString *)ticket {
|
||||
NSString *getUrl = [MewEncryptManager mewAESDecryptText:@"7xFYk5dOEOCLb2Sfp0mwZw=="];//purse/query
|
||||
[self makeRequest:getUrl method:MewHttpRequestHelperMethodGET completion:complection, __FUNCTION__, uid, ticket,nil];
|
||||
}
|
||||
@end
|
@@ -1,36 +0,0 @@
|
||||
//
|
||||
// MewAccountInfoStorage.h
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/6.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
@class MewAccountModel, MewThirdUserInfo;
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MewAccountInfoStorage : NSObject
|
||||
@property (nonatomic, strong, readonly) MewAccountModel *accountModel;
|
||||
///如果是第三方登录的话 保存一下用户信息
|
||||
@property (nonatomic,strong) MewThirdUserInfo *thirdUserInfo;
|
||||
+ (instancetype)instance;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
- (id)copy NS_UNAVAILABLE;
|
||||
- (id)mutableCopy NS_UNAVAILABLE;
|
||||
|
||||
/// 获取当前的账号用户
|
||||
- (MewAccountModel *)mew_getCurrentAccountInfo;
|
||||
/// 保存当前的账号用户
|
||||
- (void)mew_saveAccountInfo:(MewAccountModel * _Nullable)accountInfo;
|
||||
/// 保存Ticket
|
||||
- (void)mew_saveTicket:(NSString *_Nullable)ticket;
|
||||
/// 获取Ticket
|
||||
- (NSString *)mew_getTicket;
|
||||
/// 获取用户id
|
||||
- (NSString *)mew_getUid;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,87 +0,0 @@
|
||||
//
|
||||
// MewAccountInfoStorage.m
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/6.
|
||||
//
|
||||
|
||||
#import "MewAccountInfoStorage.h"
|
||||
#import "MewAccountModel.h"
|
||||
#define kFileName @"AccountInfo.data"
|
||||
#define kDataKey @"accountInfo"
|
||||
|
||||
@interface MewAccountInfoStorage()
|
||||
@property (nonatomic, copy) NSString *ticket;
|
||||
@property (nonatomic, strong) MewAccountModel *accountModel;
|
||||
@end
|
||||
@implementation MewAccountInfoStorage
|
||||
static MewAccountInfoStorage *_instance = nil;
|
||||
|
||||
+ (MewAccountInfoStorage *)instance {
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
|
||||
dispatch_once(&onceToken, ^{
|
||||
_instance = [[self alloc] init];
|
||||
}) ;
|
||||
|
||||
return _instance;
|
||||
}
|
||||
|
||||
#pragma mark - Private Method
|
||||
- (NSString *) getFilePath {
|
||||
NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
||||
NSString *path = [[array objectAtIndex:0] stringByAppendingPathComponent:kFileName];
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
|
||||
[[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:nil];
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
#pragma mark - Public Method
|
||||
- (MewAccountModel *)mew_getCurrentAccountInfo {
|
||||
if (self.accountModel != nil) {
|
||||
return self.accountModel;
|
||||
}
|
||||
|
||||
NSData *data = [[NSData alloc] initWithContentsOfFile:[self getFilePath]];
|
||||
|
||||
NSError *error;
|
||||
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
|
||||
//解档出数据模型
|
||||
self.accountModel = [unarchiver decodeObjectForKey:kDataKey];
|
||||
[unarchiver finishDecoding];//一定不要忘记finishDecoding,否则会报错
|
||||
return self.accountModel;
|
||||
}
|
||||
|
||||
- (void)mew_saveAccountInfo:(MewAccountModel *_Nullable)accountInfo {
|
||||
if (accountInfo == nil) {
|
||||
accountInfo = [[MewAccountModel alloc] init];
|
||||
}
|
||||
self.accountModel = accountInfo;
|
||||
NSMutableData *data = [[NSMutableData alloc] init];
|
||||
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
|
||||
[archiver encodeObject:accountInfo forKey:kDataKey];
|
||||
[archiver finishEncoding];
|
||||
[data writeToFile:[self getFilePath] atomically:YES];
|
||||
}
|
||||
|
||||
- (void)mew_saveTicket:(NSString *_Nullable)t {
|
||||
self.ticket = t;
|
||||
}
|
||||
|
||||
- (NSString *)mew_getTicket {
|
||||
if (self.ticket == nil) {
|
||||
return @"";
|
||||
}
|
||||
return self.ticket;
|
||||
}
|
||||
|
||||
- (NSString *)mew_getUid {
|
||||
MewAccountModel *am = [self mew_getCurrentAccountInfo];
|
||||
if (am == nil) {
|
||||
return @"";
|
||||
}
|
||||
return am.uid;
|
||||
}
|
||||
@end
|
@@ -8,7 +8,7 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MewEnum.h"
|
||||
|
||||
#import "MewUserVipInfoVo.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MewUserInfoModel : NSObject
|
||||
@@ -52,9 +52,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
//@property (nonatomic,assign) UserEnterRoomFromType fromType;
|
||||
//@property (nonatomic,copy) NSString *fromUid;
|
||||
|
||||
#pragma mark - 相亲房的字段
|
||||
///贵族信息
|
||||
@property (nonatomic, strong) MewUserVipInfoVo *MewUserVipInfoVo;
|
||||
|
||||
///麦位昵称颜色
|
||||
@property (nonatomic, copy) NSString *micNickColor;
|
||||
@end
|
||||
|
@@ -1,31 +0,0 @@
|
||||
//
|
||||
// MewUserVipInfoVo.h
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/6.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MewUserVipInfoVo : NSObject
|
||||
///贵族图标
|
||||
@property (nonatomic, copy) NSString *vipIcon;
|
||||
///贵族等级
|
||||
@property (nonatomic, assign) NSInteger vipLevel;
|
||||
//用户好友昵称颜色
|
||||
@property (nonatomic, copy) NSString *friendNickColour;
|
||||
///是否防被踢
|
||||
@property (nonatomic, assign) BOOL preventKick;
|
||||
///是否隐身进房
|
||||
@property (nonatomic, assign) BOOL enterHide;
|
||||
///贵族进房特效
|
||||
@property (nonatomic, copy) NSString *enterRoomEffects;
|
||||
///贵族名称
|
||||
@property (nonatomic, copy) NSString *vipName;
|
||||
///隐身访问主页
|
||||
@property (nonatomic,assign) BOOL lookHomepageHide;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,12 +0,0 @@
|
||||
//
|
||||
// MewUserVipInfoVo.m
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/6.
|
||||
//
|
||||
|
||||
#import "MewUserVipInfoVo.h"
|
||||
|
||||
@implementation MewUserVipInfoVo
|
||||
|
||||
@end
|
@@ -1,26 +0,0 @@
|
||||
//
|
||||
// NSObject+MewAutoCoding.h
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/6.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface NSObject (MewAutoCoding)
|
||||
// Coding
|
||||
+ (NSDictionary *)codableProperties;
|
||||
- (void)setWithCoder:(NSCoder *)aDecoder;
|
||||
|
||||
// Properties access
|
||||
- (NSDictionary *)codableProperties;
|
||||
- (NSDictionary *)dictionaryRepresentation;
|
||||
|
||||
// Loading / Saving
|
||||
+ (instancetype)objectWithContentsOfFile:(NSString *)path;
|
||||
- (BOOL)writeToFile:(NSString *)filePath atomically:(BOOL)useAuxiliaryFile;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,240 +0,0 @@
|
||||
//
|
||||
// NSObject+MewAutoCoding.m
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/6.
|
||||
//
|
||||
|
||||
#import "NSObject+MewAutoCoding.h"
|
||||
#import <objc/runtime.h>
|
||||
#pragma GCC diagnostic ignored "-Wgnu"
|
||||
|
||||
static NSString *const AutocodingException = @"AutocodingException";
|
||||
@implementation NSObject (MewAutoCoding)
|
||||
+ (BOOL)supportsSecureCoding
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (instancetype)objectWithContentsOfFile:(NSString *)filePath
|
||||
{
|
||||
//load the file
|
||||
NSData *data = [NSData dataWithContentsOfFile:filePath];
|
||||
|
||||
//attempt to deserialise data as a plist
|
||||
id object = nil;
|
||||
if (data)
|
||||
{
|
||||
NSPropertyListFormat format;
|
||||
object = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListImmutable format:&format error:NULL];
|
||||
|
||||
//success?
|
||||
if (object)
|
||||
{
|
||||
//check if object is an NSCoded unarchive
|
||||
if ([object respondsToSelector:@selector(objectForKey:)] && [(NSDictionary *)object objectForKey:@"$archiver"])
|
||||
{
|
||||
object = [NSKeyedUnarchiver unarchiveObjectWithData:data];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//return raw data
|
||||
object = data;
|
||||
}
|
||||
}
|
||||
|
||||
//return object
|
||||
return object;
|
||||
}
|
||||
|
||||
- (BOOL)writeToFile:(NSString *)filePath atomically:(BOOL)useAuxiliaryFile
|
||||
{
|
||||
//note: NSData, NSDictionary and NSArray already implement this method
|
||||
//and do not save using NSCoding, however the objectWithContentsOfFile
|
||||
//method will correctly recover these objects anyway
|
||||
|
||||
//archive object
|
||||
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self];
|
||||
return [data writeToFile:filePath atomically:useAuxiliaryFile];
|
||||
}
|
||||
|
||||
+ (NSDictionary *)codableProperties
|
||||
{
|
||||
unsigned int propertyCount;
|
||||
__autoreleasing NSMutableDictionary *codableProperties = [NSMutableDictionary dictionary];
|
||||
objc_property_t *properties = class_copyPropertyList(self, &propertyCount);
|
||||
for (unsigned int i = 0; i < propertyCount; i++)
|
||||
{
|
||||
//get property name
|
||||
objc_property_t property = properties[i];
|
||||
const char *propertyName = property_getName(property);
|
||||
__autoreleasing NSString *key = @(propertyName);
|
||||
|
||||
//check if codable
|
||||
//get property type
|
||||
Class propertyClass = nil;
|
||||
char *typeEncoding = property_copyAttributeValue(property, "T");
|
||||
switch (typeEncoding[0])
|
||||
{
|
||||
case '@':
|
||||
{
|
||||
if (strlen(typeEncoding) >= 3)
|
||||
{
|
||||
char *className = strndup(typeEncoding + 2, strlen(typeEncoding) - 3);
|
||||
__autoreleasing NSString *name = @(className);
|
||||
NSRange range = [name rangeOfString:@"<"];
|
||||
if (range.location != NSNotFound)
|
||||
{
|
||||
name = [name substringToIndex:range.location];
|
||||
}
|
||||
propertyClass = NSClassFromString(name) ?: [NSObject class];
|
||||
free(className);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'c':
|
||||
case 'i':
|
||||
case 's':
|
||||
case 'l':
|
||||
case 'q':
|
||||
case 'C':
|
||||
case 'I':
|
||||
case 'S':
|
||||
case 'L':
|
||||
case 'Q':
|
||||
case 'f':
|
||||
case 'd':
|
||||
case 'B':
|
||||
{
|
||||
propertyClass = [NSNumber class];
|
||||
break;
|
||||
}
|
||||
case '{':
|
||||
{
|
||||
propertyClass = [NSValue class];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
free(typeEncoding);
|
||||
|
||||
if (propertyClass && [propertyClass conformsToProtocol:@protocol(NSSecureCoding)])
|
||||
{
|
||||
//check if there is a backing ivar
|
||||
char *ivar = property_copyAttributeValue(property, "V");
|
||||
if (ivar)
|
||||
{
|
||||
//check if ivar has KVC-compliant name
|
||||
__autoreleasing NSString *ivarName = @(ivar);
|
||||
if ([ivarName isEqualToString:key] || [ivarName isEqualToString:[@"_" stringByAppendingString:key]])
|
||||
{
|
||||
//no setter, but setValue:forKey: will still work
|
||||
codableProperties[key] = propertyClass;
|
||||
}
|
||||
free(ivar);
|
||||
}
|
||||
else
|
||||
{
|
||||
//check if property is dynamic and readwrite
|
||||
char *dynamic = property_copyAttributeValue(property, "D");
|
||||
char *readonly = property_copyAttributeValue(property, "R");
|
||||
if (dynamic && !readonly)
|
||||
{
|
||||
//no ivar, but setValue:forKey: will still work
|
||||
codableProperties[key] = propertyClass;
|
||||
}
|
||||
free(dynamic);
|
||||
free(readonly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(properties);
|
||||
return codableProperties;
|
||||
}
|
||||
|
||||
- (NSDictionary *)codableProperties
|
||||
{
|
||||
__autoreleasing NSDictionary *codableProperties = objc_getAssociatedObject([self class], _cmd);
|
||||
if (!codableProperties)
|
||||
{
|
||||
codableProperties = [NSMutableDictionary dictionary];
|
||||
Class subclass = [self class];
|
||||
while (subclass != [NSObject class])
|
||||
{
|
||||
[(NSMutableDictionary *)codableProperties addEntriesFromDictionary:[subclass codableProperties]];
|
||||
subclass = [subclass superclass];
|
||||
}
|
||||
codableProperties = [NSDictionary dictionaryWithDictionary:codableProperties];
|
||||
|
||||
//make the association atomically so that we don't need to bother with an @synchronize
|
||||
objc_setAssociatedObject([self class], _cmd, codableProperties, OBJC_ASSOCIATION_RETAIN);
|
||||
}
|
||||
return codableProperties;
|
||||
}
|
||||
|
||||
- (NSDictionary *)dictionaryRepresentation
|
||||
{
|
||||
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
|
||||
for (__unsafe_unretained NSString *key in [self codableProperties])
|
||||
{
|
||||
id value = [self valueForKey:key];
|
||||
if (value)
|
||||
dict[key] = value;
|
||||
else
|
||||
dict[key] = @"nil";
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
|
||||
- (void)setWithCoder:(NSCoder *)aDecoder
|
||||
{
|
||||
BOOL secureAvailable = [aDecoder respondsToSelector:@selector(decodeObjectOfClass:forKey:)];
|
||||
BOOL secureSupported = [[self class] supportsSecureCoding];
|
||||
NSDictionary *properties = [self codableProperties];
|
||||
for (NSString *key in properties)
|
||||
{
|
||||
id object = nil;
|
||||
Class propertyClass = properties[key];
|
||||
if (secureAvailable)
|
||||
{
|
||||
if ([propertyClass isEqual:[NSMutableAttributedString class]]) {
|
||||
continue;
|
||||
}
|
||||
object = [aDecoder decodeObjectOfClass:propertyClass forKey:key];
|
||||
}
|
||||
else
|
||||
{
|
||||
if ([propertyClass isEqual:[NSMutableAttributedString class]]) {
|
||||
continue;
|
||||
}
|
||||
object = [aDecoder decodeObjectForKey:key];
|
||||
}
|
||||
if (object)
|
||||
{
|
||||
if (secureSupported && ![object isKindOfClass:propertyClass])
|
||||
{
|
||||
[NSException raise:AutocodingException format:@"Expected '%@' to be a %@, but was actually a %@", key, propertyClass, [object class]];
|
||||
}
|
||||
[self setValue:object forKey:key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)aDecoder
|
||||
{
|
||||
[self setWithCoder:aDecoder];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)aCoder
|
||||
{
|
||||
for (NSString *key in [self codableProperties])
|
||||
{
|
||||
id object = [self valueForKey:key];
|
||||
if (object) [aCoder encodeObject:object forKey:key];
|
||||
}
|
||||
}
|
||||
@end
|
@@ -1,34 +0,0 @@
|
||||
//
|
||||
// MewBaseMvpPresenter.h
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/5.
|
||||
//
|
||||
#import "MewBaseMvpProtocol.h"
|
||||
#import "MewHttpRequestHelper.h"
|
||||
#import <Foundation/Foundation.h>
|
||||
typedef void(^MewHttpSuccess)(MewBaseModel * _Nullable data);
|
||||
typedef void(^MewHttpFail)(NSInteger code, NSString * _Nullable msg);
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MewBaseMvpPresenter : NSObject
|
||||
// 初始化view
|
||||
- (void)mew_attatchView:(id)view;
|
||||
// 获取view
|
||||
- (id)mew_getView;
|
||||
- (void)mew_detatchView;
|
||||
// 退出
|
||||
- (void)mew_logout;
|
||||
|
||||
- (MewHttpRequestHelperCompletion)mew_createHttpCompletion:(MewHttpSuccess _Nonnull)success;
|
||||
- (MewHttpRequestHelperCompletion)mew_createHttpCompletion:(MewHttpSuccess _Nonnull)success mew_showLoading:(BOOL)loading;
|
||||
- (MewHttpRequestHelperCompletion)mew_createHttpCompletion:(MewHttpSuccess _Nonnull)success errorToast:(BOOL)toast;
|
||||
- (MewHttpRequestHelperCompletion)mew_createHttpCompletion:(MewHttpSuccess _Nonnull)success mew_showLoading:(BOOL)loading errorToast:(BOOL)toast;
|
||||
- (MewHttpRequestHelperCompletion)mew_createHttpCompletion:(MewHttpSuccess _Nonnull)success fail:(MewHttpFail _Nullable)fail;
|
||||
- (MewHttpRequestHelperCompletion)mew_createHttpCompletion:(MewHttpSuccess _Nonnull)success fail:(MewHttpFail _Nullable)fail mew_showLoading:(BOOL)loading;
|
||||
- (MewHttpRequestHelperCompletion)mew_createHttpCompletion:(MewHttpSuccess _Nonnull)success fail:(MewHttpFail _Nullable)fail errorToast:(BOOL)toast;
|
||||
- (MewHttpRequestHelperCompletion)mew_createHttpCompletion:(MewHttpSuccess _Nonnull)success fail:(MewHttpFail _Nullable)fail mew_showLoading:(BOOL)loading errorToast:(BOOL)toast;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,112 +0,0 @@
|
||||
//
|
||||
// MewBaseMvpPresenter.m
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/5.
|
||||
//
|
||||
|
||||
#import "MewBaseMvpPresenter.h"
|
||||
#import "MewAccountInfoStorage.h"
|
||||
#import "MewClientConfig.h"
|
||||
#import "NSObject+MEWExtension.h"
|
||||
@interface MewBaseMvpPresenter()
|
||||
|
||||
@property (nonatomic, weak) id view;
|
||||
|
||||
@end
|
||||
@implementation MewBaseMvpPresenter
|
||||
- (void)mew_attatchView:(id)view {
|
||||
self.view = view;
|
||||
}
|
||||
|
||||
- (id)mew_getView {
|
||||
return self.view;
|
||||
}
|
||||
|
||||
/// 登出
|
||||
- (void)mew_logout {
|
||||
[[MewAccountInfoStorage instance] mew_saveAccountInfo:nil];
|
||||
[[MewAccountInfoStorage instance] mew_saveTicket:nil];
|
||||
|
||||
///关闭心跳
|
||||
[[MewClientConfig shareConfig] mew_resetHeartBratTimer];
|
||||
[[self mew_getView] mew_getTokenId];
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (MewHttpRequestHelperCompletion)mew_createHttpCompletion:(MewHttpSuccess)success {
|
||||
return [self mew_createHttpCompletion:success fail:nil];
|
||||
}
|
||||
|
||||
- (MewHttpRequestHelperCompletion)mew_createHttpCompletion:(MewHttpSuccess)success mew_showLoading:(BOOL)loading {
|
||||
return [self mew_createHttpCompletion:success fail:nil mew_showLoading:loading];
|
||||
}
|
||||
|
||||
- (MewHttpRequestHelperCompletion)mew_createHttpCompletion:(MewHttpSuccess)success errorToast:(BOOL)toast {
|
||||
return [self mew_createHttpCompletion:success fail:nil errorToast:toast];
|
||||
}
|
||||
|
||||
- (MewHttpRequestHelperCompletion)mew_createHttpCompletion:(MewHttpSuccess)success mew_showLoading:(BOOL)loading errorToast:(BOOL)toast {
|
||||
return [self mew_createHttpCompletion:success fail:nil mew_showLoading:loading errorToast:toast];
|
||||
}
|
||||
|
||||
- (MewHttpRequestHelperCompletion)mew_createHttpCompletion:(MewHttpSuccess)success fail:(MewHttpFail)fail {
|
||||
return [self mew_createHttpCompletion:success fail:fail mew_showLoading:NO errorToast:YES];
|
||||
}
|
||||
|
||||
- (MewHttpRequestHelperCompletion)mew_createHttpCompletion:(MewHttpSuccess)success fail:(MewHttpFail)fail mew_showLoading:(BOOL)loading {
|
||||
return [self mew_createHttpCompletion:success fail:fail mew_showLoading:loading errorToast:YES];
|
||||
}
|
||||
|
||||
- (MewHttpRequestHelperCompletion)mew_createHttpCompletion:(MewHttpSuccess)success fail:(MewHttpFail)fail errorToast:(BOOL)toast {
|
||||
return [self mew_createHttpCompletion:success fail:fail mew_showLoading:NO errorToast:toast];
|
||||
}
|
||||
|
||||
- (MewHttpRequestHelperCompletion)mew_createHttpCompletion:(MewHttpSuccess)success fail:(MewHttpFail)fail mew_showLoading:(BOOL)loading errorToast:(BOOL)toast {
|
||||
// if (loading) {
|
||||
// [self.view showAnchorLoading];
|
||||
// }
|
||||
return ^(MewBaseModel *data, NSInteger code, NSString * _Nullable msg) {
|
||||
if (loading && [self.view respondsToSelector:@selector(mew_hideHUD)]) {
|
||||
[self.view mew_hideHUD];
|
||||
}
|
||||
if (code == 200) {
|
||||
success(data);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (code) {
|
||||
case 401: // 登录过期
|
||||
[self mew_logout];
|
||||
return;
|
||||
case 407:
|
||||
case 408:
|
||||
// [[self mew_getView] accountBanned:data];
|
||||
return;
|
||||
case 1415: // 未完善用户信息
|
||||
[[self mew_getView] mew_completeUserInfo];
|
||||
return;
|
||||
case 3009: // 账号已注销
|
||||
[[self mew_getView] mew_accountCanceled:data.mewModel2dictionary];
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (toast && [self.view respondsToSelector:@selector(mew_showErrorToast:)]) {
|
||||
[self.view mew_showErrorToast:msg];
|
||||
}
|
||||
|
||||
if (fail) {
|
||||
fail(code, msg);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (void)mew_detatchView {
|
||||
|
||||
}
|
||||
@end
|
@@ -1,22 +0,0 @@
|
||||
//
|
||||
// MewMewBaseMvpProtocol.h
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/5.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MewBaseViewController.h"
|
||||
@class MewBaseModel;
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol MewBaseMvpProtocol <NSObject,MewBaseViewControllerProtocol>
|
||||
/// 登录失效
|
||||
- (void)mew_getTokenId;
|
||||
/// 跳转到填写用户资料
|
||||
- (void)mew_completeUserInfo;
|
||||
/// 账号已注销
|
||||
- (void)mew_accountCanceled:(NSDictionary *)data;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,20 +0,0 @@
|
||||
//
|
||||
// MewMvpViewController.h
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/6.
|
||||
//
|
||||
#import "MewBaseViewController.h"
|
||||
#import "MewBaseMvpPresenter.h"
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MewMvpViewController<T> : MewBaseViewController
|
||||
@property (nonatomic, strong) __kindof T presenter;
|
||||
|
||||
- (__kindof T)createPresenter;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,65 +0,0 @@
|
||||
//
|
||||
// MewMvpViewController.m
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/6.
|
||||
//
|
||||
|
||||
#import "MewMvpViewController.h"
|
||||
#import "MewLoginViewController.h"
|
||||
#import "MewBaseNavigationController.h"
|
||||
@implementation MewMvpViewController
|
||||
#pragma mark - Life Cycle
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma mark - Public Method
|
||||
- (__kindof id)presenter {
|
||||
if (_presenter == nil) {
|
||||
_presenter = [self createPresenter];
|
||||
[_presenter mew_attatchView:self];
|
||||
}
|
||||
return _presenter;
|
||||
}
|
||||
|
||||
- (__kindof id)createPresenter {
|
||||
return [[MewBaseMvpPresenter alloc] init];
|
||||
}
|
||||
|
||||
#pragma mark - MewBaseMvpProtocol
|
||||
- (void)mew_getTokenId {
|
||||
MewLoginViewController *loginVC = [[MewLoginViewController alloc] init];
|
||||
MewBaseNavigationController * nav = [[MewBaseNavigationController alloc] initWithRootViewController:loginVC];
|
||||
nav.modalPresentationStyle = UIModalPresentationFullScreen;
|
||||
[self.navigationController presentViewController:nav animated:YES completion:nil];
|
||||
}
|
||||
|
||||
- (void)mew_completeUserInfo {
|
||||
|
||||
}
|
||||
|
||||
|
||||
- (void)mew_accountCanceled:(NSDictionary *)data {
|
||||
// NSString *date = [NSString stringWithFormat:@"%.0f",[[data objectForKey:@"cancelDate"] doubleValue]];
|
||||
// NSString *dateDes = [NSString stringWithFormat:@"注销时间:%@", [PLTimeUtil getDateWithYYMMDD:date]];
|
||||
// NSString *msg = [NSString stringWithFormat:@"%@\n\n请联系客服(微信:yinmeng-kefu)咨询哦!", dateDes];
|
||||
// TTAlertMessageAttributedConfig *dateAttrConfig = [[TTAlertMessageAttributedConfig alloc] init];
|
||||
// dateAttrConfig.text = dateDes;
|
||||
// dateAttrConfig.color = ThemeColor.appMainColor;
|
||||
//
|
||||
// TTAlertConfig *config = [[TTAlertConfig alloc] init];
|
||||
// config.title = @"该账号已注销";
|
||||
// config.message = msg;
|
||||
// config.messageAttributedConfig = @[dateAttrConfig];
|
||||
//
|
||||
// [TTPopup alertWithConfig:config confirmHandler:^{
|
||||
//
|
||||
// } cancelHandler:^{
|
||||
//
|
||||
// }];
|
||||
}
|
||||
|
||||
@end
|
85
yinmeng-ios/yinmeng-ios/Base/MewApi/MewOCServerManager.h
Normal file
85
yinmeng-ios/yinmeng-ios/Base/MewApi/MewOCServerManager.h
Normal file
@@ -0,0 +1,85 @@
|
||||
//
|
||||
// MewOCServerManager.h
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2024/1/19.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MewBaseModel.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
/// http://beta.h5.ymlive.fun
|
||||
#define Mew_Server_API_Base_H5_URL @"GoK87pcrCtMGRUiI37dI/jjoKPw7cA0hRRBRFdEmwbY="
|
||||
/// http://beta.api.ymlive.fun
|
||||
#define Mew_Server_API_Base_URL @"699gQF4rRYIwztF2zlUunGDlDP2GdDcO5MWptrXUmgU="
|
||||
|
||||
#else
|
||||
/// http://h5.ymlive.fun
|
||||
#define Mew_Server_API_Base_H5_URL @"https://h5.ymlive.fun"
|
||||
|
||||
/// https://api.ymlive.fun
|
||||
#define Mew_Server_API_Base_URL @"https://api.ymlive.fun"
|
||||
#endif
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
typedef void(^MewOCServerManagerSucceed)(MewBaseModel* _Nullable obj, NSInteger num, NSString * text);
|
||||
|
||||
|
||||
@interface MewOCServerManager : NSObject
|
||||
+ (void)mewRequestData:(NSString *)url type:(MewOCServerManagerType)type successBlock:(MewOCServerManagerSucceed)successBlock, ...;
|
||||
+ (void)mewRequestToken:(MewOCServerManagerSucceed)successBlock access_token:(NSString *)accessToken issue_type:(NSString *)issueType;
|
||||
+ (void)mewRequestInitInfo:(MewOCServerManagerSucceed)successBlock;
|
||||
+ (void)mewRequestMainHomeGameTabList:(MewOCServerManagerSucceed)successBlock;
|
||||
+ (void)mewRequestMainHomeNewFriendList:(MewOCServerManagerSucceed)successBlock gender:(NSString *)gender gameId:(NSString *)gameId;
|
||||
+ (void)mewRequestRandomFindFriendList:(MewOCServerManagerSucceed)successBlock gender:(NSString *)gender;
|
||||
+ (void)mewRequestUploadPhotoToken:(MewOCServerManagerSucceed)successBlock;
|
||||
+ (void)mewUploadPhotoAction:(NSString *)path
|
||||
name:(NSString *)name
|
||||
token:(NSString *)token
|
||||
successBlock:(void (^)(NSString *key, NSDictionary *res))successBlock
|
||||
failureBlock:(void (^)(NSNumber *code, NSString *message))failureBlock;
|
||||
+ (void)mewPublishSoundInfo:(MewOCServerManagerSucceed)successBlock dura:(NSString *)dura desc:(NSString *)desc gender:(NSString *)gender url:(NSString *)url;
|
||||
+ (void)mewGetCollectRoomListData:(MewOCServerManagerSucceed)successBlock uid:(NSString *)uid page:(NSString *)page pageSize:(NSString *)pageSize roomType:(NSString *)roomType;
|
||||
+ (void)mewLogout:(MewOCServerManagerSucceed)successBlock auaccess_token:(NSString *)access_token;
|
||||
+ (void)mewGetDetailData:(MewOCServerManagerSucceed)successBlock uid:(NSString *)uid page:(NSString *)page pageSize:(NSString *)pageSize;
|
||||
+ (void)mewLikeUsr:(MewOCServerManagerSucceed)successBlock uid:(NSString *)uid likedUid:(NSString *)likedUid ticket:(NSString *)ticket type:(NSString *)type;
|
||||
+ (void)mewGetListStatus:(MewOCServerManagerSucceed)successBlock uid:(NSString *)uid isLikeUid:(NSString *)isLikeUid;
|
||||
+ (void)mewGetLikeListInfo:(MewOCServerManagerSucceed)successBlock uid:(NSString *)uid pageNo:(NSString *)pageNo pageSize:(NSString *)pageSize;
|
||||
+ (void)mewGetPayDataList:(MewOCServerManagerSucceed)successBlock channelType:(NSString *)channelType;
|
||||
+ (void)mewPayAction:(MewOCServerManagerSucceed)successBlock
|
||||
chargeProdId:(NSString *)chargeProdId
|
||||
uid:(NSString *)uid
|
||||
ticket:(NSString *)ticket
|
||||
deviceInfo:(NSString *)deviceInfo
|
||||
clientIp:(NSString *)clientIp;
|
||||
+ (void)mewGetPayOrderState:(MewOCServerManagerSucceed)successBlock chooseEnv:(NSString *)chooseEnv chargeRecordId:(NSString *)chargeRecordId transcationId:(NSString *)transcationId uid:(NSString *)uid ticket:(NSString *)ticket;
|
||||
+ (void)mewSetLoginPasswordAction:(MewOCServerManagerSucceed)successBlock phone:(NSString *)phone newPwd:(NSString *)newPwd;
|
||||
+ (void)mewChangeLoginPassword:(MewOCServerManagerSucceed)successBlock phone:(NSString *)phone newPwd:(NSString *)newPwd pwd:(NSString *)pwd;
|
||||
+ (void)mewLoginAppWithCode:(MewOCServerManagerSucceed)successBlock
|
||||
phone:(NSString *)phone
|
||||
code:(NSString *)code
|
||||
client_secret:(NSString *)client_secret
|
||||
version:(NSString *)version
|
||||
client_id:(NSString *)client_id
|
||||
grant_type:(NSString *)grant_type;
|
||||
+ (void)mewLoginAppWithPassword:(MewOCServerManagerSucceed)successBlock phone:(NSString *)phone password:(NSString *)password client_secret:(NSString *)client_secret version:(NSString *)version client_id:(NSString *)client_id grant_type:(NSString *)grant_type;
|
||||
+ (void)mewAgainSetPassword:(MewOCServerManagerSucceed)successBlock phone:(NSString *)phone newPwd:(NSString *)newPwd;
|
||||
+ (void)mewAppleLogin:(MewOCServerManagerSucceed)successBlock openid:(NSString *)openid unionid:(NSString *)unionid access_token:(NSString *)access_token type:(NSString *)type;
|
||||
+ (void)mewGetUserNick:(MewOCServerManagerSucceed)successBlock;
|
||||
+ (void)mewSetUserPhoneInfo:(MewOCServerManagerSucceed)successBlock
|
||||
phone:(NSString *)phone
|
||||
code:(NSString *)code
|
||||
ticket:(NSString *)ticket;
|
||||
+ (void)mewGetUserDataWithUid:(MewOCServerManagerSucceed)successBlock uid:(NSString *)uid;
|
||||
+ (void)mewGetPhoneAuthCode:(MewOCServerManagerSucceed)successBlock mobile:(NSString *)mobile type:(NSString *)type;
|
||||
+ (void)mewSetUserDataWithRegister:(MewOCServerManagerSucceed)successBlock
|
||||
userInfo:(NSDictionary *)userInfo;
|
||||
+ (void)mewGetDiamondCount:(MewOCServerManagerSucceed)successBlock
|
||||
uid:(NSString *)uid
|
||||
ticket:(NSString *)ticket;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
328
yinmeng-ios/yinmeng-ios/Base/MewApi/MewOCServerManager.m
Normal file
328
yinmeng-ios/yinmeng-ios/Base/MewApi/MewOCServerManager.m
Normal file
@@ -0,0 +1,328 @@
|
||||
//
|
||||
// MewOCServerManager.m
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2024/1/19.
|
||||
//
|
||||
|
||||
#import "MewOCServerManager.h"
|
||||
#import "MewAccountModel.h"
|
||||
|
||||
#import <Qiniu/QiniuSDK.h>
|
||||
@implementation MewOCServerManager
|
||||
|
||||
+ (AFHTTPSessionManager *)share {
|
||||
|
||||
static AFHTTPSessionManager *mewRequesmanager = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSString *path ;
|
||||
#ifdef DEBUG
|
||||
path = [MewEncryptManager mewAESDecryptText:Mew_Server_API_Base_URL];
|
||||
#else
|
||||
path = Mew_Server_API_Base_URL;
|
||||
#endif
|
||||
NSLog(@"%@",path);
|
||||
NSLog(@"%@",path);
|
||||
mewRequesmanager = [[AFHTTPSessionManager manager]initWithBaseURL:[NSURL URLWithString:path]];
|
||||
|
||||
mewRequesmanager .responseSerializer = [AFJSONResponseSerializer serializer];
|
||||
mewRequesmanager .requestSerializer.HTTPShouldHandleCookies = YES;
|
||||
// 客户端是否信任非法证书
|
||||
mewRequesmanager .securityPolicy.allowInvalidCertificates = YES;
|
||||
AFSecurityPolicy *securityPolicy= [AFSecurityPolicy defaultPolicy];
|
||||
mewRequesmanager .securityPolicy = securityPolicy;
|
||||
// 是否在证书域字段中验证域名
|
||||
[mewRequesmanager .securityPolicy setValidatesDomainName:NO];
|
||||
mewRequesmanager .responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/plain",@"image/jpeg",@"image/png", nil];
|
||||
mewRequesmanager .requestSerializer.timeoutInterval = 60;
|
||||
|
||||
});
|
||||
return mewRequesmanager;
|
||||
}
|
||||
+ (void)mewRequestGetAction:(NSString *)path
|
||||
dic:(NSDictionary *)dic
|
||||
successBlock:(void (^)(MewBaseModel *model))successBlock
|
||||
failBlock:(void (^)(NSInteger num, NSString *text))failBlock {
|
||||
|
||||
|
||||
|
||||
dic = [self mewSetParmars:dic];
|
||||
|
||||
|
||||
|
||||
[[MewOCServerManager share] GET:path parameters:dic headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
|
||||
MewBaseModel *obj = [MewBaseModel mewModelWithDictionary:responseObject];
|
||||
|
||||
successBlock(obj);
|
||||
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
|
||||
NSString * code = error.code ? [NSString stringWithFormat:@"%ld", error.code] : @"9999";
|
||||
NSString * des = error.description.length > 0 ? error.description : @"接口报错信息未知";
|
||||
failBlock(code.integerValue,des);
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)mewRequestPOSTAction:(NSString *)path
|
||||
dic:(NSDictionary *)dic
|
||||
successBlock:(void (^)(MewBaseModel *model))successBlock
|
||||
failBlock:(void (^)(NSInteger num, NSString *text))failBlock {
|
||||
dic = [self mewSetParmars:dic];
|
||||
[[MewOCServerManager share] POST:path parameters:dic headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
|
||||
MewBaseModel *obj = [MewBaseModel mewModelWithDictionary:responseObject];
|
||||
|
||||
successBlock(obj);
|
||||
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
|
||||
NSString * code = error.code ? [NSString stringWithFormat:@"%ld", error.code] : @"9999";
|
||||
NSString * des = error.description.length > 0 ? error.description : @"接口报错信息未知";
|
||||
failBlock(code.integerValue,des);
|
||||
}];
|
||||
}
|
||||
+ (void)mewSetHeadValue {
|
||||
AFHTTPSessionManager *Session = [MewOCServerManager share];
|
||||
if ([[MewSaveBaseUserModel share]mewGetUserId].length > 0) {
|
||||
[Session.requestSerializer setValue:[[MewSaveBaseUserModel share]mewGetUserId] forHTTPHeaderField:@"pub_uid"];
|
||||
} else {
|
||||
[Session.requestSerializer setValue:nil forHTTPHeaderField:@"pub_uid"];
|
||||
}
|
||||
if ([[MewSaveBaseUserModel share]mewUserTicket].length > 0) {
|
||||
[Session.requestSerializer setValue:[[MewSaveBaseUserModel share]mewUserTicket] forHTTPHeaderField:@"pub_ticket"];
|
||||
}else {
|
||||
[Session.requestSerializer setValue:nil forHTTPHeaderField:@"pub_ticket"];
|
||||
}
|
||||
}
|
||||
+ (NSDictionary*)mewSetParmars:(NSDictionary *)curParmars {
|
||||
[self mewSetHeadValue];
|
||||
NSMutableDictionary *parameter= [NSMutableDictionary dictionary];
|
||||
parameter[[MewEncryptManager mewAESDecryptText:@"+vPajLxpuvmaFpBH26XVkg=="]] = @"iOS";
|
||||
parameter[[MewEncryptManager mewAESDecryptText:@"e3uFgfA1DSaVUGVs97LpVw=="]] = [[UIDevice currentDevice]systemVersion];
|
||||
parameter[[MewEncryptManager mewAESDecryptText:@"uDuliQq7OrGAtXyx0P4Mgw=="]] = @2;
|
||||
parameter[[MewEncryptManager mewAESDecryptText:@"MFhlDl0azUC4ijdSjtfFMA=="]] = @1;
|
||||
parameter[[MewEncryptManager mewAESDecryptText:@"KnAW3pOjhIwI2KgYBdwZ1w=="]] = [MewEncryptManager mewAESDecryptText:@"atzdKXYSzyjNCQwb6+zhEE429CmSze6hoQ1a0rAMqV8="];
|
||||
parameter[[MewEncryptManager mewAESDecryptText:@"DZHjXki1EfFXxqGQ6DmraQ=="]] = [[UIDevice currentDevice] mewGetModelName];
|
||||
parameter[[MewEncryptManager mewAESDecryptText:@"bjj8oPzea/SQ7gWSikkEMA=="]] = [MewDevice mewGetUUID];
|
||||
parameter[[MewEncryptManager mewAESDecryptText:@"cqgmQC8kvWUUyNNtURTiJw=="]] = [NSBundle mainBundle].infoDictionary[@"CFBundleShortVersionString"];
|
||||
|
||||
if (!curParmars||![curParmars isKindOfClass:[NSDictionary class]]){
|
||||
NSMutableDictionary *getDic = [NSMutableDictionary dictionaryWithDictionary:parameter];
|
||||
return getDic;
|
||||
}
|
||||
NSMutableDictionary * dic = [NSMutableDictionary dictionaryWithDictionary:curParmars];
|
||||
for (NSString *key in parameter.allKeys) {
|
||||
[dic setObject:parameter[key] forKey:key];
|
||||
}
|
||||
return dic;
|
||||
}
|
||||
|
||||
|
||||
+ (void)mewRequestData:(NSString *)url type:(MewOCServerManagerType)type successBlock:(MewOCServerManagerSucceed)successBlock, ... {
|
||||
va_list list;
|
||||
va_start(list, successBlock);
|
||||
|
||||
// 获取第一个参数 __FUNCTION__ ,然后解析出来 key 。
|
||||
const char *name = va_arg(list, const char *);
|
||||
NSString *text = [[NSString alloc] initWithUTF8String:name];
|
||||
// NSLog 一下 __FUNCTION__ 就知道为什么这么截取了。
|
||||
NSRange range = [text rangeOfString:@":"];
|
||||
NSUInteger index = range.location + 1;
|
||||
NSUInteger count;
|
||||
if ((index + 2) < text.length) {
|
||||
count = text.length - index - 2;
|
||||
} else if ((index + 1) < text.length) {
|
||||
count = text.length - index - 1;
|
||||
} else {
|
||||
count = text.length - index;
|
||||
}
|
||||
|
||||
NSString *key = [text substringWithRange:NSMakeRange(index, count)];
|
||||
|
||||
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
|
||||
|
||||
NSArray *keys = [key componentsSeparatedByString:@":"];
|
||||
NSEnumerator *keyList = [keys objectEnumerator];
|
||||
NSString *value = nil;
|
||||
while((value = va_arg(list, NSString*))){
|
||||
|
||||
[dic setValue:value forKey:keyList.nextObject];
|
||||
};
|
||||
va_end(list);
|
||||
switch (type) {
|
||||
case MewOCServerManagerTypeGET: {
|
||||
[self mewRequestGetAction:url dic:dic successBlock:^(MewBaseModel *model) {
|
||||
if(successBlock){
|
||||
successBlock(model,model.code,model.message);
|
||||
}
|
||||
} failBlock:^(NSInteger num, NSString *text) {
|
||||
if(successBlock){
|
||||
successBlock(nil,num,text);
|
||||
}
|
||||
} ];
|
||||
}
|
||||
break;
|
||||
case MewOCServerManagerTypePOST:{
|
||||
[self mewRequestPOSTAction:url dic:dic successBlock:^(MewBaseModel *model) {
|
||||
if(successBlock){
|
||||
successBlock(model,model.code,model.message);
|
||||
}
|
||||
} failBlock:^(NSInteger num, NSString *text) {
|
||||
if(successBlock){
|
||||
successBlock(nil,num,text);
|
||||
}
|
||||
}];
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+ (void)mewRequestToken:(MewOCServerManagerSucceed)successBlock access_token:(NSString *)accessToken issue_type:(NSString *)issueType {
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"G0vRJk+lM7aIFJdrDs1Xhg=="] type:MewOCServerManagerTypePOST successBlock:successBlock,__FUNCTION__,accessToken, issueType, nil];
|
||||
}
|
||||
+ (void)mewRequestInitInfo:(MewOCServerManagerSucceed)successBlock{
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"B0VaK5AAEVj2lGQmh7fdkg=="] type:MewOCServerManagerTypeGET successBlock:successBlock,__FUNCTION__,nil];
|
||||
}
|
||||
+ (void)mewRequestMainHomeGameTabList:(MewOCServerManagerSucceed)successBlock{
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"p6hShsDD1gduNfxvLDh40fGXNIVVYidusuyiqLoiE2E="] type:MewOCServerManagerTypeGET successBlock:successBlock,__FUNCTION__,nil];
|
||||
}
|
||||
+ (void)mewRequestMainHomeNewFriendList:(MewOCServerManagerSucceed)successBlock gender:(NSString *)gender gameId:(NSString *)gameId{
|
||||
NSMutableDictionary * dic = [NSMutableDictionary dictionary];
|
||||
if(gender != nil){
|
||||
[dic setObject:gender forKey:@"gender"];
|
||||
}
|
||||
if(gameId != nil){
|
||||
[dic setObject:gameId forKey:@"gameId"];
|
||||
}
|
||||
|
||||
[self mewRequestGetAction:[MewEncryptManager mewAESDecryptText:@"snLITcKwwnlRGbuT+0t3Gw=="] dic:dic successBlock:^(MewBaseModel *model) {
|
||||
if(successBlock){
|
||||
successBlock(model,model.code,model.message);
|
||||
}
|
||||
} failBlock:^(NSInteger num, NSString *text) {
|
||||
if(successBlock){
|
||||
successBlock(nil,num,text);
|
||||
}
|
||||
} ];
|
||||
|
||||
}
|
||||
|
||||
+ (void)mewRequestRandomFindFriendList:(MewOCServerManagerSucceed)successBlock gender:(NSString *)gender{
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"ZnqkAkDTTXWcnvwqETmxzC3fgpK+OuH3kRHkQFI0HyM="] type:MewOCServerManagerTypeGET successBlock:successBlock,__FUNCTION__,gender,nil];
|
||||
}
|
||||
+ (void)mewRequestUploadPhotoToken:(MewOCServerManagerSucceed)successBlock {
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"V5gbqkWkuc4Fvzj9mYj/hBeoD5CULsPTsiK8Z8GieqY="] type:MewOCServerManagerTypeGET successBlock:successBlock,__FUNCTION__,nil];
|
||||
}
|
||||
+ (void)mewUploadPhotoAction:(NSString *)path
|
||||
name:(NSString *)name
|
||||
token:(NSString *)token
|
||||
successBlock:(void (^)(NSString *key, NSDictionary *res))successBlock
|
||||
failureBlock:(void (^)(NSNumber *code, NSString *message))failureBlock{
|
||||
QNConfiguration *configuration = [QNConfiguration build:^(QNConfigurationBuilder *builder) {
|
||||
builder.zone = [QNFixedZone zone2];
|
||||
}];
|
||||
QNUploadManager *tool = [[QNUploadManager alloc] initWithConfiguration:configuration];
|
||||
[tool putFile:path key:name token:token complete:^(QNResponseInfo *info, NSString *key, NSDictionary *res) {
|
||||
if (res) {
|
||||
successBlock(key, res);
|
||||
} else {
|
||||
failureBlock(@(info.statusCode), info.error.localizedDescription);
|
||||
}
|
||||
} option:nil];
|
||||
}
|
||||
|
||||
+ (void)mewPublishSoundInfo:(MewOCServerManagerSucceed)successBlock dura:(NSString *)dura desc:(NSString *)desc gender:(NSString *)gender url:(NSString *)url{
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"VmR16aLR6D6MhSh4o1qFSc6g1dXX7LC9v9YRqDn/UZA="] type:MewOCServerManagerTypePOST successBlock:successBlock,__FUNCTION__,dura,desc,gender,url,nil];
|
||||
}
|
||||
+ (void)mewGetCollectRoomListData:(MewOCServerManagerSucceed)successBlock uid:(NSString *)uid page:(NSString *)page pageSize:(NSString *)pageSize roomType:(NSString *)roomType{
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"xbrIaF3tjG37mRyRC97ZrffhHg2YaksxPephr1wGtYI="] type:MewOCServerManagerTypeGET successBlock:successBlock,__FUNCTION__,uid,page,pageSize,roomType,nil];
|
||||
}
|
||||
+ (void)mewLogout:(MewOCServerManagerSucceed)successBlock auaccess_token:(NSString *)access_token {
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"73cfDtRGGthZvJUN7DktoA=="] type:MewOCServerManagerTypePOST successBlock:successBlock,__FUNCTION__,access_token,nil];
|
||||
}
|
||||
+ (void)mewGetDetailData:(MewOCServerManagerSucceed)successBlock uid:(NSString *)uid page:(NSString *)page pageSize:(NSString *)pageSize{
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"W7uzbHnGUU1RiDHmTvViGQ=="] type:MewOCServerManagerTypeGET successBlock:successBlock,__FUNCTION__,uid,page,pageSize,nil];
|
||||
}
|
||||
|
||||
+ (void)mewLikeUsr:(MewOCServerManagerSucceed)successBlock uid:(NSString *)uid likedUid:(NSString *)likedUid ticket:(NSString *)ticket type:(NSString *)type{
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"atxkzRc+U9YS4UOIpECXlw=="] type:MewOCServerManagerTypePOST successBlock:successBlock,__FUNCTION__,uid,likedUid,ticket,type,nil];
|
||||
}
|
||||
+ (void)mewGetListStatus:(MewOCServerManagerSucceed)successBlock uid:(NSString *)uid isLikeUid:(NSString *)isLikeUid {
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"2D8AkLpUg8cU9aQTxO+Mmw=="] type:MewOCServerManagerTypeGET successBlock:successBlock,__FUNCTION__,uid,isLikeUid,nil];
|
||||
}
|
||||
+ (void)mewGetLikeListInfo:(MewOCServerManagerSucceed)successBlock uid:(NSString *)uid pageNo:(NSString *)pageNo pageSize:(NSString *)pageSize {
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"INF19c+8RN4ef4v8DIWwJQ=="] type:MewOCServerManagerTypeGET successBlock:successBlock,__FUNCTION__,uid,pageNo,pageSize,nil];
|
||||
}
|
||||
+ (void)mewGetPayDataList:(MewOCServerManagerSucceed)successBlock channelType:(NSString *)channelType {
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"tJGng+8YSnwgwk5S0i5New=="] type:MewOCServerManagerTypeGET successBlock:successBlock,__FUNCTION__,channelType,nil];
|
||||
}
|
||||
+ (void)mewPayAction:(MewOCServerManagerSucceed)successBlock
|
||||
chargeProdId:(NSString *)chargeProdId
|
||||
uid:(NSString *)uid
|
||||
ticket:(NSString *)ticket
|
||||
deviceInfo:(NSString *)deviceInfo
|
||||
clientIp:(NSString *)clientIp{
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"bwrNIwSuCtX9ebT29xed93rJaaaSsuxrTFso6OAppms="] type:MewOCServerManagerTypePOST successBlock:successBlock,__FUNCTION__,chargeProdId,uid,ticket,deviceInfo,clientIp,nil];
|
||||
}
|
||||
+ (void)mewGetPayOrderState:(MewOCServerManagerSucceed)successBlock chooseEnv:(NSString *)chooseEnv chargeRecordId:(NSString *)chargeRecordId transcationId:(NSString *)transcationId uid:(NSString *)uid ticket:(NSString *)ticket{
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"10iACYRNJ/Q7R019Q4DRNFPf0nODacTzggh6x9bvmOw="] type:MewOCServerManagerTypePOST successBlock:successBlock,__FUNCTION__,chooseEnv,chargeRecordId,transcationId,uid,ticket,nil];
|
||||
}
|
||||
+ (void)mewSetLoginPasswordAction:(MewOCServerManagerSucceed)successBlock phone:(NSString *)phone newPwd:(NSString *)newPwd{
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"EHh/18eezsUFPDyLjSNBRA=="] type:MewOCServerManagerTypePOST successBlock:successBlock,__FUNCTION__,phone,newPwd,nil];
|
||||
}
|
||||
+ (void)mewChangeLoginPassword:(MewOCServerManagerSucceed)successBlock phone:(NSString *)phone newPwd:(NSString *)newPwd pwd:(NSString *)pwd{
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"eI/SwohmpNub6JQaD8dWIA=="] type:MewOCServerManagerTypePOST successBlock:successBlock,__FUNCTION__,phone,newPwd,pwd,nil];
|
||||
}
|
||||
+ (void)mewLoginAppWithCode:(MewOCServerManagerSucceed)successBlock
|
||||
phone:(NSString *)phone
|
||||
code:(NSString *)code
|
||||
client_secret:(NSString *)client_secret
|
||||
version:(NSString *)version
|
||||
client_id:(NSString *)client_id
|
||||
grant_type:(NSString *)grant_type{
|
||||
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"QFgInRYQSkXdbIyvBsVUvA=="] type:MewOCServerManagerTypePOST successBlock:successBlock,__FUNCTION__,phone,code,client_secret,version,client_id,grant_type,nil];
|
||||
|
||||
}
|
||||
|
||||
+ (void)mewLoginAppWithPassword:(MewOCServerManagerSucceed)successBlock phone:(NSString *)phone password:(NSString *)password client_secret:(NSString *)client_secret version:(NSString *)version client_id:(NSString *)client_id grant_type:(NSString *)grant_type {
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"QFgInRYQSkXdbIyvBsVUvA=="] type:MewOCServerManagerTypePOST successBlock:successBlock,__FUNCTION__,phone,password,client_secret,version,client_id,grant_type,nil];
|
||||
}
|
||||
+ (void)mewAgainSetPassword:(MewOCServerManagerSucceed)successBlock phone:(NSString *)phone newPwd:(NSString *)newPwd{
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"ZstXKg9XrXuRUPW6jNgkzQ=="] type:MewOCServerManagerTypePOST successBlock:successBlock,__FUNCTION__,phone,newPwd,nil];
|
||||
}
|
||||
+ (void)mewAppleLogin:(MewOCServerManagerSucceed)successBlock openid:(NSString *)openid unionid:(NSString *)unionid access_token:(NSString *)access_token type:(NSString *)type{
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"jenVNOO6MbwSC77wnPIMng=="] type:MewOCServerManagerTypePOST successBlock:successBlock,__FUNCTION__,openid,unionid,access_token,type,nil];
|
||||
}
|
||||
+ (void)mewGetUserNick:(MewOCServerManagerSucceed)successBlock{
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"7oWMT+wxmM3FF/aCDKLrRw=="] type:MewOCServerManagerTypePOST successBlock:successBlock,__FUNCTION__,nil];
|
||||
}
|
||||
|
||||
+ (void)mewSetUserPhoneInfo:(MewOCServerManagerSucceed)successBlock
|
||||
phone:(NSString *)phone
|
||||
code:(NSString *)code
|
||||
ticket:(NSString *)ticket{
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"l+R2IRWIqi9yPiDc6rg+jg=="] type:MewOCServerManagerTypePOST successBlock:successBlock,__FUNCTION__,phone,code,ticket,nil];
|
||||
}
|
||||
+ (void)mewGetUserDataWithUid:(MewOCServerManagerSucceed)successBlock uid:(NSString *)uid{
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"KEMxFkjgYfZuaj0tYsUeqQ=="] type:MewOCServerManagerTypeGET successBlock:successBlock,__FUNCTION__,uid,nil];
|
||||
}
|
||||
+ (void)mewGetPhoneAuthCode:(MewOCServerManagerSucceed)successBlock mobile:(NSString *)mobile type:(NSString *)type{
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"2Hx71goXCYG6r1fVVkSHsA=="] type:MewOCServerManagerTypePOST successBlock:successBlock,__FUNCTION__,mobile,type,nil];
|
||||
}
|
||||
+ (void)mewSetUserDataWithRegister:(MewOCServerManagerSucceed)successBlock
|
||||
userInfo:(NSDictionary *)userInfo{
|
||||
|
||||
[self mewRequestPOSTAction:[MewEncryptManager mewAESDecryptText:@"6A7+MXSz6a7RbsOb9Ls+mA=="] dic:userInfo successBlock:^(MewBaseModel *model) {
|
||||
if(successBlock){
|
||||
successBlock(model,model.code,model.message);
|
||||
}
|
||||
} failBlock:^(NSInteger num, NSString *text) {
|
||||
if(successBlock){
|
||||
successBlock(nil,num,text);
|
||||
}
|
||||
} ];
|
||||
}
|
||||
+ (void)mewGetDiamondCount:(MewOCServerManagerSucceed)successBlock
|
||||
uid:(NSString *)uid
|
||||
ticket:(NSString *)ticket{
|
||||
[MewOCServerManager mewRequestData:[MewEncryptManager mewAESDecryptText:@"7xFYk5dOEOCLb2Sfp0mwZw=="] type:MewOCServerManagerTypeGET successBlock:successBlock,__FUNCTION__,uid,ticket,nil];
|
||||
}
|
||||
@end
|
@@ -91,7 +91,7 @@ extension MewServerApi:TargetType{
|
||||
mewGetParams["netType"] = 2
|
||||
mewGetParams["ispType"] = 1
|
||||
mewGetParams["channel"] = "yinmeng_appstore"
|
||||
mewGetParams["model"] = UIDevice.current.modelName
|
||||
mewGetParams["model"] = UIDevice.current.mewGetModelName
|
||||
mewGetParams["deviceId"] = MewDevice.mewGetUUID()
|
||||
mewGetParams["appVersion"] = Bundle.main.infoDictionary?["CFBundleShortVersionString"]
|
||||
mewGetParams["app"] = "yinmeng"
|
||||
@@ -107,11 +107,11 @@ extension MewServerApi:TargetType{
|
||||
|
||||
public var headers: [String : String]? {
|
||||
var mewHeader: [String: String] = [:]
|
||||
if MewAccountInfoStorage.instance().mew_getUid().count > 0{
|
||||
mewHeader["pub_uid"] = MewAccountInfoStorage.instance().mew_getUid()
|
||||
if MewSaveBaseUserModel.share().mewGetUserId().count > 0{
|
||||
mewHeader["pub_uid"] = MewSaveBaseUserModel.share().mewGetUserId()
|
||||
}
|
||||
if MewAccountInfoStorage.instance().mew_getTicket().count > 0{
|
||||
mewHeader["pub_ticket"] = MewAccountInfoStorage.instance().mew_getTicket()
|
||||
if MewSaveBaseUserModel.share().mewUserTicket().count > 0{
|
||||
mewHeader["pub_ticket"] = MewSaveBaseUserModel.share().mewUserTicket()
|
||||
}
|
||||
return mewHeader
|
||||
}
|
||||
@@ -121,7 +121,7 @@ extension MewServerApi:TargetType{
|
||||
|
||||
|
||||
extension UIDevice {
|
||||
var modelName: String {
|
||||
@objc public var mewGetModelName: String {
|
||||
var systemInfo = utsname()
|
||||
uname(&systemInfo)
|
||||
let machineMirror = Mirror(reflecting: systemInfo.machine)
|
||||
|
@@ -3,13 +3,12 @@
|
||||
//
|
||||
|
||||
|
||||
#import "MewMvpViewController.h"
|
||||
#import "MewServerBaseApi.h"
|
||||
|
||||
#import "MewEncryptManager.h"
|
||||
#import "MewAccountInfoStorage.h"
|
||||
|
||||
#import "YYReachability.h"
|
||||
#import "SSKeychain.h"
|
||||
|
||||
#import "MewSaveBaseUserModel.h"
|
||||
#import <MJExtension/MJExtension.h>
|
||||
#import "MewHUDTool.h"
|
||||
#import "MewMacro.h"
|
||||
@@ -25,7 +24,7 @@
|
||||
#import <SDImageCache.h>
|
||||
#import "MewMsgDataModel.h"
|
||||
#import "MewWebViewController.h"
|
||||
|
||||
#import "MewOCServerManager.h"
|
||||
#import <TXLiteAVSDK_TRTC/TRTCCloud.h>
|
||||
#import "MewAttachmentModel.h"
|
||||
#import "MewConstant.h"
|
||||
|
@@ -10,16 +10,16 @@
|
||||
|
||||
|
||||
#import <Masonry/Masonry.h>
|
||||
#import "NetImageView.h"
|
||||
#import "MewMacro.h"
|
||||
#import "MewEncryptManager.h"
|
||||
#import "MewServerBaseApi.h"
|
||||
#import "yinmeng_ios-Swift.h"
|
||||
#import "NSArray+MewSafe.h"
|
||||
|
||||
#import "MewThemeColor.h"
|
||||
#import "MewUserInfoModel.h"
|
||||
#import "NSMutableDictionary+MEWSafe.h"
|
||||
|
||||
#import "MewBaseNavigationController.h"
|
||||
#import "UIButton+MewEnlargeTouchArea.h"
|
||||
#import "UIButton+MewSetButtomArea.h"
|
||||
#import "MewBaseModel.h"
|
||||
#import "MewSaveBaseUserModel.h"
|
||||
#import "MewOCServerManager.h"
|
||||
#endif /* MewHeader_h */
|
||||
|
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// MewSaveBaseUserModel.h
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2024/1/19.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MewAccountModel.h"
|
||||
#import "MewThirdUserInfo.h"
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MewSaveBaseUserModel : NSObject
|
||||
|
||||
///如果是第三方登录的话 保存一下用户信息
|
||||
@property (nonatomic,strong) MewThirdUserInfo *mewAppleInfo;
|
||||
+ (MewSaveBaseUserModel *)share;
|
||||
-(MewAccountModel *)mewGetBaseUserData;
|
||||
-(void)mewSaveBaseUserData:(MewAccountModel *_Nullable)model;
|
||||
- (void)mewSaveUserTickets:(NSString *_Nullable)tickets;
|
||||
- (NSString *)mewUserTicket;
|
||||
- (NSString *)mewGetUserId;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// MewSaveBaseUserModel.m
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2024/1/19.
|
||||
//
|
||||
|
||||
#import "MewSaveBaseUserModel.h"
|
||||
#import "MewAccountModel.h"
|
||||
|
||||
@interface MewSaveBaseUserModel()
|
||||
@property (nonatomic, copy) NSString *mewPrivateUserTicket;
|
||||
@property (nonatomic, strong) MewAccountModel *mewUserData;
|
||||
@end
|
||||
@implementation MewSaveBaseUserModel
|
||||
static MewSaveBaseUserModel *_user = nil;
|
||||
|
||||
+ (MewSaveBaseUserModel *)share {
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
|
||||
dispatch_once(&onceToken, ^{
|
||||
_user = [[self alloc] init];
|
||||
}) ;
|
||||
|
||||
return _user;
|
||||
}
|
||||
-(MewAccountModel *)mewGetBaseUserData{
|
||||
NSDictionary *dic = [[NSUserDefaults standardUserDefaults]valueForKey:@"kMewSaveBaseUserModel"];
|
||||
if(dic == nil)return nil;
|
||||
MewAccountModel *model = [MewAccountModel mewModelWithDictionary:dic];
|
||||
return model;
|
||||
}
|
||||
-(void)mewSaveBaseUserData:(MewAccountModel *_Nullable)model{
|
||||
if(model == nil){
|
||||
model = [MewAccountModel new];
|
||||
}
|
||||
self.mewUserData = model;
|
||||
NSDictionary *dic = [model mewModel2dictionary];
|
||||
[[NSUserDefaults standardUserDefaults]setValue:dic forKey:@"kMewSaveBaseUserModel"];
|
||||
[[NSUserDefaults standardUserDefaults]synchronize];
|
||||
}
|
||||
- (void)mewSaveUserTickets:(NSString *_Nullable)tickets{
|
||||
self.mewPrivateUserTicket = tickets;
|
||||
}
|
||||
- (NSString *)mewUserTicket{
|
||||
if(self.mewPrivateUserTicket == nil){
|
||||
return @"";
|
||||
}
|
||||
return self.mewPrivateUserTicket;
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)mewGetUserId {
|
||||
MewAccountModel *user = [self mewGetBaseUserData];
|
||||
if (user == nil) {
|
||||
return @"";
|
||||
}
|
||||
return user.uid;
|
||||
}
|
||||
@end
|
@@ -1,53 +0,0 @@
|
||||
//
|
||||
// MewHttpRequestHelper.h
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/5.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MewBaseModel.h"
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef NS_ENUM(NSUInteger, MewHttpRequestHelperMethod) {
|
||||
MewHttpRequestHelperMethodPOST,
|
||||
MewHttpRequestHelperMethodGET,
|
||||
MewHttpRequestHelperMethodDELETE
|
||||
};
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
typedef void(^MewHttpRequestHelperCompletion)(MewBaseModel* data, NSInteger code, NSString * msg);
|
||||
|
||||
@interface MewHttpRequestHelper : NSObject
|
||||
|
||||
/// 配置公参
|
||||
+ (NSDictionary*)mew_configBaseParmars:(NSDictionary *)parmars;
|
||||
|
||||
+ (void)GET:(NSString *)method
|
||||
params:(NSDictionary *)params
|
||||
success:(void (^)(MewBaseModel *data))success
|
||||
failure:(void (^)(NSInteger resCode, NSString *message))failure;
|
||||
|
||||
+ (void)POST:(NSString *)method
|
||||
params:(NSDictionary *)params
|
||||
success:(void (^)(MewBaseModel *data))success
|
||||
failure:(void (^)(NSInteger resCode, NSString *message))failure;
|
||||
|
||||
+ (void)DELETE:(NSString *)method
|
||||
params:(NSDictionary *)params
|
||||
success:(void (^)(MewBaseModel *data))success
|
||||
failure:(void (^)(NSInteger resCode, NSString *message))failure;
|
||||
|
||||
+ (void)request:(NSString *)url
|
||||
method:(MewHttpRequestHelperMethod)method
|
||||
params:(NSDictionary *)params
|
||||
success:(void (^)(MewBaseModel *data))success
|
||||
failure:(void (^)(NSInteger resCode, NSString *message))failure;
|
||||
|
||||
+ (void)request:(NSString *)path
|
||||
method:(MewHttpRequestHelperMethod)method
|
||||
params:(NSDictionary *)params
|
||||
completion:(MewHttpRequestHelperCompletion)completion;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,266 +0,0 @@
|
||||
//
|
||||
// MewHttpRequestHelper.m
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/5.
|
||||
//
|
||||
|
||||
#import "MewHttpRequestHelper.h"
|
||||
#import "NSObject+MEWExtension.h"
|
||||
#import <AFNetworking.h>
|
||||
|
||||
#import "MewStackManager.h"
|
||||
#import "MewAccountInfoStorage.h"
|
||||
|
||||
#import "MewUtility.h"
|
||||
#import "YYReachability.h"
|
||||
|
||||
@implementation MewHttpRequestHelper
|
||||
|
||||
static BOOL isShowing = NO;
|
||||
|
||||
+ (AFHTTPSessionManager *)requestManager {
|
||||
|
||||
static AFHTTPSessionManager *manager = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSString *url ;
|
||||
#ifdef DEBUG
|
||||
url = [MewEncryptManager mewAESDecryptText:Mew_Server_API_Base_URL];
|
||||
#else
|
||||
url = Mew_Server_API_Base_URL;
|
||||
#endif
|
||||
manager = [[AFHTTPSessionManager manager]initWithBaseURL:[NSURL URLWithString:url]];
|
||||
manager.responseSerializer = [AFJSONResponseSerializer serializer];
|
||||
manager.requestSerializer.HTTPShouldHandleCookies = YES;
|
||||
// 客户端是否信任非法证书
|
||||
manager.securityPolicy.allowInvalidCertificates = YES;
|
||||
AFSecurityPolicy *securityPolicy= [AFSecurityPolicy defaultPolicy];
|
||||
manager.securityPolicy = securityPolicy;
|
||||
// 是否在证书域字段中验证域名
|
||||
[manager.securityPolicy setValidatesDomainName:NO];
|
||||
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/plain",@"image/jpeg",@"image/png", nil];
|
||||
manager.requestSerializer.timeoutInterval = 60;
|
||||
});
|
||||
return manager;
|
||||
}
|
||||
|
||||
+ (void)mew_showNoNetAlert {
|
||||
if (isShowing == NO) {
|
||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"请检查网络配置或确定设备是否联网" preferredStyle:UIAlertControllerStyleAlert];
|
||||
[alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
|
||||
isShowing = NO;
|
||||
}]];
|
||||
[alert addAction:[UIAlertAction actionWithTitle:@"设置" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
|
||||
isShowing = NO;
|
||||
NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
|
||||
if ([[UIApplication sharedApplication] canOpenURL:url]) {
|
||||
[[UIApplication sharedApplication] openURL:url options:nil completionHandler:^(BOOL success) {
|
||||
|
||||
}];
|
||||
}
|
||||
}]];
|
||||
[[MewStackManager shareManager].mew_getCurrentVC presentViewController:alert animated:YES completion:nil];
|
||||
isShowing = YES;
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)GET:(NSString *)method
|
||||
params:(NSDictionary *)params
|
||||
success:(void (^)(MewBaseModel *data))success
|
||||
failure:(void (^)(NSInteger resCode, NSString *message))failure {
|
||||
if ([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus == 0) {
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
[self mew_showNoNetAlert];
|
||||
failure(-1, @"请检查网络连接。");
|
||||
NSException * extrion= [NSException exceptionWithName:method reason:@"接口没有网络" userInfo:nil];
|
||||
NSLog(@"extrion - %@",extrion);
|
||||
// [Bugly reportException:extrion];
|
||||
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
[self configHeaders];
|
||||
params = [self mew_configBaseParmars:params];
|
||||
#ifdef DEBUG
|
||||
NSLog(@"\nmethod:\n%@\nparameter:\n%@", method, params);
|
||||
#endif
|
||||
|
||||
AFHTTPSessionManager *manager = [MewHttpRequestHelper requestManager];
|
||||
[manager GET:method parameters:params headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
|
||||
MewBaseModel *baseModel = [MewBaseModel mewModelWithDictionary:responseObject];
|
||||
#ifdef DEBUG
|
||||
NSLog(@"\n%@", [MewBaseModel mewToJSONString]);
|
||||
#endif
|
||||
success(baseModel);
|
||||
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
|
||||
[self mew_handleNetError:error method:method failure:failure];
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)POST:(NSString *)method
|
||||
params:(NSDictionary *)params
|
||||
success:(void (^)(MewBaseModel *data))success
|
||||
failure:(void (^)(NSInteger resCode, NSString *message))failure {
|
||||
if ([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus == 0) {
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
failure(-1, @"请检查网络连接。");
|
||||
NSException * extrion= [NSException exceptionWithName:method reason:@"接口没有网络" userInfo:nil];
|
||||
NSLog(@"extrion - %@",extrion);
|
||||
// [Bugly reportException:extrion];
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
[self configHeaders];
|
||||
params = [self mew_configBaseParmars:params];
|
||||
#ifdef DEBUG
|
||||
NSLog(@"\nmethod:\n%@\nparameter:\n%@", method, params);
|
||||
#endif
|
||||
|
||||
AFHTTPSessionManager *manager = [MewHttpRequestHelper requestManager];
|
||||
[manager POST:method parameters:params headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
|
||||
MewBaseModel *baseModel = [MewBaseModel mewModelWithDictionary:responseObject];
|
||||
#ifdef DEBUG
|
||||
NSLog(@"\n%@", [baseModel mewToJSONString]);
|
||||
#endif
|
||||
success(baseModel);
|
||||
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
|
||||
[self mew_handleNetError:error method:method failure:failure];
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)DELETE:(NSString *)method
|
||||
params:(NSDictionary *)params
|
||||
success:(void (^)(MewBaseModel *data))success
|
||||
failure:(void (^)(NSInteger resCode, NSString *message))failure {
|
||||
if ([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus == 0) {
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
failure(-1, @"请检查网络连接。");
|
||||
NSException * extrion= [NSException exceptionWithName:method reason:@"接口没有网络" userInfo:nil];
|
||||
NSLog(@"extrion - %@",extrion);
|
||||
// [Bugly reportException:extrion];
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
[self configHeaders];
|
||||
params = [self mew_configBaseParmars:params];
|
||||
#ifdef DEBUG
|
||||
NSLog(@"\nmethod:\n%@\nparameter:\n%@", method, params);
|
||||
#endif
|
||||
|
||||
AFHTTPSessionManager *manager = [MewHttpRequestHelper requestManager];
|
||||
[manager DELETE:method parameters:params headers:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
|
||||
MewBaseModel *baseModel = [MewBaseModel mewModelWithDictionary:responseObject];
|
||||
#ifdef DEBUG
|
||||
NSLog(@"\n%@", [baseModel mewToJSONString]);
|
||||
#endif
|
||||
success(baseModel);
|
||||
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
|
||||
[self mew_handleNetError:error method:method failure:failure];
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)request:(NSString *)url
|
||||
method:(MewHttpRequestHelperMethod)method
|
||||
params:(NSDictionary *)params
|
||||
success:(void (^)(MewBaseModel *data))success
|
||||
failure:(void (^)(NSInteger resCode, NSString *message))failure {
|
||||
switch (method) {
|
||||
case MewHttpRequestHelperMethodGET: {
|
||||
[self GET:url params:params success:success failure:failure];
|
||||
}
|
||||
break;
|
||||
case MewHttpRequestHelperMethodPOST:{
|
||||
[self POST:url params:params success:success failure:failure];
|
||||
}
|
||||
break;
|
||||
case MewHttpRequestHelperMethodDELETE:{
|
||||
[self DELETE:url params:params success:success failure:failure];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)request:(NSString *)path
|
||||
method:(MewHttpRequestHelperMethod)method
|
||||
params:(NSDictionary *)params
|
||||
completion:(MewHttpRequestHelperCompletion)completion {
|
||||
[self request:path method:method params:params success:^(MewBaseModel *data) {
|
||||
if (completion) {
|
||||
completion(data, data.code, data.message);
|
||||
}
|
||||
} failure:^(NSInteger resCode, NSString *message) {
|
||||
if (completion) {
|
||||
completion(nil, resCode, message);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)configHeaders {
|
||||
AFHTTPSessionManager *client = [MewHttpRequestHelper requestManager];
|
||||
if ([[MewAccountInfoStorage instance] mew_getUid].length > 0) {
|
||||
[client.requestSerializer setValue:[[MewAccountInfoStorage instance] mew_getUid] forHTTPHeaderField:@"pub_uid"];
|
||||
} else {
|
||||
[client.requestSerializer setValue:nil forHTTPHeaderField:@"pub_uid"];
|
||||
}
|
||||
if ([[MewAccountInfoStorage instance] mew_getTicket].length > 0) {
|
||||
[client.requestSerializer setValue:[[MewAccountInfoStorage instance] mew_getTicket] forHTTPHeaderField:@"pub_ticket"];
|
||||
}else {
|
||||
[client.requestSerializer setValue:nil forHTTPHeaderField:@"pub_ticket"];
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSDictionary*)mew_configBaseParmars:(NSDictionary *)parmars {
|
||||
NSDictionary *defaultBasciParame = @{
|
||||
@"os" : @"iOS",
|
||||
@"osVersion" : [MewUtility systemVersion],
|
||||
@"netType" : ([MewUtility networkStatus] == ReachableViaWiFi) ? @2 : @1,
|
||||
@"ispType" : @([MewUtility carrierIdentifier]),
|
||||
@"channel" : [MewUtility getAppSource] ? : @"",
|
||||
@"model" : [MewUtility modelName],
|
||||
@"deviceId" : [MewUtility deviceUniqueIdentification],
|
||||
@"appVersion" : [MewUtility appVersion],
|
||||
@"app" : [MewUtility appName]
|
||||
};
|
||||
if (!parmars||![parmars isKindOfClass:[NSDictionary class]]){
|
||||
NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:defaultBasciParame];
|
||||
return dic;
|
||||
}
|
||||
NSMutableDictionary * dic = [NSMutableDictionary dictionaryWithDictionary:parmars];
|
||||
for (NSString *parameKey in defaultBasciParame.allKeys) {
|
||||
[dic setObject:defaultBasciParame[parameKey] forKey:parameKey];
|
||||
}
|
||||
return dic;
|
||||
}
|
||||
|
||||
+ (void)mew_handleNetError:(NSError *)error method:(NSString *)method
|
||||
failure:(void (^)(NSInteger resCode, NSString *message))failure
|
||||
{
|
||||
#ifdef DEBUG
|
||||
NSLog(@"\n%@", error);
|
||||
#endif
|
||||
// 别问,反正 oauth/ticket 接口要通过这种方式取错误码。
|
||||
NSHTTPURLResponse *response = error.userInfo[@"com.alamofire.serialization.response.error.response"];
|
||||
if (response && response.statusCode == 401) {
|
||||
failure(response.statusCode, @"登录已过期。");
|
||||
} else {
|
||||
|
||||
if (error.code == -1009 || error.code == -1001 || error.code == -1004 || error.code == -1003 || error.code == -1002 || error.code == 3840) {
|
||||
failure(error.code, @"");
|
||||
} else {
|
||||
failure(error.code, error.localizedDescription.length > 0 ? error.localizedDescription : @"大鹅开小差中~请稍后再试");
|
||||
}
|
||||
NSString * code = error.code ? [NSString stringWithFormat:@"%ld", error.code] : @"9999";
|
||||
NSString * des = error.description.length > 0 ? error.description : @"接口报错信息未知";
|
||||
NSException *exception = [NSException exceptionWithName:@"229181"
|
||||
reason:method
|
||||
userInfo:@{@"code":code, @"desc":des}];
|
||||
NSLog(@" exception - %@",exception);
|
||||
// [Bugly reportException:exception];
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
@@ -1,24 +0,0 @@
|
||||
//
|
||||
// MewServerBaseApi.h
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2024/1/15.
|
||||
//
|
||||
|
||||
#ifndef MewServerBaseApi_h
|
||||
#define MewServerBaseApi_h
|
||||
|
||||
#ifdef DEBUG
|
||||
/// http://beta.h5.ymlive.fun
|
||||
#define Mew_Server_API_Base_H5_URL @"GoK87pcrCtMGRUiI37dI/jjoKPw7cA0hRRBRFdEmwbY="
|
||||
/// http://beta.api.ymlive.fun
|
||||
#define Mew_Server_API_Base_URL @"699gQF4rRYIwztF2zlUunGDlDP2GdDcO5MWptrXUmgU="
|
||||
|
||||
#else
|
||||
/// http://h5.ymlive.fun
|
||||
#define Mew_Server_API_Base_H5_URL @"https://h5.ymlive.fun"
|
||||
|
||||
/// https://api.ymlive.fun
|
||||
#define Mew_Server_API_Base_URL @"https://api.ymlive.fun"
|
||||
#endif
|
||||
#endif /* MewServerBaseApi_h */
|
@@ -1,27 +0,0 @@
|
||||
//
|
||||
// MEWUploadFile.h
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/1.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MEWUploadFile : NSObject
|
||||
/// 上传一个文件
|
||||
/// @param filePath 文件地址
|
||||
/// @param fileName 文件的名字
|
||||
/// @param token token
|
||||
/// @param success 成功
|
||||
/// @param failure 失败
|
||||
+ (void)mewUploadFile:(NSString *)filePath
|
||||
named:(NSString *)fileName
|
||||
token:(NSString *)token
|
||||
success:(void (^)(NSString *key, NSDictionary *res))success
|
||||
failure:(void (^)(NSNumber *code, NSString *message))failure;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,34 +0,0 @@
|
||||
//
|
||||
// MEWUploadFile.m
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/1.
|
||||
//
|
||||
|
||||
#import "MEWUploadFile.h"
|
||||
#import <Qiniu/QiniuSDK.h>
|
||||
@implementation MEWUploadFile
|
||||
/// 上传一个文件
|
||||
/// @param filePath 文件地址
|
||||
/// @param fileName 文件的名字
|
||||
/// @param token token
|
||||
/// @param success 成功
|
||||
/// @param failure 失败
|
||||
+ (void)mewUploadFile:(NSString *)filePath
|
||||
named:(NSString *)fileName
|
||||
token:(NSString *)token
|
||||
success:(void (^)(NSString *key, NSDictionary *res))success
|
||||
failure:(void (^)(NSNumber *code, NSString *message))failure{
|
||||
QNConfiguration *config = [QNConfiguration build:^(QNConfigurationBuilder *builder) {
|
||||
builder.zone = [QNFixedZone zone2];
|
||||
}];
|
||||
QNUploadManager *upManager = [[QNUploadManager alloc] initWithConfiguration:config];
|
||||
[upManager putFile:filePath key:fileName token:token complete:^(QNResponseInfo *info, NSString *key, NSDictionary *res) {
|
||||
if (res) {
|
||||
success(key, res);
|
||||
} else {
|
||||
failure(@(info.statusCode), info.error.localizedDescription);
|
||||
}
|
||||
} option:nil];
|
||||
}
|
||||
@end
|
@@ -1,10 +0,0 @@
|
||||
//
|
||||
// MewGCDHelper.h
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/1.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
void mew_dispatch_main_sync_safe(dispatch_block_t block);
|
@@ -1,16 +0,0 @@
|
||||
//
|
||||
// MewGCDHelper.m
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/1.
|
||||
//
|
||||
|
||||
#import "MewGCDHelper.h"
|
||||
|
||||
void mew_dispatch_main_sync_safe(dispatch_block_t block) {
|
||||
if ([NSThread isMainThread]) {
|
||||
block();
|
||||
}else {
|
||||
dispatch_sync(dispatch_get_main_queue(), block);
|
||||
}
|
||||
}
|
@@ -7,7 +7,7 @@
|
||||
|
||||
#import "MewHUDTool.h"
|
||||
#import <MBProgressHUD/MBProgressHUD.h>
|
||||
#import "MewGCDHelper.h"
|
||||
|
||||
|
||||
#define kDelayTime 2.5
|
||||
@implementation MewHUDTool
|
||||
@@ -19,14 +19,25 @@ static NSArray * _animationImages = nil;
|
||||
@param view view
|
||||
*/
|
||||
+ (void)mew_hideHUDInView:(nullable UIView *)view {
|
||||
mew_dispatch_main_sync_safe(^{
|
||||
if ([NSThread isMainThread]) {
|
||||
if (view) {
|
||||
[MBProgressHUD hideHUDForView:view animated:NO];
|
||||
[MBProgressHUD hideHUDForView:[UIApplication sharedApplication].keyWindow animated:NO];
|
||||
} else {
|
||||
[MBProgressHUD hideHUDForView:[UIApplication sharedApplication].keyWindow animated:NO];
|
||||
}
|
||||
});
|
||||
}else {
|
||||
dispatch_sync(dispatch_get_main_queue(), ^(){
|
||||
if (view) {
|
||||
[MBProgressHUD hideHUDForView:view animated:NO];
|
||||
[MBProgressHUD hideHUDForView:[UIApplication sharedApplication].keyWindow animated:NO];
|
||||
} else {
|
||||
[MBProgressHUD hideHUDForView:[UIApplication sharedApplication].keyWindow animated:NO];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -65,8 +76,7 @@ static NSArray * _animationImages = nil;
|
||||
|
||||
if (message.length == 0) { return; }
|
||||
__block UIView *inView = view;
|
||||
|
||||
mew_dispatch_main_sync_safe(^{
|
||||
if ([NSThread isMainThread]) {
|
||||
if (!inView) {
|
||||
inView = [UIApplication sharedApplication].keyWindow;
|
||||
}
|
||||
@@ -83,7 +93,26 @@ static NSArray * _animationImages = nil;
|
||||
hud.label.textColor = [UIColor whiteColor];
|
||||
hud.label.font = [UIFont systemFontOfSize:14];
|
||||
[hud hideAnimated:YES afterDelay:afterDelay];
|
||||
});
|
||||
}else {
|
||||
dispatch_sync(dispatch_get_main_queue(), ^(){
|
||||
if (!inView) {
|
||||
inView = [UIApplication sharedApplication].keyWindow;
|
||||
}
|
||||
[self mew_hideHUDInView:view]; // 先隐藏
|
||||
MBProgressHUD *hud = [self normalProgressHUD:view];
|
||||
hud.userInteractionEnabled = enabled;
|
||||
hud.mode = MBProgressHUDModeText;
|
||||
hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor;
|
||||
hud.margin = 8;
|
||||
// 方框背景颜色
|
||||
hud.bezelView.color = [[UIColor blackColor] colorWithAlphaComponent:0.8];
|
||||
hud.label.text = message;
|
||||
hud.label.numberOfLines = 0;
|
||||
hud.label.textColor = [UIColor whiteColor];
|
||||
hud.label.font = [UIFont systemFontOfSize:14];
|
||||
[hud hideAnimated:YES afterDelay:afterDelay];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,8 +149,7 @@ static NSArray * _animationImages = nil;
|
||||
}
|
||||
|
||||
[self mew_hideHUDInView:view]; // 先隐藏
|
||||
|
||||
mew_dispatch_main_sync_safe(^{
|
||||
if ([NSThread isMainThread]) {
|
||||
MBProgressHUD *hud = [self normalProgressHUD:view];
|
||||
hud.userInteractionEnabled = enabled;
|
||||
hud.mode = MBProgressHUDModeText;
|
||||
@@ -134,7 +162,22 @@ static NSArray * _animationImages = nil;
|
||||
hud.label.textColor = [UIColor whiteColor];
|
||||
hud.label.font = [UIFont systemFontOfSize:14];
|
||||
[hud hideAnimated:YES afterDelay:afterDelay];
|
||||
});
|
||||
}else{
|
||||
dispatch_sync(dispatch_get_main_queue(), ^(){
|
||||
MBProgressHUD *hud = [self normalProgressHUD:view];
|
||||
hud.userInteractionEnabled = enabled;
|
||||
hud.mode = MBProgressHUDModeText;
|
||||
hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor;
|
||||
hud.margin = 8;
|
||||
// 方框背景颜色
|
||||
hud.bezelView.color = [[UIColor blackColor] colorWithAlphaComponent:0.8];
|
||||
hud.label.text = message;
|
||||
hud.label.numberOfLines = 0;
|
||||
hud.label.textColor = [UIColor whiteColor];
|
||||
hud.label.font = [UIFont systemFontOfSize:14];
|
||||
[hud hideAnimated:YES afterDelay:afterDelay];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -180,8 +223,7 @@ static NSArray * _animationImages = nil;
|
||||
view = [UIApplication sharedApplication].keyWindow;
|
||||
}
|
||||
[self mew_hideHUDInView:view];
|
||||
|
||||
mew_dispatch_main_sync_safe(^{
|
||||
if ([NSThread isMainThread]) {
|
||||
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:view animated:YES];
|
||||
hud.userInteractionEnabled = enabled;
|
||||
hud.bezelView.color = [[UIColor whiteColor] colorWithAlphaComponent:0.8];
|
||||
@@ -192,8 +234,20 @@ static NSArray * _animationImages = nil;
|
||||
hud.label.textColor = [UIColor blackColor];
|
||||
hud.label.font = [UIFont systemFontOfSize:14];
|
||||
}
|
||||
});
|
||||
|
||||
}else{
|
||||
dispatch_sync(dispatch_get_main_queue(), ^(){
|
||||
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:view animated:YES];
|
||||
hud.userInteractionEnabled = enabled;
|
||||
hud.bezelView.color = [[UIColor whiteColor] colorWithAlphaComponent:0.8];
|
||||
hud.removeFromSuperViewOnHide = YES;
|
||||
if (message.length) {
|
||||
hud.label.text = message;
|
||||
hud.label.numberOfLines = 0;
|
||||
hud.label.textColor = [UIColor blackColor];
|
||||
hud.label.font = [UIFont systemFontOfSize:14];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - private
|
||||
|
@@ -1,16 +0,0 @@
|
||||
//
|
||||
// NSArray+MewSafe.h
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/1.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface NSArray (MewSafe)
|
||||
-(id)mewSafeObjectAtIndex:(NSUInteger)index;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,22 +0,0 @@
|
||||
//
|
||||
// NSArray+MewSafe.m
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/1.
|
||||
//
|
||||
|
||||
#import "NSArray+MewSafe.h"
|
||||
|
||||
@implementation NSArray (MewSafe)
|
||||
-(id)mewSafeObjectAtIndex:(NSUInteger)index{
|
||||
if ([self isKindOfClass:[NSArray class]]){
|
||||
if (self.count){
|
||||
if (self.count>index){
|
||||
return self[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
@@ -1,16 +0,0 @@
|
||||
//
|
||||
// NSMutableDictionary+MEWSafe.h
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/1.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface NSMutableDictionary (MEWSafe)
|
||||
- (void)mewSafeSetObject:(id)anObject forKey:(id <NSCopying>)aKey;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,15 +0,0 @@
|
||||
//
|
||||
// NSMutableDictionary+MEWSafe.m
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/1.
|
||||
//
|
||||
|
||||
#import "NSMutableDictionary+MEWSafe.h"
|
||||
|
||||
@implementation NSMutableDictionary (MEWSafe)
|
||||
- (void)mewSafeSetObject:(id)anObject forKey:(id <NSCopying>)aKey {
|
||||
if (anObject == nil || aKey == nil) return;
|
||||
[self setObject:anObject forKey:aKey];
|
||||
}
|
||||
@end
|
@@ -1,21 +0,0 @@
|
||||
//
|
||||
// MewTimer.h
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/1.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
typedef void(^MewTimerHandler) (id _Nullable userInfo);
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
@interface MewTimerTarget : NSObject
|
||||
|
||||
@end
|
||||
|
||||
@interface MewTimer : NSObject
|
||||
+ (NSTimer *)MewScheduledTimerWithTimeInterval:(NSTimeInterval)interval block:(MewTimerHandler)block userInfo:(id)userInfo repeats:(BOOL)repeats;
|
||||
|
||||
+ (NSTimer *)MewScheduledTimerWithTimeInterval:(NSTimeInterval)interval target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,57 +0,0 @@
|
||||
//
|
||||
// MewTimer.m
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/1.
|
||||
//
|
||||
|
||||
#import "MewTimer.h"
|
||||
@interface MewTimerTarget()
|
||||
@property (nonatomic, weak) id target;
|
||||
@property (nonatomic, weak) NSTimer* timer;
|
||||
@property (nonatomic, assign) SEL selector;
|
||||
@end
|
||||
@implementation MewTimerTarget
|
||||
- (void) fire:(NSTimer *)timer {
|
||||
if(self.target) {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
|
||||
[self.target performSelector:self.selector withObject:timer.userInfo afterDelay:0.0f];
|
||||
#pragma clang diagnostic pop
|
||||
} else {
|
||||
[self.timer invalidate];
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
#pragma mark - YMWeakTimer
|
||||
@implementation MewTimer
|
||||
|
||||
+ (NSTimer *)MewScheduledTimerWithTimeInterval:(NSTimeInterval)interval target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats{
|
||||
MewTimerTarget* timerTarget = [[MewTimerTarget alloc] init];
|
||||
timerTarget.target = aTarget;
|
||||
timerTarget.selector = aSelector;
|
||||
timerTarget.timer = [NSTimer scheduledTimerWithTimeInterval:interval target:timerTarget selector:@selector(fire:) userInfo:userInfo repeats:repeats];
|
||||
return timerTarget.timer;
|
||||
}
|
||||
|
||||
+ (NSTimer *)MewScheduledTimerWithTimeInterval:(NSTimeInterval)interval block:(MewTimerHandler)block userInfo:(id)userInfo repeats:(BOOL)repeats{
|
||||
NSMutableArray *userInfoArray = [NSMutableArray arrayWithObject:[block copy]];
|
||||
if (userInfo != nil) {
|
||||
[userInfoArray addObject:userInfo];
|
||||
}
|
||||
return [self MewScheduledTimerWithTimeInterval:interval target:self selector:@selector(MewTimerBlockInvoke:) userInfo:[userInfoArray copy] repeats:repeats];
|
||||
}
|
||||
|
||||
+ (void)MewTimerBlockInvoke:(NSArray*)userInfo {
|
||||
MewTimerHandler block = userInfo[0];
|
||||
id info = nil;
|
||||
if (userInfo.count == 2) {
|
||||
info = userInfo[1];
|
||||
}
|
||||
if (block) {
|
||||
block(info);
|
||||
}
|
||||
}
|
||||
@end
|
@@ -22,7 +22,7 @@
|
||||
#import <net/if_dl.h>
|
||||
#import <sys/socket.h>
|
||||
#import "SSKeychain.h"
|
||||
#import "MewGCDHelper.h"
|
||||
|
||||
|
||||
|
||||
#if !defined(IFT_ETHER)
|
||||
@@ -134,8 +134,8 @@
|
||||
case AVAuthorizationStatusNotDetermined:
|
||||
{
|
||||
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
|
||||
|
||||
mew_dispatch_main_sync_safe(^{
|
||||
|
||||
dispatch_sync(dispatch_get_main_queue(), ^(){
|
||||
if (granted)
|
||||
{
|
||||
available();
|
||||
@@ -144,8 +144,8 @@
|
||||
{
|
||||
denied();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
}];
|
||||
}
|
||||
|
@@ -1,29 +0,0 @@
|
||||
//
|
||||
// MewButton.h
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/5.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
typedef NS_ENUM(NSInteger, XPButtonImagePosition) {
|
||||
MewButtonImagePositionLeft = 0, // 图片在文字左侧
|
||||
MewButtonImagePositionRight = 1, // 图片在文字右侧
|
||||
MewButtonImagePositionTop = 2, // 图片在文字上侧
|
||||
MewButtonImagePositionBottom = 3 // 图片在文字下侧
|
||||
};
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MewButton : UIButton
|
||||
- (instancetype)initWithImagePosition:(XPButtonImagePosition)imagePosition;
|
||||
|
||||
#if TARGET_INTERFACE_BUILDER // storyBoard/xib中设置
|
||||
@property (nonatomic,assign) IBInspectable NSInteger imagePosition; // 图片位置
|
||||
@property (nonatomic, assign) IBInspectable CGFloat imageTitleSpace; // 图片和文字之间的间距
|
||||
#else // 纯代码设置
|
||||
@property (nonatomic) XPButtonImagePosition imagePosition; // 图片位置
|
||||
@property (nonatomic, assign) CGFloat imageTitleSpace; // 图片和文字之间的间距
|
||||
#endif
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,595 +0,0 @@
|
||||
//
|
||||
// MewButton.m
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/5.
|
||||
//
|
||||
|
||||
#import "MewButton.h"
|
||||
|
||||
@implementation MewButton
|
||||
- (instancetype)initWithImagePosition:(XPButtonImagePosition)imagePosition {
|
||||
if (self = [super init]) {
|
||||
self.imagePosition = imagePosition;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - system methods
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
[self initialize];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
|
||||
if (self = [super initWithCoder:aDecoder]) {
|
||||
[self initialize];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)initialize {
|
||||
_imagePosition = MewButtonImagePositionLeft;
|
||||
_imageTitleSpace = 0.0;
|
||||
}
|
||||
|
||||
// 下面这2个方法,我所知道的:
|
||||
// 在第一次调用titleLabel和imageView的getter方法(懒加载)时,alloc init之前会调用一次(无论有无图片文字都会直接调),因此,在重写这2个方法时,在方法里面不要使用self.imageView和self.titleLabel,因为这2个控件是懒加载,如果在重写的这2个方法里是第一调用imageView和titleLabel的getter方法, 则会造成死循环
|
||||
// 在layoutsSubviews中如果文字或图片不为空时会调用, 测试方式:在重写的这两个方法里调用setNeedsLayout(layutSubviews),发现会造成死循环
|
||||
// 设置文字图片、改动文字和图片、设置对齐方式,设置内容区域等时会调用,其实设置这些属性,系统是调用了layoutSubviews从而间接的去调用imageRectForContentRect:和titleRectForContentRect:
|
||||
// ...
|
||||
- (CGRect)imageRectForContentRect:(CGRect)contentRect {
|
||||
// 先获取系统为我们计算好的rect,这样大小图片在左右时我们就不要自己去计算,我门要改变的,仅仅是origin
|
||||
CGRect imageRect = [super imageRectForContentRect:contentRect];
|
||||
CGRect titleRect = [super titleRectForContentRect:contentRect];
|
||||
if (!self.currentTitle) { // 如果没有文字,则图片占据整个button,空格算一个文字
|
||||
return imageRect;
|
||||
}
|
||||
switch (self.imagePosition) {
|
||||
case MewButtonImagePositionLeft: { // 图片在左
|
||||
imageRect = [self imageRectImageAtLeftForContentRect:contentRect imageRect:imageRect titleRect:titleRect];
|
||||
}
|
||||
break;
|
||||
case MewButtonImagePositionRight: {
|
||||
imageRect = [self imageRectImageAtRightForContentRect:contentRect imageRect:imageRect titleRect:titleRect];
|
||||
}
|
||||
break;
|
||||
case MewButtonImagePositionTop: {
|
||||
imageRect = [self imageRectImageAtTopForContentRect:contentRect imageRect:imageRect titleRect:titleRect];
|
||||
}
|
||||
break;
|
||||
case MewButtonImagePositionBottom: {
|
||||
imageRect = [self imageRectImageAtBottomForContentRect:contentRect imageRect:imageRect titleRect:titleRect];
|
||||
}
|
||||
break;
|
||||
}
|
||||
return imageRect;
|
||||
}
|
||||
|
||||
- (CGRect)titleRectForContentRect:(CGRect)contentRect {
|
||||
CGRect titleRect = [super titleRectForContentRect:contentRect];
|
||||
CGRect imageRect = [super imageRectForContentRect:contentRect];
|
||||
if (!self.currentImage) { // 如果没有图片
|
||||
return titleRect;
|
||||
}
|
||||
switch (self.imagePosition) {
|
||||
case MewButtonImagePositionLeft: {
|
||||
titleRect = [self titleRectImageAtLeftForContentRect:contentRect titleRect:titleRect imageRect:imageRect];
|
||||
}
|
||||
break;
|
||||
case MewButtonImagePositionRight: {
|
||||
titleRect = [self titleRectImageAtRightForContentRect:contentRect titleRect:titleRect imageRect:imageRect];
|
||||
}
|
||||
break;
|
||||
case MewButtonImagePositionTop: {
|
||||
titleRect = [self titleRectImageAtTopForContentRect:contentRect titleRect:titleRect imageRect:imageRect];
|
||||
}
|
||||
break;
|
||||
case MewButtonImagePositionBottom: {
|
||||
titleRect = [self titleRectImageAtBottomForContentRect:contentRect titleRect:titleRect imageRect:imageRect];
|
||||
}
|
||||
break;
|
||||
}
|
||||
return titleRect;
|
||||
|
||||
}
|
||||
|
||||
- (void)sizeToFit {
|
||||
// 这个super很重要,它能保证下面使用的self.frame的值是系统计算好的结果
|
||||
[super sizeToFit];
|
||||
|
||||
CGRect myFrame = self.frame;
|
||||
switch (self.imagePosition) {
|
||||
case MewButtonImagePositionLeft:
|
||||
case MewButtonImagePositionRight: // 图片在左右时,在系统计算好的基础上宽度再加间距
|
||||
myFrame.size.width = self.frame.size.width + _imageTitleSpace;
|
||||
break;
|
||||
case MewButtonImagePositionTop:
|
||||
case MewButtonImagePositionBottom: {// 图片在上下时,就不能再在系统计算的基础上增减值了,因为系统计算是基于图片在左文字在右时进行的,宽度依赖图片+文字之和,而图片在上下时,宽度应该依赖图片和文字较大的那个
|
||||
CGFloat imageFitWidth = self.contentEdgeInsets.left + self.currentImage.size.width + self.contentEdgeInsets.right;
|
||||
CGFloat titleFitWidth = self.contentEdgeInsets.left + [self calculateTitleSizeForSystemTitleSize:CGSizeMake(0, 0)].width + self.contentEdgeInsets.right;
|
||||
myFrame.size.width = MAX(imageFitWidth, titleFitWidth);
|
||||
myFrame.size.height = self.contentEdgeInsets.top + self.currentImage.size.height + [self calculateTitleSizeForSystemTitleSize:CGSizeMake(0, 0)].height + self.contentEdgeInsets.bottom + _imageTitleSpace;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
self.frame = myFrame;
|
||||
}
|
||||
|
||||
#pragma - private
|
||||
|
||||
// ----------------------------------------------------- left -----------------------------------------------------
|
||||
|
||||
- (CGRect)imageRectImageAtLeftForContentRect:(CGRect)contentRect imageRect:(CGRect)imageRect titleRect:(CGRect)titleRect {
|
||||
CGPoint imageOrigin = imageRect.origin;
|
||||
CGSize imageSize = imageRect.size;
|
||||
|
||||
//CGSize titleSize = titleRect.size;
|
||||
|
||||
switch (self.contentHorizontalAlignment) {
|
||||
case UIControlContentHorizontalAlignmentCenter: // 中心对齐
|
||||
// imageView的x值向左偏移间距的一半,另一半由titleLabe分担,不用管会不会超出contentRect,我定的规则是允许超出,如果对此作出限制,那么必须要对图片或者文字宽高有所压缩,压缩只能由imageEdgeInsets决定,当图片的内容区域容不下时才产生宽度压缩
|
||||
imageOrigin.x = imageOrigin.x - _imageTitleSpace*0.5;
|
||||
break;
|
||||
case UIControlContentHorizontalAlignmentRight:
|
||||
case UIControlContentHorizontalAlignmentTrailing: // 右对齐
|
||||
imageOrigin.x = imageOrigin.x - _imageTitleSpace;
|
||||
break;
|
||||
case UIControlContentHorizontalAlignmentFill: // 填充整个按钮,水平填充模式有点怪异,填充的意思是将图片和文字整个水平填满,但是,事实上能够被填满,但是titleLabel的x值不会发生变化,即图片被拉伸,但是图片的右边会预留一个titleLabel的宽度,这个titleLabel的宽度由系统计算,我们不必关心计算过程。还有,填充模式下,设置图片的contentMode是不管用的,因为系统强制设置了图片的大小
|
||||
imageOrigin.x = imageOrigin.x - _imageTitleSpace*0.5;
|
||||
break;
|
||||
default: // 剩下的就是左对齐,左对齐image不用做任何改变
|
||||
break;
|
||||
}
|
||||
imageRect.size = imageSize;
|
||||
imageRect.origin = imageOrigin;
|
||||
return imageRect;
|
||||
}
|
||||
|
||||
- (CGRect)titleRectImageAtLeftForContentRect:(CGRect)contentRect titleRect:(CGRect)titleRect imageRect:(CGRect)imageRect {
|
||||
CGPoint titleOrigin = titleRect.origin;
|
||||
CGSize titleSize = titleRect.size;
|
||||
|
||||
//CGSize imageSize = imageRect.size;
|
||||
|
||||
switch (self.contentHorizontalAlignment) {
|
||||
case UIControlContentHorizontalAlignmentCenter: { // 中心对齐
|
||||
titleOrigin.x = titleOrigin.x + _imageTitleSpace * 0.5;
|
||||
}
|
||||
break;
|
||||
case UIControlContentHorizontalAlignmentLeft:
|
||||
case UIControlContentHorizontalAlignmentLeading: { // 左对齐
|
||||
titleOrigin.x = titleOrigin.x + _imageTitleSpace;
|
||||
}
|
||||
break;
|
||||
case UIControlContentHorizontalAlignmentFill: // 填充整个按钮
|
||||
// 填充整个按钮,水平填充模式有点怪异,填充的意思是将图片和文字整个水平填满,但是,事实上能够被填满,但是titleLabel的x值不会发生变化,即图片被拉伸,但是图片的右边会预留一个titleLabel的宽度,这个titleLabel的宽度由系统计算,我们不必关心计算过程。还有,填充模式下,设置图片的contentMode是不管用的,因为系统强制设置了图片的大小
|
||||
// 宽度减去间距的一半,另一半由imageView分担,x值保持系统值
|
||||
titleOrigin.x = titleOrigin.x + _imageTitleSpace * 0.5;
|
||||
break;
|
||||
default: // 剩下的就是右对齐,右对齐titleLabel不用做任何改变
|
||||
break;
|
||||
}
|
||||
|
||||
titleRect.size = titleSize;
|
||||
titleRect.origin = titleOrigin;
|
||||
return titleRect;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- right -----------------------------------------------------
|
||||
|
||||
- (CGRect)imageRectImageAtRightForContentRect:(CGRect)contentRect imageRect:(CGRect)imageRect titleRect:(CGRect)titleRect {
|
||||
|
||||
CGFloat imageSafeWidth = contentRect.size.width - self.imageEdgeInsets.left - self.imageEdgeInsets.right;
|
||||
if (imageRect.size.width >= imageSafeWidth) {
|
||||
return imageRect;
|
||||
}
|
||||
|
||||
CGPoint imageOrigin = imageRect.origin;
|
||||
CGSize imageSize = imageRect.size;
|
||||
CGSize titleSize = titleRect.size;
|
||||
|
||||
// 这里水平中心对齐,跟图片在右边时的中心对齐时差别在于:图片在右边时中心对齐考虑了titleLabel+imageView这个整体,而这里只单独考虑imageView
|
||||
if (imageSize.width + titleSize.width > imageSafeWidth) {
|
||||
imageSize.width = imageSize.width - (imageSize.width + titleSize.width - imageSafeWidth);
|
||||
}
|
||||
|
||||
CGFloat buttonWidth = contentRect.size.width + self.contentEdgeInsets.left + self.contentEdgeInsets.right;
|
||||
titleSize = [self calculateTitleSizeForSystemTitleSize:titleSize];
|
||||
|
||||
switch (self.contentHorizontalAlignment) {
|
||||
case UIControlContentHorizontalAlignmentCenter: // 中心对齐
|
||||
// (contentRect.size.width - self.imageEdgeInsets.left - self.imageEdgeInsets.right - (imageSize.width + titleSize.width))/2.0+titleSize.width指的是imageView在其有效区域内联合titleLabel整体居中时的x值,有效区域指的是contentRect内缩imageEdgeInsets后的区域
|
||||
imageOrigin.x = (contentRect.size.width - self.imageEdgeInsets.left - self.imageEdgeInsets.right - (imageSize.width + titleSize.width))/2.0 + titleSize.width + self.contentEdgeInsets.left + self.imageEdgeInsets.left + _imageTitleSpace * 0.5;
|
||||
break;
|
||||
case UIControlContentHorizontalAlignmentLeft:
|
||||
case UIControlContentHorizontalAlignmentLeading: // 左对齐
|
||||
imageOrigin.x = self.contentEdgeInsets.left + self.imageEdgeInsets.left + titleSize.width + _imageTitleSpace;
|
||||
break;
|
||||
case UIControlContentHorizontalAlignmentRight:
|
||||
case UIControlContentHorizontalAlignmentTrailing: // 右对齐
|
||||
// 注意image的大小要使用系统计算的结果,这里不能使用self.currentImage.size.width,当imageEdgeInsets的left过大时可以进行测试
|
||||
imageOrigin.x = buttonWidth - imageSize.width - self.imageEdgeInsets.right - self.contentEdgeInsets.right;
|
||||
break;
|
||||
case UIControlContentHorizontalAlignmentFill: // 填充
|
||||
imageOrigin.x = buttonWidth - imageSize.width - self.imageEdgeInsets.right - self.contentEdgeInsets.right + _imageTitleSpace * 0.5;
|
||||
break;
|
||||
}
|
||||
imageRect.size = imageSize;
|
||||
imageRect.origin = imageOrigin;
|
||||
return imageRect;
|
||||
}
|
||||
|
||||
- (CGRect)titleRectImageAtRightForContentRect:(CGRect)contentRect titleRect:(CGRect)titleRect imageRect:(CGRect)imageRect {
|
||||
|
||||
CGPoint titleOrigin = titleRect.origin;
|
||||
CGSize titleSize = titleRect.size;
|
||||
CGSize imageSize = imageRect.size;
|
||||
|
||||
CGFloat buttonWidth = contentRect.size.width + self.contentEdgeInsets.left + self.contentEdgeInsets.right;
|
||||
|
||||
switch (self.contentHorizontalAlignment) {
|
||||
case UIControlContentHorizontalAlignmentCenter: // 中心对齐
|
||||
// (contentRect.size.width - self.titleEdgeInsets.left - self.titleEdgeInsets.right - (imageSize.width + titleSize.width))/2.0的意思是titleLabel在其有效区域内联合imageView整体居中时的x值,有效区域指的是contentRect内缩titleEdgeInsets后的区域
|
||||
titleOrigin.x = (contentRect.size.width - self.titleEdgeInsets.left - self.titleEdgeInsets.right - (imageSize.width + titleSize.width))/2.0 + self.contentEdgeInsets.left + self.titleEdgeInsets.left - _imageTitleSpace * 0.5;
|
||||
break;
|
||||
case UIControlContentHorizontalAlignmentLeft:
|
||||
case UIControlContentHorizontalAlignmentLeading: // 左对齐
|
||||
titleOrigin.x = self.contentEdgeInsets.left + self.titleEdgeInsets.left;
|
||||
break;
|
||||
case UIControlContentHorizontalAlignmentRight:
|
||||
case UIControlContentHorizontalAlignmentTrailing: // 右对齐
|
||||
// 这里必须使用self.currentImage的宽度。不能使用imageSize.width,因为图片可能会被压缩或者拉伸,例如当图片的imageEdgeInsets的right设置过大,图片的宽度就会被压缩,这时的图片宽度不是我们要的
|
||||
titleOrigin.x = buttonWidth - (titleSize.width + self.currentImage.size.width) - self.titleEdgeInsets.right - self.contentEdgeInsets.right - _imageTitleSpace;
|
||||
break;
|
||||
case UIControlContentHorizontalAlignmentFill:
|
||||
titleOrigin.x = buttonWidth - (titleSize.width + self.currentImage.size.width) - self.titleEdgeInsets.right - self.contentEdgeInsets.right - _imageTitleSpace * 0.5;
|
||||
break;
|
||||
}
|
||||
titleRect.size = titleSize;
|
||||
titleRect.origin = titleOrigin;
|
||||
return titleRect;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- top -----------------------------------------------------
|
||||
|
||||
- (CGRect)imageRectImageAtTopForContentRect:(CGRect)contentRect imageRect:(CGRect)imageRect titleRect:(CGRect)titleRect {
|
||||
CGPoint imageOrigin = imageRect.origin;
|
||||
CGSize imageSize = self.currentImage.size;
|
||||
CGSize titleSize = [self calculateTitleSizeForSystemTitleSize:titleRect.size];
|
||||
|
||||
CGFloat imageSafeWidth = contentRect.size.width - self.imageEdgeInsets.left - self.imageEdgeInsets.right;
|
||||
CGFloat imageSafeHeight = contentRect.size.height - self.imageEdgeInsets.top - self.imageEdgeInsets.bottom;
|
||||
|
||||
// 这里水平中心对齐,跟图片在右边时的中心对齐时差别在于:图片在右边时中心对齐考虑了titleLabel+imageView这个整体,而这里只单独考虑imageView
|
||||
if (imageSize.width > imageSafeWidth) {
|
||||
imageSize.width = imageSafeWidth;
|
||||
}
|
||||
if (imageSize.height > imageSafeHeight) {
|
||||
imageSize.height = imageSafeHeight;
|
||||
}
|
||||
|
||||
CGFloat buttonWidth = contentRect.size.width + self.contentEdgeInsets.left + self.contentEdgeInsets.right;
|
||||
CGFloat buttonHeight = contentRect.size.height + self.contentEdgeInsets.top + self.contentEdgeInsets.bottom;
|
||||
|
||||
// 水平方向
|
||||
switch (self.contentHorizontalAlignment) {
|
||||
case UIControlContentHorizontalAlignmentCenter: {// 中心对齐
|
||||
imageOrigin.x = (contentRect.size.width - self.imageEdgeInsets.left - self.imageEdgeInsets.right - imageSize.width) / 2.0 + self.contentEdgeInsets.left + self.imageEdgeInsets.left;
|
||||
}
|
||||
break;
|
||||
case UIControlContentHorizontalAlignmentLeft:
|
||||
case UIControlContentHorizontalAlignmentLeading: // 左对齐
|
||||
imageOrigin.x = self.contentEdgeInsets.left + self.imageEdgeInsets.left;
|
||||
break;
|
||||
case UIControlContentHorizontalAlignmentRight:
|
||||
case UIControlContentHorizontalAlignmentTrailing: // 右对齐
|
||||
imageOrigin.x = buttonWidth - imageSize.width - self.imageEdgeInsets.right - self.contentEdgeInsets.right;
|
||||
break;
|
||||
case UIControlContentHorizontalAlignmentFill: // 填充
|
||||
imageOrigin.x = self.contentEdgeInsets.left + self.imageEdgeInsets.left;
|
||||
imageSize.width = imageSafeWidth; // 宽度填满
|
||||
break;
|
||||
}
|
||||
|
||||
// 给图片高度作最大限制,超出限制对高度进行压缩,这样还可以保证titeLabel不会超出其有效区域
|
||||
CGFloat imageTitleLimitMaxH = contentRect.size.height - self.imageEdgeInsets.top - self.imageEdgeInsets.bottom;
|
||||
if (imageSize.height < imageTitleLimitMaxH) {
|
||||
if (titleSize.height + imageSize.height > imageTitleLimitMaxH) {
|
||||
CGFloat beyondValue = titleSize.height + self.currentImage.size.height - imageTitleLimitMaxH;
|
||||
imageSize.height = imageSize.height - beyondValue;
|
||||
}
|
||||
}
|
||||
|
||||
// 垂直方向
|
||||
switch (self.contentVerticalAlignment) {
|
||||
case UIControlContentVerticalAlignmentCenter: // 中心对齐
|
||||
// (imageSize.height + titleSize.height)这个整体高度很重要,这里相当于按照按钮原有规则进行对齐,即按钮的对齐方式不管是设置谁的insets,计算时都是以图片+文字这个整体作为考虑对象
|
||||
imageOrigin.y = (contentRect.size.height - self.imageEdgeInsets.top - self.imageEdgeInsets.bottom - (imageSize.height + titleSize.height)) / 2.0 + self.contentEdgeInsets.top + self.imageEdgeInsets.top - _imageTitleSpace * 0.5;
|
||||
break;
|
||||
case UIControlContentVerticalAlignmentTop: // 顶部对齐
|
||||
imageOrigin.y = self.contentEdgeInsets.top + self.imageEdgeInsets.top - _imageTitleSpace * 0.5;
|
||||
break;
|
||||
case UIControlContentVerticalAlignmentBottom: // 底部对齐
|
||||
imageOrigin.y = buttonHeight - (imageSize.height + titleSize.height) - self.contentEdgeInsets.bottom - self.imageEdgeInsets.bottom - _imageTitleSpace * 0.5;
|
||||
break;
|
||||
case UIControlContentVerticalAlignmentFill: // 填充
|
||||
imageOrigin.y = self.contentEdgeInsets.top + self.imageEdgeInsets.top - _imageTitleSpace * 0.5;
|
||||
imageSize.height = contentRect.size.height - self.imageEdgeInsets.top - self.imageEdgeInsets.bottom - [self calculateTitleSizeForSystemTitleSize:titleSize].height;
|
||||
break;
|
||||
}
|
||||
imageRect.size = imageSize;
|
||||
imageRect.origin = imageOrigin;
|
||||
return imageRect;
|
||||
}
|
||||
|
||||
- (CGRect)titleRectImageAtTopForContentRect:(CGRect)contentRect titleRect:(CGRect)titleRect imageRect:(CGRect)imageRect {
|
||||
CGPoint titleOrigin = titleRect.origin;
|
||||
CGSize imageSize = self.currentImage.size;
|
||||
CGSize titleSize = [self calculateTitleSizeForSystemTitleSize:titleRect.size];
|
||||
|
||||
CGFloat buttonWidth = contentRect.size.width + self.contentEdgeInsets.left + self.contentEdgeInsets.right;
|
||||
CGFloat buttonHeight = contentRect.size.height + self.contentEdgeInsets.top + self.contentEdgeInsets.bottom;
|
||||
|
||||
// 这个if语句的含义是:计算图片由于设置了contentEdgeInsets而被压缩的高度,设置imageEdgeInsets被压缩的高度不计算在内。这样做的目的是,当设置了contentEdgeInsets时,图片可能会被压缩,此时titleLabel的y值依赖于图片压缩后的高度,当设置了imageEdgeInsets时,图片也可能被压缩,此时titleLabel的y值依赖于图片压缩前的高度,这样以来,设置imageEdgeInsets就不会对titleLabel的y值产生影响
|
||||
if (imageSize.height + titleSize.height > contentRect.size.height) {
|
||||
imageSize.height = self.currentImage.size.height - (self.currentImage.size.height + titleSize.height - contentRect.size.height);
|
||||
}
|
||||
// titleLabel的安全宽度,这里一定要改变宽度值,因为当外界设置了titleEdgeInsets值时,系统计算出来的所有值都是在”左图右文“的基础上进行的,这个基础上可能会导致titleLabel的宽度被压缩,所以我们在此自己重新计算
|
||||
CGFloat titleSafeWidth = contentRect.size.width - self.titleEdgeInsets.left - self.titleEdgeInsets.right;
|
||||
if (titleSize.width > titleSafeWidth) {
|
||||
titleSize.width = titleSafeWidth;
|
||||
}
|
||||
|
||||
// 水平方向
|
||||
switch (self.contentHorizontalAlignment) {
|
||||
case UIControlContentHorizontalAlignmentCenter: {// 中心对齐
|
||||
|
||||
titleOrigin.x = (titleSafeWidth - titleSize.width) / 2.0 + self.contentEdgeInsets.left + self.titleEdgeInsets.left;
|
||||
}
|
||||
break;
|
||||
case UIControlContentHorizontalAlignmentLeft:
|
||||
case UIControlContentHorizontalAlignmentLeading: // 左对齐
|
||||
titleOrigin.x = self.contentEdgeInsets.left + self.titleEdgeInsets.left;
|
||||
break;
|
||||
case UIControlContentHorizontalAlignmentRight:
|
||||
case UIControlContentHorizontalAlignmentTrailing: // 右对齐
|
||||
titleOrigin.x = buttonWidth - titleSize.width - self.titleEdgeInsets.right - self.contentEdgeInsets.right;
|
||||
break;
|
||||
case UIControlContentHorizontalAlignmentFill: // 填充
|
||||
titleOrigin.x = self.contentEdgeInsets.left + self.titleEdgeInsets.left;
|
||||
// titleLabel宽度上不填充,按系统一样,在有效区域内,自适应文字宽度
|
||||
break;
|
||||
}
|
||||
|
||||
if (titleSize.height > contentRect.size.height - self.titleEdgeInsets.top - self.titleEdgeInsets.bottom) {
|
||||
titleSize.height = contentRect.size.height - self.titleEdgeInsets.top - self.titleEdgeInsets.bottom;
|
||||
}
|
||||
|
||||
// 垂直方向
|
||||
switch (self.contentVerticalAlignment) {
|
||||
case UIControlContentVerticalAlignmentCenter: {// 中心对齐
|
||||
// (imageSize.height + titleSize.height)这个整体高度很重要,这里相当于按照按钮原有规则进行对齐,即按钮的对齐方式不管是设置谁的Insets,计算时都是以图片+文字这个整体作为考虑对象
|
||||
titleOrigin.y = (contentRect.size.height - self.titleEdgeInsets.top - self.titleEdgeInsets.bottom - (imageSize.height + titleSize.height)) / 2.0 + imageSize.height + self.contentEdgeInsets.top + self.titleEdgeInsets.top + _imageTitleSpace * 0.5;
|
||||
}
|
||||
break;
|
||||
case UIControlContentVerticalAlignmentTop: // 顶部对齐
|
||||
titleOrigin.y = self.contentEdgeInsets.top + self.titleEdgeInsets.top + imageSize.height + _imageTitleSpace * 0.5;
|
||||
break;
|
||||
case UIControlContentVerticalAlignmentBottom: // 底部对齐
|
||||
titleOrigin.y = buttonHeight - titleSize.height - self.contentEdgeInsets.bottom - self.titleEdgeInsets.bottom+ _imageTitleSpace * 0.5;
|
||||
break;
|
||||
case UIControlContentVerticalAlignmentFill: // 填充
|
||||
titleOrigin.y = buttonHeight - titleSize.height - self.contentEdgeInsets.bottom - self.titleEdgeInsets.bottom + _imageTitleSpace * 0.5;
|
||||
break;
|
||||
}
|
||||
|
||||
titleRect.size = titleSize;
|
||||
titleRect.origin = titleOrigin;
|
||||
return titleRect;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------- bottom -----------------------------------------------------
|
||||
|
||||
- (CGRect)imageRectImageAtBottomForContentRect:(CGRect)contentRect imageRect:(CGRect)imageRect titleRect:(CGRect)titleRect {
|
||||
CGPoint imageOrigin = imageRect.origin;
|
||||
CGSize imageSize = self.currentImage.size;
|
||||
CGSize titleSize = [self calculateTitleSizeForSystemTitleSize:titleRect.size];
|
||||
|
||||
CGFloat imageSafeWidth = contentRect.size.width - self.imageEdgeInsets.left - self.imageEdgeInsets.right;
|
||||
CGFloat imageSafeHeight = contentRect.size.height - self.imageEdgeInsets.top - self.imageEdgeInsets.bottom;
|
||||
|
||||
// 这里水平中心对齐,跟图片在右边时的中心对齐时差别在于:图片在右边时中心对齐考虑了titleLabel+imageView这个整体,而这里只单独考虑imageView
|
||||
if (imageSize.width > imageSafeWidth) {
|
||||
imageSize.width = imageSafeWidth;
|
||||
}
|
||||
if (imageSize.height > imageSafeHeight) {
|
||||
imageSize.height = imageSafeHeight;
|
||||
}
|
||||
|
||||
CGFloat buttonWidth = contentRect.size.width + self.contentEdgeInsets.left + self.contentEdgeInsets.right;
|
||||
CGFloat buttonHeight = contentRect.size.height + self.contentEdgeInsets.top + self.contentEdgeInsets.bottom;
|
||||
|
||||
// 水平方向
|
||||
switch (self.contentHorizontalAlignment) {
|
||||
case UIControlContentHorizontalAlignmentCenter: {// 中心对齐
|
||||
imageOrigin.x = (contentRect.size.width - self.imageEdgeInsets.left - self.imageEdgeInsets.right - imageSize.width) / 2.0 + self.contentEdgeInsets.left + self.imageEdgeInsets.left;
|
||||
}
|
||||
break;
|
||||
case UIControlContentHorizontalAlignmentLeft:
|
||||
case UIControlContentHorizontalAlignmentLeading: // 左对齐
|
||||
imageOrigin.x = self.contentEdgeInsets.left + self.imageEdgeInsets.left;
|
||||
break;
|
||||
case UIControlContentHorizontalAlignmentRight:
|
||||
case UIControlContentHorizontalAlignmentTrailing: // 右对齐
|
||||
imageOrigin.x = buttonWidth - imageSize.width - self.imageEdgeInsets.right - self.contentEdgeInsets.right;
|
||||
break;
|
||||
case UIControlContentHorizontalAlignmentFill: // 填充
|
||||
imageOrigin.x = self.contentEdgeInsets.left + self.imageEdgeInsets.left;
|
||||
imageSize.width = imageSafeWidth; // 宽度填满
|
||||
break;
|
||||
}
|
||||
|
||||
// 给图片高度作最大限制,超出限制对高度进行压缩,这样还可以保证titeLabel不会超出其有效区域
|
||||
CGFloat imageTitleLimitMaxH = contentRect.size.height - self.imageEdgeInsets.top - self.imageEdgeInsets.bottom;
|
||||
if (imageSize.height < imageTitleLimitMaxH) {
|
||||
if (titleSize.height + imageSize.height > imageTitleLimitMaxH) {
|
||||
CGFloat beyondValue = titleSize.height + self.currentImage.size.height - imageTitleLimitMaxH;
|
||||
imageSize.height = imageSize.height - beyondValue;
|
||||
}
|
||||
}
|
||||
// 垂直方向
|
||||
switch (self.contentVerticalAlignment) {
|
||||
case UIControlContentVerticalAlignmentCenter: // 中心对齐
|
||||
// (self.currentImage.size.height + titleSize.height)这个整体高度很重要,这里相当于按照按钮原有规则进行对齐,即按钮的对齐方式不管是设置谁的insets,计算时都是以图片+文字这个整体作为考虑对象
|
||||
imageOrigin.y = (contentRect.size.height - self.imageEdgeInsets.top - self.imageEdgeInsets.bottom - (imageSize.height + titleSize.height)) / 2.0 + titleSize.height + self.contentEdgeInsets.top + self.imageEdgeInsets.top + _imageTitleSpace * 0.5;
|
||||
break;
|
||||
case UIControlContentVerticalAlignmentTop: // 顶部对齐
|
||||
imageOrigin.y = self.contentEdgeInsets.top + self.imageEdgeInsets.top + titleSize.height + _imageTitleSpace * 0.5;
|
||||
break;
|
||||
case UIControlContentVerticalAlignmentBottom: // 底部对齐
|
||||
imageOrigin.y = buttonHeight - imageSize.height - self.contentEdgeInsets.bottom - self.imageEdgeInsets.bottom + _imageTitleSpace * 0.5;
|
||||
break;
|
||||
case UIControlContentVerticalAlignmentFill: // 填充
|
||||
// 这里不能使用titleSize.height,因为垂直填充模式下,系统计算出的titleSize就是contentRect的高度,我们需要的是titleLabel拉伸前的高度
|
||||
imageSize.height = contentRect.size.height - self.imageEdgeInsets.top - self.imageEdgeInsets.bottom - [self calculateTitleSizeForSystemTitleSize:titleSize].height;
|
||||
imageOrigin.y = buttonHeight - imageSize.height - self.contentEdgeInsets.bottom - self.imageEdgeInsets.bottom + _imageTitleSpace * 0.5;
|
||||
break;
|
||||
}
|
||||
|
||||
imageRect.size = imageSize;
|
||||
imageRect.origin = imageOrigin;
|
||||
return imageRect;
|
||||
}
|
||||
|
||||
- (CGRect)titleRectImageAtBottomForContentRect:(CGRect)contentRect titleRect:(CGRect)titleRect imageRect:(CGRect)imageRect {
|
||||
CGPoint titleOrigin = titleRect.origin;
|
||||
CGSize imageSize = self.currentImage.size;
|
||||
CGSize titleSize = [self calculateTitleSizeForSystemTitleSize:titleRect.size];
|
||||
|
||||
// 这个if语句的含义是:计算图片由于设置了contentEdgeInsets而被压缩的高度,设置imageEdgeInsets被压缩的高度不计算在内。这样做的目的是,当设置了contentEdgeInsets时,图片可能会被压缩,此时titleLabel的y值依赖于图片压缩后的高度,当设置了imageEdgeInsets时,图片也可能被压缩,此时titleLabel的y值依赖于图片压缩前的高度,这样一来,设置imageEdgeInsets就不会对titleLabel的y值产生影响
|
||||
if (self.currentImage.size.height + titleSize.height > contentRect.size.height) {
|
||||
imageSize.height = self.currentImage.size.height - (self.currentImage.size.height + titleSize.height - contentRect.size.height);
|
||||
}
|
||||
|
||||
// titleLabel的安全宽度,因为当外界设置了titleEdgeInsets值时,系统计算出来的所有值都是在”左图右文“的基础上进行的,这个基础上可能会导致titleLabel的宽度被压缩,所以我们在此自己重新计算
|
||||
CGFloat titleSafeWidth = contentRect.size.width - self.titleEdgeInsets.left - self.titleEdgeInsets.right;
|
||||
if (titleSize.width > titleSafeWidth) {
|
||||
titleSize.width = titleSafeWidth;
|
||||
}
|
||||
|
||||
CGFloat buttonWidth = contentRect.size.width + self.contentEdgeInsets.left + self.contentEdgeInsets.right;
|
||||
CGFloat buttonHeight = contentRect.size.height + self.contentEdgeInsets.top + self.contentEdgeInsets.bottom;
|
||||
|
||||
// 水平方向
|
||||
switch (self.contentHorizontalAlignment) {
|
||||
case UIControlContentHorizontalAlignmentCenter: {// 中心对齐
|
||||
titleOrigin.x = (titleSafeWidth - titleSize.width) / 2.0 + self.contentEdgeInsets.left + self.titleEdgeInsets.left;
|
||||
}
|
||||
break;
|
||||
case UIControlContentHorizontalAlignmentLeft:
|
||||
case UIControlContentHorizontalAlignmentLeading: // 左对齐
|
||||
titleOrigin.x = self.contentEdgeInsets.left + self.titleEdgeInsets.left;
|
||||
break;
|
||||
case UIControlContentHorizontalAlignmentRight:
|
||||
case UIControlContentHorizontalAlignmentTrailing: // 右对齐
|
||||
titleOrigin.x = buttonWidth - titleSize.width - self.titleEdgeInsets.right - self.contentEdgeInsets.right;
|
||||
break;
|
||||
case UIControlContentHorizontalAlignmentFill: // 填充
|
||||
titleOrigin.x = self.contentEdgeInsets.left + self.titleEdgeInsets.left;
|
||||
// titleLabel宽度上不填充,按系统一样,在有效区域内,自适应文字宽度
|
||||
break;
|
||||
}
|
||||
|
||||
if (titleSize.height > contentRect.size.height - self.titleEdgeInsets.top - self.titleEdgeInsets.bottom) {
|
||||
titleSize.height = contentRect.size.height - self.titleEdgeInsets.top - self.titleEdgeInsets.bottom;
|
||||
}
|
||||
|
||||
// 垂直方向
|
||||
switch (self.contentVerticalAlignment) {
|
||||
case UIControlContentVerticalAlignmentCenter: // 中心对齐
|
||||
// (self.currentImage.size.height + titleSize.height)这个整体高度很重要,这里相当于按照按钮原有规则进行对齐,即按钮的对齐方式不管是设置谁的Insets,计算时都是以图片+文字这个整体作为考虑对象
|
||||
titleOrigin.y = (contentRect.size.height - self.titleEdgeInsets.top - self.titleEdgeInsets.bottom - (imageSize.height + titleSize.height)) / 2.0 + self.contentEdgeInsets.top + self.titleEdgeInsets.top - _imageTitleSpace * 0.5;
|
||||
break;
|
||||
case UIControlContentVerticalAlignmentTop: // 顶部对齐
|
||||
titleOrigin.y = self.contentEdgeInsets.top + self.titleEdgeInsets.top - _imageTitleSpace * 0.5;
|
||||
break;
|
||||
case UIControlContentVerticalAlignmentBottom: // 底部对齐
|
||||
titleOrigin.y = buttonHeight - (titleSize.height + imageSize.height) - self.contentEdgeInsets.bottom - self.titleEdgeInsets.bottom - _imageTitleSpace * 0.5;
|
||||
break;
|
||||
case UIControlContentVerticalAlignmentFill: // 填充
|
||||
titleOrigin.y = self.contentEdgeInsets.top + self.titleEdgeInsets.top - _imageTitleSpace * 0.5;
|
||||
break;
|
||||
}
|
||||
|
||||
titleRect.size = titleSize;
|
||||
titleRect.origin = titleOrigin;
|
||||
return titleRect;
|
||||
}
|
||||
|
||||
// 自己计算titleLabel的大小
|
||||
- (CGSize)calculateTitleSizeForSystemTitleSize:(CGSize)titleSize {
|
||||
CGSize myTitleSize = titleSize;
|
||||
// 获取按钮里的titleLabel,之所以遍历获取而不直接调用self.titleLabel,是因为假如这里是第一次调用self.titleLabel,则会跟titleRectForContentRect: 方法造成死循环,titleLabel的getter方法中,alloc init之前调用了titleRectForContentRect:
|
||||
UILabel *titleLabel = [self findTitleLabel];
|
||||
if (!titleLabel) { // 此时还没有创建titleLabel,先通过系统button的字体进行文字宽度计算
|
||||
CGFloat fontSize = [UIFont buttonFontSize]; // 按钮默认字体,18号
|
||||
// 说明外界使用了被废弃的font属性,被废弃但是依然生效
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
if (self.font.pointSize != [UIFont buttonFontSize]) {
|
||||
fontSize = self.font.pointSize;
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
myTitleSize.height = ceil([self.currentTitle boundingRectWithSize:CGSizeMake(titleSize.width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fontSize]} context:nil].size.height);
|
||||
// 根据文字计算宽度,取上整,补齐误差,保证跟titleLabel.intrinsicContentSize.width一致
|
||||
myTitleSize.width = ceil([self.currentTitle boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, titleSize.height) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fontSize]} context:nil].size.width);
|
||||
} else { // 说明此时titeLabel已经产生,直接取titleLabel的内容宽度
|
||||
myTitleSize.width = titleLabel.intrinsicContentSize.width;
|
||||
myTitleSize.height = titleLabel.intrinsicContentSize.height;
|
||||
}
|
||||
return myTitleSize;
|
||||
}
|
||||
|
||||
// 遍历获取按钮里面的titleLabel
|
||||
- (UILabel *)findTitleLabel {
|
||||
for (UIView *subView in self.subviews) {
|
||||
if ([subView isKindOfClass:NSClassFromString(@"UIButtonLabel")]) {
|
||||
UILabel *titleLabel = (UILabel *)subView;
|
||||
return titleLabel;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma mark - setter
|
||||
// 以下所有setter方法中都调用了layoutSubviews, 其实是为了间接的调用imageRectForContentRect:和titleRectForContentRect:,不能直接调用imageRectForContentRect:和titleRectForContentRect:,因为按钮的子控件布局最终都是通过调用layoutSubviews而确定,如果直接调用这两个方法,那么只能保证我们能够获取的CGRect是对的,但并不会作用在titleLabel和imageView上
|
||||
- (void)setImagePosition:(XPButtonImagePosition)imagePosition {
|
||||
_imagePosition = imagePosition;
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)setImageTitleSpace:(CGFloat)imageTitleSpace {
|
||||
_imageTitleSpace = imageTitleSpace;
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)setContentHorizontalAlignment:(UIControlContentHorizontalAlignment)contentHorizontalAlignment {
|
||||
[super setContentHorizontalAlignment:contentHorizontalAlignment];
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
// 垂直方向的排列方式在设置之前如果调用了titleLabel或imageView的getter方法,则设置后不会生效,点击一下按钮之后就生效了,这应该属于按钮的一个小bug,我们只要重写它的setter方法重新布局一次就好
|
||||
- (void)setContentVerticalAlignment:(UIControlContentVerticalAlignment)contentVerticalAlignment {
|
||||
[super setContentVerticalAlignment:contentVerticalAlignment];
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
@end
|
@@ -10,7 +10,7 @@
|
||||
#import <Masonry/Masonry.h>
|
||||
///Tool
|
||||
#import "MewThemeColor.h"
|
||||
#import "UIImageConstant.h"
|
||||
|
||||
|
||||
@interface MewEmptyTableViewCell()
|
||||
@property (nonatomic,strong) UIImageView *emptyImageView;
|
||||
@@ -61,7 +61,6 @@
|
||||
if (!_emptyImageView) {
|
||||
_emptyImageView = [[UIImageView alloc] init];
|
||||
_emptyImageView.userInteractionEnabled = YES;
|
||||
_emptyImageView.image = [UIImageConstant defalutEmptyPlaceholder];
|
||||
_emptyImageView.layer.masksToBounds = YES;
|
||||
_emptyImageView.contentMode = UIViewContentModeScaleAspectFit;
|
||||
}
|
||||
|
@@ -1,57 +0,0 @@
|
||||
//
|
||||
// TTActionSheetConfig.h
|
||||
// AFNetworking
|
||||
//
|
||||
// Created by lee on 2019/5/23.
|
||||
// action sheet item 配置
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
typedef enum : NSUInteger {
|
||||
TTItemSelectNormal,
|
||||
TTItemSelectHighLight,
|
||||
} TTItemSelectType;
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
typedef void(^TTActionSheetClickAction)(void);
|
||||
|
||||
@interface TTActionSheetConfig : NSObject
|
||||
|
||||
/** 标题 */
|
||||
@property (nonatomic, copy) NSString *title;
|
||||
|
||||
/**
|
||||
标题颜色
|
||||
*/
|
||||
@property (nonatomic, strong) UIColor *titleColor;
|
||||
|
||||
/** 是否选中 */
|
||||
@property (nonatomic, assign) TTItemSelectType type;
|
||||
|
||||
/** 点击事件 */
|
||||
@property (nonatomic, copy) TTActionSheetClickAction clickAction;
|
||||
|
||||
/**
|
||||
构建 actionSheet item 实例
|
||||
|
||||
@param title 标题
|
||||
@param clickAction 点击事件
|
||||
@return item 实例
|
||||
*/
|
||||
+ (TTActionSheetConfig *)normalTitle:(NSString *)title
|
||||
clickAction:(TTActionSheetClickAction)clickAction;
|
||||
+ (TTActionSheetConfig *)normalTitle:(NSString *)title
|
||||
selectColorType:(TTItemSelectType)type clickAction:(TTActionSheetClickAction)clickAction;
|
||||
|
||||
|
||||
/// 构建实例
|
||||
/// @param title 标题
|
||||
/// @param textColor 颜色
|
||||
/// @param handler 事件处理
|
||||
+ (TTActionSheetConfig *)actionWithTitle:(NSString *)title
|
||||
color:(UIColor *)textColor
|
||||
handler:(TTActionSheetClickAction)handler;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,48 +0,0 @@
|
||||
//
|
||||
// TTActionSheetConfig.m
|
||||
// AFNetworking
|
||||
//
|
||||
// Created by lee on 2019/5/23.
|
||||
//
|
||||
|
||||
#import "TTActionSheetConfig.h"
|
||||
#import "MewThemeColor.h"
|
||||
|
||||
@implementation TTActionSheetConfig
|
||||
|
||||
/**
|
||||
构建 actionSheet item 实例
|
||||
|
||||
@param title 标题
|
||||
@param clickAction 点击事件
|
||||
@return item 实例
|
||||
*/
|
||||
+ (TTActionSheetConfig *)normalTitle:(NSString *)title clickAction:(TTActionSheetClickAction)clickAction {
|
||||
|
||||
return [self normalTitle:title selectColorType:TTItemSelectNormal clickAction:clickAction];
|
||||
}
|
||||
|
||||
+ (TTActionSheetConfig *)normalTitle:(NSString *)title selectColorType:(TTItemSelectType)type clickAction:(TTActionSheetClickAction)clickAction {
|
||||
|
||||
UIColor *color = type == TTItemSelectHighLight ? [MewThemeColor mewAlertTitleColor] : [MewThemeColor mewAlertTitleColor];
|
||||
|
||||
TTActionSheetConfig *config = [self actionWithTitle:title color:color handler:clickAction];
|
||||
config.type = type;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
+ (TTActionSheetConfig *)actionWithTitle:(NSString *)title
|
||||
color:(UIColor *)textColor
|
||||
handler:(TTActionSheetClickAction)handler {
|
||||
|
||||
TTActionSheetConfig *config = [[TTActionSheetConfig alloc] init];
|
||||
config.type = TTItemSelectNormal;
|
||||
config.title = title;
|
||||
config.titleColor = textColor;
|
||||
config.clickAction = handler;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
@end
|
@@ -1,30 +0,0 @@
|
||||
//
|
||||
// TTAlertButtonConfig.h
|
||||
// XC_TTChatViewKit
|
||||
//
|
||||
// Created by lee on 2019/5/21.
|
||||
// Copyright © 2019 YiZhuan. All rights reserved.
|
||||
// alert 按钮配置
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface TTAlertButtonConfig : NSObject
|
||||
/** 按钮标题 */
|
||||
@property (nonatomic, copy) NSString *title;
|
||||
/** 按钮字体 */
|
||||
@property (nonatomic, strong) UIFont *font;
|
||||
/** 按钮字体颜色 */
|
||||
@property (nonatomic, strong) UIColor *titleColor;
|
||||
/** 背景色 */
|
||||
@property (nonatomic, strong) UIColor *backgroundColor;
|
||||
/** 背景图 */
|
||||
@property (nonatomic, strong) UIImage *backgroundImage;
|
||||
/** 圆角 */
|
||||
@property (nonatomic, assign) CGFloat cornerRadius;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,13 +0,0 @@
|
||||
//
|
||||
// TTAlertButtonConfig.m
|
||||
// XC_TTChatViewKit
|
||||
//
|
||||
// Created by lee on 2019/5/21.
|
||||
// Copyright © 2019 YiZhuan. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TTAlertButtonConfig.h"
|
||||
|
||||
@implementation TTAlertButtonConfig
|
||||
|
||||
@end
|
@@ -1,85 +0,0 @@
|
||||
//
|
||||
// TTAlertConfig.h
|
||||
// XC_TTChatViewKit
|
||||
//
|
||||
// Created by lee on 2019/5/20.
|
||||
// Copyright © 2019 YiZhuan. All rights reserved.
|
||||
// alert 配置
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "TTAlertButtonConfig.h"
|
||||
#import "TTAlertMessageAttributedConfig.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef NS_ENUM(NSUInteger, TTAlertActionStyle) {
|
||||
TTAlertActionConfirmStyle = 0, // 只有确定按钮
|
||||
TTAlertActionCancelStyle = 1, // 只有取消按钮
|
||||
TTAlertActionBothStyle = 2, // 全部按钮
|
||||
};
|
||||
|
||||
|
||||
@interface TTAlertConfig : NSObject
|
||||
// 按钮显示风格
|
||||
@property (nonatomic, assign) TTAlertActionStyle actionStyle;
|
||||
// 容器背景设置
|
||||
@property (nonatomic, strong) UIColor *backgroundColor;
|
||||
|
||||
// 标题设置
|
||||
@property (nonatomic, copy) NSString *title;
|
||||
@property (nonatomic, strong) UIFont *titleFont;
|
||||
@property (nonatomic, strong) UIColor *titleColor;
|
||||
|
||||
// 内容设置
|
||||
@property (nonatomic, copy) NSString *message;
|
||||
@property (nonatomic, strong) UIFont *messageFont;
|
||||
@property (nonatomic, strong) UIColor *messageColor;
|
||||
/** 内容的行间距,默认不设置,当值为 0 或负数时无效 */
|
||||
@property (nonatomic, assign) CGFloat messageLineSpacing;
|
||||
/** 内容富文本配置 */
|
||||
@property (nonatomic, strong) NSArray<TTAlertMessageAttributedConfig *> *messageAttributedConfig;
|
||||
///配置内容的富文本
|
||||
@property (nonatomic,strong) NSMutableAttributedString *messageAttributed;
|
||||
|
||||
// 取消按钮配置
|
||||
@property (nonatomic, strong) TTAlertButtonConfig *cancelButtonConfig;
|
||||
|
||||
// 确定按钮配置
|
||||
@property (nonatomic, strong) TTAlertButtonConfig *confirmButtonConfig;
|
||||
|
||||
/**
|
||||
背景蒙层的透明度
|
||||
@Description 默认是 000000 黑色 0.3 alpha
|
||||
*/
|
||||
@property (nonatomic, assign) CGFloat maskBackgroundAlpha;
|
||||
|
||||
// 圆角
|
||||
@property (nonatomic, assign) CGFloat cornerRadius;
|
||||
|
||||
// 点击蒙层是否消失,默认:YES
|
||||
@property (nonatomic, assign) BOOL shouldDismissOnBackgroundTouch;
|
||||
|
||||
/**
|
||||
点击‘确定’‘取消’按钮时禁止弹窗自动消失,默认:NO
|
||||
|
||||
@discussion 若值为 YES,需要主动调用 [TTPopup dismiss] 消除弹窗
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL disableAutoDismissWhenClickButton;
|
||||
|
||||
/**
|
||||
重复弹窗过滤,默认:NO
|
||||
|
||||
@discussion 设置过滤时,队列中将不会出现相同过滤标识的弹窗
|
||||
过滤标识通过 #<filterIdentifier> 设置
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL shouldFilterPopup;
|
||||
|
||||
/**
|
||||
过滤标识,默认:nil
|
||||
*/
|
||||
@property (nonatomic, copy) NSString *filterIdentifier;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,75 +0,0 @@
|
||||
//
|
||||
// TTAlertConfig.m
|
||||
// XC_TTChatViewKit
|
||||
//
|
||||
// Created by lee on 2019/5/20.
|
||||
// Copyright © 2019 YiZhuan. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TTAlertConfig.h"
|
||||
#import "UIImage+MewUtils.h"
|
||||
#import "MewThemeColor.h"
|
||||
|
||||
static CGFloat kAlertTitleFont = 18.f;
|
||||
static CGFloat kAlertButtonFont = 15.f;
|
||||
static CGFloat kAlertMessageFont = 15.f;
|
||||
static CGFloat kAlertCornerRadius = 12.f;
|
||||
static CGFloat kmewAlertBackgroundColorAlpha = 0.3;
|
||||
static CGFloat kAlertMessageFontLineSpace = -1;
|
||||
static CGFloat kAlertButtonCornerRadius = 8.f;
|
||||
|
||||
@implementation TTAlertConfig
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
|
||||
_backgroundColor = [MewThemeColor mewAlertBackgroundColor];
|
||||
|
||||
//背景颜色
|
||||
kAlertTitleFont = 16.f;
|
||||
kAlertCornerRadius = 14.f;
|
||||
kAlertButtonCornerRadius = 19.f;
|
||||
|
||||
_actionStyle = TTAlertActionBothStyle;
|
||||
|
||||
// title
|
||||
_title = @"";// 标题
|
||||
_titleFont = [UIFont fontWithName:@"PingFangSC-Medium" size:kAlertTitleFont];// 字体
|
||||
_titleColor = [MewThemeColor mewAlertTitleColor];// 颜色
|
||||
|
||||
// message
|
||||
_message = @"";
|
||||
_messageFont = [UIFont systemFontOfSize:kAlertMessageFont];// 内容
|
||||
_messageColor = [MewThemeColor mewAlertMessageColor];// 颜色
|
||||
_messageLineSpacing = kAlertMessageFontLineSpace;// 字体行间距
|
||||
_messageAttributedConfig = @[];// 自定义富文本样式
|
||||
|
||||
// cancel button
|
||||
_cancelButtonConfig = [[TTAlertButtonConfig alloc] init];
|
||||
_cancelButtonConfig.title = @"取消";// 取消按钮
|
||||
_cancelButtonConfig.font = [UIFont systemFontOfSize:kAlertButtonFont];// 按钮字体
|
||||
_cancelButtonConfig.titleColor = [MewThemeColor mewCancelButtonTextColor];// 字体颜色
|
||||
_cancelButtonConfig.backgroundImage = [UIImage mew_gradientColorImageFromColors:@[[MewThemeColor mewCancelButtonGradientStartColor], [MewThemeColor mewCancelButtonGradientEndColor]] gradientType:MewGradientTypeLeftToRight imgSize:CGSizeMake(10, 10)];
|
||||
_cancelButtonConfig.cornerRadius = kAlertButtonCornerRadius;// 按钮背景图
|
||||
|
||||
// confirm button
|
||||
_confirmButtonConfig = [[TTAlertButtonConfig alloc] init];
|
||||
_confirmButtonConfig.title = @"确定";
|
||||
_confirmButtonConfig.font = [UIFont systemFontOfSize:kAlertButtonFont];
|
||||
_confirmButtonConfig.titleColor = [MewThemeColor mewConfirmButtonTextColor];
|
||||
_confirmButtonConfig.backgroundImage = [UIImage mew_gradientColorImageFromColors:@[[MewThemeColor mewConfirmButtonGradientStartColor], [MewThemeColor mewConfirmButtonGradientEndColor]] gradientType:MewGradientTypeLeftToRight imgSize:CGSizeMake(10, 10)];
|
||||
_confirmButtonConfig.cornerRadius = kAlertButtonCornerRadius;
|
||||
|
||||
_cornerRadius = kAlertCornerRadius;// 默认圆角
|
||||
_shouldDismissOnBackgroundTouch = YES;// 点击蒙层是否消失
|
||||
|
||||
// mask default 0.3 black
|
||||
_maskBackgroundAlpha = kmewAlertBackgroundColorAlpha; // alert 背景色
|
||||
_disableAutoDismissWhenClickButton = NO;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
@@ -1,34 +0,0 @@
|
||||
//
|
||||
// TTAlertContentAttributedConfig.h
|
||||
// XC_TTChatViewKit
|
||||
//
|
||||
// Created by lee on 2019/5/21.
|
||||
// Copyright © 2019 YiZhuan. All rights reserved.
|
||||
// alert 提示内容富文本配置
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface TTAlertMessageAttributedConfig : NSObject
|
||||
|
||||
/** 富文本字段需要特殊显示的文本 */
|
||||
@property (nonatomic, copy) NSString *text;
|
||||
|
||||
/** 颜色 */
|
||||
@property (nonatomic, strong) UIColor *color;
|
||||
|
||||
/** 字体 */
|
||||
@property (nonatomic, strong) UIFont *font;
|
||||
|
||||
/**
|
||||
目标文本指定位置,一旦设置则无视 text 的值
|
||||
|
||||
@discussion 内容文本中出现相同的目标文本时,可通过设置 range 精确指定位置
|
||||
*/
|
||||
@property (nonatomic, assign) NSRange range;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,13 +0,0 @@
|
||||
//
|
||||
// TTAlertContentAttributedConfig.m
|
||||
// XC_TTChatViewKit
|
||||
//
|
||||
// Created by lee on 2019/5/21.
|
||||
// Copyright © 2019 YiZhuan. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TTAlertMessageAttributedConfig.h"
|
||||
|
||||
@implementation TTAlertMessageAttributedConfig
|
||||
|
||||
@end
|
@@ -1,38 +0,0 @@
|
||||
//
|
||||
// TTPopupConstants.h
|
||||
// XC_TTChatViewKit
|
||||
//
|
||||
// Created by lvjunhang on 2019/5/21.
|
||||
// Copyright © 2019 YiZhuan. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
/**
|
||||
Popup 组件通用回调
|
||||
*/
|
||||
typedef void(^TTPopupCompletionHandler)(void);
|
||||
|
||||
/**
|
||||
弹窗类型
|
||||
|
||||
- TTPopupStyleAlert: Alert
|
||||
- TTPopupStyleActionSheet: ActionSheet
|
||||
*/
|
||||
typedef NS_ENUM(NSUInteger, TTPopupStyle) {
|
||||
TTPopupStyleAlert = 0,
|
||||
TTPopupStyleActionSheet
|
||||
};
|
||||
|
||||
/**
|
||||
弹窗优先级
|
||||
|
||||
- TTPopupPriorityNormal: 普通
|
||||
- TTPopupPriorityHigh: 高
|
||||
- TTPopupPriorityRequired: 必须
|
||||
*/
|
||||
typedef NS_ENUM(NSUInteger, TTPopupPriority) {
|
||||
TTPopupPriorityNormal = 0,
|
||||
TTPopupPriorityHigh,
|
||||
TTPopupPriorityRequired
|
||||
};
|
@@ -1,24 +0,0 @@
|
||||
//
|
||||
// TTPopupManagerService.h
|
||||
// XC_TTChatViewKit
|
||||
//
|
||||
// Created by lvjunhang on 2019/5/21.
|
||||
// Copyright © 2019 YiZhuan. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "TTPopupManagerServiceProtocol.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface TTPopupManagerService : NSObject<TTPopupManagerServiceProtocol>
|
||||
/**
|
||||
当前显示的弹窗服务
|
||||
*/
|
||||
@property (nonatomic, strong) id<TTPopupServiceProtocol> currentPopupService;
|
||||
|
||||
+ (instancetype)sharedInstance;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,200 +0,0 @@
|
||||
//
|
||||
// TTPopupManagerService.m
|
||||
// XC_TTChatViewKit
|
||||
//
|
||||
// Created by lvjunhang on 2019/5/21.
|
||||
// Copyright © 2019 YiZhuan. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TTPopupManagerService.h"
|
||||
|
||||
#import <FFPopup/FFPopup.h>
|
||||
|
||||
@interface TTPopupManagerService ()
|
||||
|
||||
@property (nonatomic, strong) NSMutableArray< id<TTPopupServiceProtocol> > *queue;
|
||||
/**
|
||||
当前是否正在显示状态
|
||||
*/
|
||||
@property (nonatomic, assign, getter=isShowingPopup) BOOL showingPopup;
|
||||
|
||||
@end
|
||||
|
||||
@implementation TTPopupManagerService
|
||||
|
||||
#pragma mark - Life Cycle
|
||||
+ (instancetype)sharedInstance {
|
||||
static TTPopupManagerService *instance = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
instance = [[self alloc] init];
|
||||
});
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
_queue = [NSMutableArray array];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - TTPopupManagerServiceProtocol
|
||||
- (void)addPopupService:(id<TTPopupServiceProtocol>)service {
|
||||
if (![service conformsToProtocol:@protocol(TTPopupServiceProtocol)]) {
|
||||
return;
|
||||
}
|
||||
if ([_queue containsObject:service]) {
|
||||
return;
|
||||
}
|
||||
NSInteger insertPosition = [self insertPositionForPopupService:service];
|
||||
if (insertPosition == NSNotFound) {
|
||||
return;
|
||||
}
|
||||
[_queue insertObject:service atIndex:insertPosition];
|
||||
//当前没有弹窗显示且队列只有一个元素时,显示弹窗
|
||||
if (_currentPopupService == nil && _queue.count == 1) {
|
||||
[self showPopup];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)removePopupService {
|
||||
|
||||
//防止当弹窗还未显示完成,在显示过程中频繁调用 dismiss
|
||||
//使得 _currentPopupService 被清空,导致弹窗无法消失,从而假死现象
|
||||
if (!self.isShowingPopup) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_currentPopupService == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_queue.count > 0) {
|
||||
[_queue removeObjectAtIndex:0];
|
||||
}
|
||||
|
||||
[FFPopup dismissPopupForView:_currentPopupService.contentView animated:YES];
|
||||
_currentPopupService = nil;
|
||||
}
|
||||
|
||||
/**
|
||||
点击蒙层时移除队列中的数据源
|
||||
|
||||
@discussion 注意无需调用 dismissPopupForView
|
||||
*/
|
||||
- (void)removeSourceWhenTouchMaskView {
|
||||
if (_currentPopupService == nil) {
|
||||
return;
|
||||
}
|
||||
if (_queue.count > 0) {
|
||||
[_queue removeObjectAtIndex:0];
|
||||
}
|
||||
_currentPopupService = nil;
|
||||
}
|
||||
|
||||
#pragma mark - Private Methods
|
||||
/**
|
||||
显示弹窗
|
||||
*/
|
||||
- (void)showPopup {
|
||||
if (self.isShowingPopup) {
|
||||
return;
|
||||
}
|
||||
if (_currentPopupService) {
|
||||
return;
|
||||
}
|
||||
if (_queue.count == 0) {
|
||||
return;
|
||||
}
|
||||
id<TTPopupServiceProtocol> popupService = _queue.firstObject;
|
||||
if (![popupService conformsToProtocol:@protocol(TTPopupServiceProtocol)]) {
|
||||
return;
|
||||
}
|
||||
_currentPopupService = popupService;
|
||||
FFPopupHorizontalLayout horizontalLayout = FFPopupHorizontalLayout_Center;
|
||||
FFPopupVerticalLayout verticalLayout = FFPopupVerticalLayout_Center;
|
||||
FFPopupShowType showType = (FFPopupShowType)popupService.showType;
|
||||
FFPopupDismissType dismissType = FFPopupDismissType_GrowOut;
|
||||
if (popupService.style == TTPopupStyleActionSheet) {
|
||||
verticalLayout = FFPopupVerticalLayout_Bottom;
|
||||
showType = FFPopupShowType_SlideInFromBottom;
|
||||
dismissType = FFPopupDismissType_SlideOutToBottom;
|
||||
}
|
||||
FFPopup *popup = [FFPopup popupWithContentView:popupService.contentView];
|
||||
popup.showType = showType;
|
||||
popup.dismissType = dismissType;
|
||||
popup.maskType = FFPopupMaskType_Dimmed;
|
||||
popup.dimmedMaskAlpha = popupService.maskBackgroundAlpha;
|
||||
popup.shouldDismissOnBackgroundTouch = popupService.shouldDismissOnBackgroundTouch;
|
||||
|
||||
[popup showWithLayout:FFPopupLayoutMake(horizontalLayout, verticalLayout) duration:0.0];
|
||||
__weak typeof(self) weakSelf = self;
|
||||
// 不管是调用’dismissPopupForView:animated:‘ 还是‘点击蒙层消除’,最终都会走到这里
|
||||
// 适合在此展示队列中下一个弹窗
|
||||
// 通过 _currentPopupService 是否为空可以判断是哪种消除方式
|
||||
popup.didFinishDismissingBlock = ^{
|
||||
__strong typeof(weakSelf) strongSelf = weakSelf;
|
||||
BOOL isDismissOnBackgroundTouch = strongSelf.currentPopupService != nil;
|
||||
if (isDismissOnBackgroundTouch) {
|
||||
// ‘点击蒙层消除’时,在展现下一个弹窗前移除数据源
|
||||
[self removeSourceWhenTouchMaskView];
|
||||
}
|
||||
if (popupService.didFinishDismissHandler) {
|
||||
popupService.didFinishDismissHandler(isDismissOnBackgroundTouch);
|
||||
}
|
||||
// 弹窗消除结束,更新状态
|
||||
strongSelf.showingPopup = NO;
|
||||
// 显示下一个弹窗
|
||||
[strongSelf showPopup];
|
||||
};
|
||||
|
||||
popup.didFinishShowingBlock = ^{
|
||||
// 开始弹窗,更新状态
|
||||
self.showingPopup = YES;
|
||||
if (popupService.didFinishShowingHandler) {
|
||||
popupService.didFinishShowingHandler();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
弹窗将要插入队列的位置
|
||||
@param service 弹窗服务实例
|
||||
@return 队列的位置
|
||||
*/
|
||||
- (NSInteger)insertPositionForPopupService:(id<TTPopupServiceProtocol>)service {
|
||||
__block NSInteger result = NSNotFound;
|
||||
if (service == nil) {
|
||||
return result;
|
||||
}
|
||||
if (_queue.count == 0) {
|
||||
return 0;
|
||||
}
|
||||
// 设置重复弹窗过滤
|
||||
if (service.shouldFilterPopup && service.filterIdentifier.length > 0) {
|
||||
BOOL filterFlag = NO;
|
||||
for (id<TTPopupServiceProtocol> serv in _queue) {
|
||||
if ([serv.filterIdentifier isEqualToString:service.filterIdentifier]) {
|
||||
filterFlag = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (filterFlag) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
[_queue enumerateObjectsUsingBlock:^(id<TTPopupServiceProtocol> _Nonnull model, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
// 找到队中比当前弹窗优先级低的位置
|
||||
if (service.priority > model.priority) {
|
||||
result = idx;
|
||||
*stop = YES;
|
||||
}
|
||||
}];
|
||||
// 如果没有合适的位置,则将新的弹窗放在队尾
|
||||
result = MIN(result, _queue.count);
|
||||
return result;
|
||||
}
|
||||
|
||||
@end
|
@@ -1,25 +0,0 @@
|
||||
//
|
||||
// TTPopupManagerServiceProtocol.h
|
||||
// XC_TTChatViewKit
|
||||
//
|
||||
// Created by lvjunhang on 2019/5/21.
|
||||
// Copyright © 2019 YiZhuan. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TTPopupServiceProtocol.h"
|
||||
|
||||
@protocol TTPopupManagerServiceProtocol <NSObject>
|
||||
|
||||
/**
|
||||
添加一个弹窗
|
||||
|
||||
@param service 服从弹窗服务的实例
|
||||
*/
|
||||
- (void)addPopupService:(id<TTPopupServiceProtocol>)service;
|
||||
|
||||
/**
|
||||
移除一个弹窗
|
||||
*/
|
||||
- (void)removePopupService;
|
||||
|
||||
@end
|
@@ -1,22 +0,0 @@
|
||||
//
|
||||
// TTPopupService.h
|
||||
// XC_TTChatViewKit
|
||||
//
|
||||
// Created by lvjunhang on 2019/5/21.
|
||||
// Copyright © 2019 YiZhuan. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "TTPopupServiceProtocol.h"
|
||||
|
||||
// TTPopupConfig 是 TTPopupService 的别称
|
||||
// 具体信息见 TTPopupService
|
||||
#define TTPopupConfig TTPopupService
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface TTPopupService : NSObject<TTPopupServiceProtocol>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,36 +0,0 @@
|
||||
//
|
||||
// TTPopupService.m
|
||||
// XC_TTChatViewKit
|
||||
//
|
||||
// Created by lvjunhang on 2019/5/21.
|
||||
// Copyright © 2019 YiZhuan. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TTPopupService.h"
|
||||
|
||||
@implementation TTPopupService
|
||||
|
||||
@synthesize style = _style;
|
||||
@synthesize priority = _priority;
|
||||
@synthesize contentView = _contentView;
|
||||
@synthesize maskBackgroundAlpha = _maskBackgroundAlpha;
|
||||
@synthesize shouldDismissOnBackgroundTouch = _shouldDismissOnBackgroundTouch;
|
||||
@synthesize didFinishDismissHandler = _didFinishDismissHandler;
|
||||
@synthesize didFinishShowingHandler = _didFinishShowingHandler;
|
||||
@synthesize shouldFilterPopup = _shouldFilterPopup;
|
||||
@synthesize filterIdentifier = _filterIdentifier;
|
||||
@synthesize showType = _showType;
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_style = TTPopupStyleAlert;
|
||||
_priority = TTPopupPriorityNormal;
|
||||
_maskBackgroundAlpha = 0.5;
|
||||
_shouldDismissOnBackgroundTouch = YES;
|
||||
_shouldFilterPopup = NO;
|
||||
_showType = TTPopupShowTypeDefault;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
@@ -1,78 +0,0 @@
|
||||
//
|
||||
// TTPopupServiceProtocol.h
|
||||
// XC_TTChatViewKit
|
||||
//
|
||||
// Created by lvjunhang on 2019/5/21.
|
||||
// Copyright © 2019 YiZhuan. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TTPopupConstants.h"
|
||||
|
||||
typedef NS_ENUM(NSUInteger, TTPopupShowType) {
|
||||
TTPopupShowType_FadeIn = 1,
|
||||
TTPopupShowTypeDefault = 8,
|
||||
};
|
||||
|
||||
@class UIView;
|
||||
|
||||
@protocol TTPopupServiceProtocol <NSObject>
|
||||
|
||||
/**
|
||||
弹窗样式,默认:TTPopupStyleAlert
|
||||
*/
|
||||
@property (nonatomic, assign) TTPopupStyle style;
|
||||
|
||||
/**
|
||||
弹窗优先级权重,默认:TTPopupPriorityNormal
|
||||
|
||||
@discussion 权重越高在弹窗队列的优先级越高,即优先弹出;相同权重按先来后到原则
|
||||
*/
|
||||
@property (nonatomic, assign) TTPopupPriority priority;
|
||||
|
||||
/**
|
||||
自定义视图内容,默认:nil
|
||||
|
||||
@discussion 如果未配置,或 contentView 未继承自 UIView 及其子类,将忽略该弹窗
|
||||
*/
|
||||
@property (nonatomic, strong) UIView *contentView;
|
||||
|
||||
/**
|
||||
背景蒙层透明度,默认:0x000000 0.3 alpha
|
||||
|
||||
@discussion 由于第三方原因,暂不支持蒙层颜色修改
|
||||
*/
|
||||
@property (nonatomic, assign) CGFloat maskBackgroundAlpha;
|
||||
|
||||
/**
|
||||
点击蒙层是否消除弹窗,默认:YES
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL shouldDismissOnBackgroundTouch;
|
||||
|
||||
/**
|
||||
弹窗消失回调,isDismissOnBackgroundTouch 区分是否点击蒙层触发
|
||||
*/
|
||||
@property (nonatomic, copy) void (^didFinishDismissHandler)(BOOL isDismissOnBackgroundTouch);
|
||||
|
||||
/**
|
||||
弹窗显示成功回调
|
||||
*/
|
||||
@property (nonatomic, copy) void (^didFinishShowingHandler)(void);
|
||||
|
||||
/**
|
||||
重复弹窗过滤,默认:NO
|
||||
|
||||
@discussion 设置过滤时,队列中将不会出现相同过滤标识的弹窗
|
||||
过滤标识通过 #<filterIdentifier> 设置
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL shouldFilterPopup;
|
||||
|
||||
/**
|
||||
过滤标识,默认:nil
|
||||
*/
|
||||
@property (nonatomic, copy) NSString *filterIdentifier;
|
||||
|
||||
/**
|
||||
显示动画类型, 默认是 default
|
||||
*/
|
||||
@property (nonatomic, assign) TTPopupShowType showType;
|
||||
@end
|
@@ -1,126 +0,0 @@
|
||||
//
|
||||
// TTPopup.h
|
||||
// XC_TTChatViewKit
|
||||
//
|
||||
// Created by lvjunhang on 2019/5/22.
|
||||
// Copyright © 2019 YiZhuan. All rights reserved.
|
||||
// 弹窗工具类
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "TTPopupConstants.h"
|
||||
#import "TTAlertConfig.h"
|
||||
#import "TTActionSheetConfig.h"
|
||||
#import "TTPopupService.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class UIView;
|
||||
|
||||
@interface TTPopup : NSObject
|
||||
|
||||
#pragma mark Alert
|
||||
/**
|
||||
显示 alert 弹窗
|
||||
|
||||
@discussion 显示四个内容:默认标题‘提示’,提示内容,取消按钮,确认按钮
|
||||
|
||||
@param message 提示内容,不能为空(⊙o⊙)哦
|
||||
@param confirmHandler 确认操作
|
||||
@param cancelHandler 取消操作
|
||||
*/
|
||||
+ (void)alertWithMessage:(NSString *)message
|
||||
confirmHandler:(TTPopupCompletionHandler)confirmHandler
|
||||
cancelHandler:(TTPopupCompletionHandler)cancelHandler;
|
||||
|
||||
|
||||
/**
|
||||
显示 alert 弹窗
|
||||
|
||||
@discussion 显示四个内容:默认标题‘提示’,提示内容,取消按钮,确认按钮
|
||||
|
||||
@param config 完善的视图配置,为您变态的需求保驾护航
|
||||
@param isShowBorder 是否显示边框
|
||||
@param confirmHandler 确认操作
|
||||
@param cancelHandler 取消操作
|
||||
*/
|
||||
+ (void)alertWithConfig:(TTAlertConfig *)config
|
||||
showBorder:(BOOL)isShowBorder
|
||||
confirmHandler:(TTPopupCompletionHandler)confirmHandler
|
||||
cancelHandler:(TTPopupCompletionHandler)cancelHandler;
|
||||
|
||||
|
||||
|
||||
+ (void)alertWithMessage:(NSString *)message
|
||||
config:(TTAlertConfig *)config
|
||||
showBorder:(BOOL)isShowBorder
|
||||
cancelHandler:(TTPopupCompletionHandler)cancelHandler
|
||||
confirmHandler:(TTPopupCompletionHandler)confirmHandler;
|
||||
|
||||
/**
|
||||
显示 alert 弹窗
|
||||
@discussion 显示四个内容:标题,提示内容,取消按钮,确认按钮
|
||||
@param config 完善的视图配置,为您变态的需求保驾护航
|
||||
@param cancelHandler 取消操作
|
||||
@param confirmHandler 确认操作
|
||||
*/
|
||||
+ (void)alertWithConfig:(TTAlertConfig *)config
|
||||
confirmHandler:(TTPopupCompletionHandler)confirmHandler
|
||||
cancelHandler:(TTPopupCompletionHandler)cancelHandler;
|
||||
|
||||
#pragma mark Action Sheet
|
||||
/**
|
||||
显示 action sheet 弹窗,自带贴心的取消按钮😊
|
||||
|
||||
@param items 配置列表
|
||||
*/
|
||||
+ (void)actionSheetWithItems:(NSArray<TTActionSheetConfig *> *)items;
|
||||
|
||||
/**
|
||||
显示 action sheet 弹窗
|
||||
|
||||
@param items 配置列表
|
||||
@param showCancelItem 是否显示取消按钮
|
||||
*/
|
||||
+ (void)actionSheetWithItems:(NSArray<TTActionSheetConfig *> *)items
|
||||
showCancelItem:(BOOL)showCancelItem;
|
||||
|
||||
/**
|
||||
显示 action sheet 弹窗
|
||||
|
||||
@param items 配置列表
|
||||
@param cancelHandler 取消按钮回调
|
||||
*/
|
||||
+ (void)actionSheetWithItems:(NSArray<TTActionSheetConfig *> *)items
|
||||
cancelHandler:(TTActionSheetClickAction)cancelHandler;
|
||||
|
||||
#pragma mark Popup
|
||||
/**
|
||||
显示自定义弹窗
|
||||
@param customView 自定义 view
|
||||
@param style 弹窗样式
|
||||
*/
|
||||
+ (void)popupView:(UIView *)customView
|
||||
style:(TTPopupStyle)style;
|
||||
|
||||
/**
|
||||
显示自定义弹窗
|
||||
|
||||
@param config 自定义弹窗配置
|
||||
*/
|
||||
+ (void)popupWithConfig:(TTPopupService *)config;
|
||||
|
||||
#pragma mark Dismiss
|
||||
/**
|
||||
消除当前弹窗
|
||||
*/
|
||||
+ (void)dismiss;
|
||||
|
||||
#pragma mark Query
|
||||
/**
|
||||
当前是否有显示弹窗
|
||||
*/
|
||||
+ (BOOL)hasShowPopup;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,237 +0,0 @@
|
||||
//
|
||||
// TTPopup.m
|
||||
// XC_TTChatViewKit
|
||||
//
|
||||
// Created by lvjunhang on 2019/5/22.
|
||||
// Copyright © 2019 YiZhuan. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TTPopup.h"
|
||||
#import "TTAlertView.h"
|
||||
#import "TTActionSheetView.h"
|
||||
#import "TTPopupService.h"
|
||||
#import "TTPopupManagerService.h"
|
||||
|
||||
static CGFloat const kActionSheetViewPadding = 15.f;
|
||||
static CGFloat const kActionSheetViewCellHeight = 52.f;
|
||||
static CGFloat const kActionSheetViewCancelViewHeight = 67.f;
|
||||
static CGFloat const kActionSheetViewBottomPadding = 15.f;
|
||||
static CGFloat const kMixHeight = 200.f;
|
||||
static CGFloat const kMaxHeight = 450.f;
|
||||
|
||||
@implementation TTPopup
|
||||
|
||||
#pragma mark - Public Methods
|
||||
#pragma mark Alert
|
||||
+ (void)alertWithMessage:(NSString *)message
|
||||
confirmHandler:(TTPopupCompletionHandler)confirmHandler
|
||||
cancelHandler:(TTPopupCompletionHandler)cancelHandler {
|
||||
|
||||
[self alertWithMessage:message
|
||||
config:nil
|
||||
cancelHandler:cancelHandler
|
||||
confirmHandler:confirmHandler];
|
||||
}
|
||||
|
||||
+ (void)alertWithConfig:(TTAlertConfig *)config
|
||||
confirmHandler:(TTPopupCompletionHandler)confirmHandler
|
||||
cancelHandler:(TTPopupCompletionHandler)cancelHandler {
|
||||
|
||||
[self alertWithMessage:nil
|
||||
config:config
|
||||
cancelHandler:cancelHandler
|
||||
confirmHandler:confirmHandler];
|
||||
}
|
||||
|
||||
+ (void)alertWithMessage:(NSString *)message
|
||||
config:(TTAlertConfig *)config
|
||||
cancelHandler:(TTPopupCompletionHandler)cancelHandler
|
||||
confirmHandler:(TTPopupCompletionHandler)confirmHandler {
|
||||
|
||||
if (!config) {
|
||||
config = [[TTAlertConfig alloc] init];
|
||||
config.message = message;
|
||||
}
|
||||
|
||||
if (config.message.length <= 0 && config.messageAttributed.length <=0 && config.messageAttributedConfig.count <=0) {
|
||||
NSAssert(NO, @" message can not be nil, 弹窗文案不可以为空");
|
||||
return;
|
||||
}
|
||||
CGFloat width = [UIScreen mainScreen].bounds.size.width - 40 * 2;
|
||||
CGFloat height = ([self messageSize:config.message width:width].height + 160);
|
||||
// 最小 200, 最大 450
|
||||
if (height < kMixHeight) {
|
||||
height = kMixHeight;
|
||||
} else if (height > kMaxHeight) {
|
||||
height = kMaxHeight;
|
||||
}
|
||||
TTAlertView *contentView = [[TTAlertView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
|
||||
contentView.config = config;
|
||||
contentView.isConfigBoard = NO;
|
||||
contentView.cancelAction = cancelHandler;
|
||||
contentView.confirmAction = confirmHandler;
|
||||
if (!contentView.config.disableAutoDismissWhenClickButton) {
|
||||
// 设置弹窗按钮自动消除
|
||||
contentView.dismissAction = ^{
|
||||
[TTPopup dismiss];
|
||||
};
|
||||
}
|
||||
[self popupView:contentView style:TTPopupStyleAlert config:config];
|
||||
}
|
||||
|
||||
+ (void)alertWithConfig:(TTAlertConfig *)config
|
||||
showBorder:(BOOL)isShowBorder
|
||||
confirmHandler:(TTPopupCompletionHandler)confirmHandler
|
||||
cancelHandler:(TTPopupCompletionHandler)cancelHandler {
|
||||
[self alertWithMessage:nil
|
||||
config:config
|
||||
showBorder:isShowBorder
|
||||
cancelHandler:cancelHandler
|
||||
confirmHandler:confirmHandler];
|
||||
}
|
||||
|
||||
+ (void)alertWithMessage:(NSString *)message
|
||||
config:(TTAlertConfig *)config
|
||||
showBorder:(BOOL)isShowBorder
|
||||
cancelHandler:(TTPopupCompletionHandler)cancelHandler
|
||||
confirmHandler:(TTPopupCompletionHandler)confirmHandler {
|
||||
|
||||
if (!config) {
|
||||
config = [[TTAlertConfig alloc] init];
|
||||
config.message = message;
|
||||
}
|
||||
|
||||
if (config.message.length <= 0) {
|
||||
NSAssert(NO, @" message can not be nil, 弹窗文案不可以为空");
|
||||
return;
|
||||
}
|
||||
|
||||
CGFloat width = [UIScreen mainScreen].bounds.size.width - 40 * 2;
|
||||
CGFloat height = ([self messageSize:config.message width:width].height + 160);
|
||||
|
||||
// 最小 200, 最大 450
|
||||
if (height < kMixHeight) {
|
||||
height = kMixHeight;
|
||||
} else if (height > kMaxHeight) {
|
||||
height = kMaxHeight;
|
||||
}
|
||||
|
||||
TTAlertView *contentView = [[TTAlertView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
|
||||
contentView.config = config;
|
||||
contentView.cancelAction = cancelHandler;
|
||||
contentView.confirmAction = confirmHandler;
|
||||
contentView.isConfigBoard = isShowBorder;
|
||||
|
||||
if (!contentView.config.disableAutoDismissWhenClickButton) {
|
||||
// 设置弹窗按钮自动消除
|
||||
contentView.dismissAction = ^{
|
||||
[TTPopup dismiss];
|
||||
};
|
||||
}
|
||||
|
||||
[self popupView:contentView style:TTPopupStyleAlert config:config];
|
||||
}
|
||||
|
||||
#pragma mark Action Sheet
|
||||
+ (void)actionSheetWithItems:(NSArray<TTActionSheetConfig *> *)items {
|
||||
|
||||
[TTPopup actionSheetWithItems:items showCancelItem:YES cancelHandler:nil];
|
||||
}
|
||||
|
||||
+ (void)actionSheetWithItems:(NSArray<TTActionSheetConfig *> *)items
|
||||
showCancelItem:(BOOL)showCancelItem {
|
||||
|
||||
[TTPopup actionSheetWithItems:items showCancelItem:showCancelItem cancelHandler:nil];
|
||||
}
|
||||
|
||||
+ (void)actionSheetWithItems:(NSArray<TTActionSheetConfig *> *)items cancelHandler:(TTActionSheetClickAction)cancelHandler {
|
||||
|
||||
[TTPopup actionSheetWithItems:items showCancelItem:YES cancelHandler:cancelHandler];
|
||||
}
|
||||
|
||||
+ (void)actionSheetWithItems:(NSArray<TTActionSheetConfig *> *)items
|
||||
showCancelItem:(BOOL)showCancelItem
|
||||
cancelHandler:(TTActionSheetClickAction)cancelHandler {
|
||||
|
||||
CGFloat width = [UIScreen mainScreen].bounds.size.width - kActionSheetViewPadding * 2;
|
||||
CGFloat height = kActionSheetViewCellHeight * items.count + kActionSheetViewBottomPadding;
|
||||
|
||||
// 如果需要显示取消按钮则增加响应的高度
|
||||
if (showCancelItem) {
|
||||
// 按钮的高度和间距
|
||||
height += kActionSheetViewCancelViewHeight;
|
||||
}
|
||||
|
||||
if (@available(iOS 11.0, *)) {
|
||||
// 如果是 iPhone X 系列(刘海屏幕系列) 底部则需要添加 34 的高度
|
||||
height += [UIApplication sharedApplication].keyWindow.safeAreaInsets.bottom;
|
||||
}
|
||||
|
||||
CGRect rect = CGRectMake(0, 0, width, height);
|
||||
|
||||
TTActionSheetView *sheetView = [[TTActionSheetView alloc] initWithFrame:rect
|
||||
needCancel:showCancelItem
|
||||
items:items];
|
||||
sheetView.cancelAction = cancelHandler;
|
||||
|
||||
// 设置弹窗按钮自动消除
|
||||
sheetView.dismissAction = ^{
|
||||
[TTPopup dismiss];
|
||||
};
|
||||
|
||||
[self popupView:sheetView style:TTPopupStyleActionSheet];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Popup
|
||||
+ (void)popupView:(UIView *)customView
|
||||
style:(TTPopupStyle)style {
|
||||
|
||||
TTPopupService *service = [[TTPopupService alloc] init];
|
||||
service.style = style;
|
||||
service.contentView = customView;
|
||||
|
||||
[self popupWithConfig:service];
|
||||
}
|
||||
|
||||
+ (void)popupView:(UIView *)customView
|
||||
style:(TTPopupStyle)style
|
||||
config:(TTAlertConfig *)config {
|
||||
|
||||
TTPopupService *service = [[TTPopupService alloc] init];
|
||||
service.style = style;
|
||||
service.contentView = customView;
|
||||
service.shouldDismissOnBackgroundTouch = config.shouldDismissOnBackgroundTouch;
|
||||
service.maskBackgroundAlpha = config.maskBackgroundAlpha;
|
||||
[self popupWithConfig:service];
|
||||
}
|
||||
|
||||
|
||||
+ (void)popupWithConfig:(TTPopupService *)config {
|
||||
if (![config.contentView isKindOfClass:UIView.class]) {
|
||||
NSAssert(NO, @"TTPopup customView should inherit from UIView.");
|
||||
return;
|
||||
}
|
||||
[[TTPopupManagerService sharedInstance] addPopupService:config];
|
||||
}
|
||||
|
||||
#pragma mark Dismiss
|
||||
+ (void)dismiss {
|
||||
[[TTPopupManagerService sharedInstance] removePopupService];
|
||||
}
|
||||
|
||||
#pragma mark Query
|
||||
/**
|
||||
当前是否有显示弹窗
|
||||
*/
|
||||
+ (BOOL)hasShowPopup {
|
||||
return [TTPopupManagerService sharedInstance].currentPopupService != nil;
|
||||
}
|
||||
|
||||
#pragma mark - Privite
|
||||
+ (CGSize)messageSize:(NSString *)text width:(CGFloat)width {
|
||||
CGRect stringRect = [text boundingRectWithSize:CGSizeMake(width - 2 * 20, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:15.f]} context:nil];
|
||||
return stringRect.size;
|
||||
}
|
||||
|
||||
@end
|
@@ -1,26 +0,0 @@
|
||||
//
|
||||
// TTActionSheetView.h
|
||||
// XC_TTChatViewKit
|
||||
//
|
||||
// Created by lee on 2019/5/22.
|
||||
// Copyright © 2019 YiZhuan. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "TTPopupConstants.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class TTActionSheetConfig;
|
||||
|
||||
@interface TTActionSheetView : UIView
|
||||
|
||||
@property (nonatomic, copy) TTPopupCompletionHandler cancelAction;
|
||||
@property (nonatomic, copy) TTPopupCompletionHandler dismissAction;
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
needCancel:(BOOL)needCancel
|
||||
items:(NSArray<TTActionSheetConfig *> *)items;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,135 +0,0 @@
|
||||
//
|
||||
// TTActionSheetView.m
|
||||
// XC_TTChatViewKit
|
||||
//
|
||||
// Created by lee on 2019/5/22.
|
||||
// Copyright © 2019 YiZhuan. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TTActionSheetView.h"
|
||||
#import "TTActionSheetConfig.h"
|
||||
#import "MewThemeColor.h"
|
||||
#import <Masonry/Masonry.h>
|
||||
|
||||
static CGFloat const kSheetViewCellHeight = 51.f;
|
||||
static CGFloat const kSheetViewCornerRadius = 14.f;
|
||||
static NSString *const kSheetViewCellConst = @"kSheetViewCellConst";
|
||||
|
||||
@interface TTActionSheetView ()<UITableViewDelegate, UITableViewDataSource>
|
||||
|
||||
/** sheetView 载体 */
|
||||
@property (nonatomic, strong) UITableView *tableView;
|
||||
/** 数据源 */
|
||||
@property (nonatomic, strong) NSArray<TTActionSheetConfig *> *items;
|
||||
/** 是否需要显示取消按钮 */
|
||||
@property (nonatomic, assign) BOOL needCancel;
|
||||
/** 取消按钮 */
|
||||
@property (nonatomic, strong) UIButton *cancelButton;
|
||||
|
||||
@end
|
||||
|
||||
@implementation TTActionSheetView
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark lifeCycle
|
||||
- (instancetype)initWithFrame:(CGRect)frame needCancel:(BOOL)needCancel items:(NSArray<TTActionSheetConfig *> *)items {
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
_items = items;
|
||||
_needCancel = needCancel;
|
||||
[self mew_initViews];
|
||||
[self initConstraints];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)mew_initViews {
|
||||
[self addSubview:self.tableView];
|
||||
[self addSubview:self.cancelButton];
|
||||
}
|
||||
|
||||
- (void)initConstraints {
|
||||
|
||||
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.right.top.mas_equalTo(self);
|
||||
make.height.mas_equalTo(self.items.count * kSheetViewCellHeight);
|
||||
}];
|
||||
|
||||
if (_needCancel) {
|
||||
// 显示 cancel view
|
||||
self.cancelButton.hidden = NO;
|
||||
[self.cancelButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.right.mas_equalTo(self);
|
||||
make.height.mas_equalTo(kSheetViewCellHeight);
|
||||
make.top.mas_equalTo(self.tableView.mas_bottom).offset(15);
|
||||
}];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
||||
return 1;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||
return self.items.count;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kSheetViewCellConst];
|
||||
cell.backgroundColor = UIColor.clearColor;
|
||||
cell.textLabel.textAlignment = NSTextAlignmentCenter;
|
||||
cell.textLabel.text = _items[indexPath.row].title;
|
||||
cell.textLabel.textColor = _items[indexPath.row].titleColor;
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
[tableView deselectRowAtIndexPath:indexPath animated:YES];
|
||||
|
||||
// 配置中的事件处理
|
||||
TTActionSheetConfig *config = _items[indexPath.row];
|
||||
!config.clickAction ?: config.clickAction();
|
||||
|
||||
!_dismissAction ?: _dismissAction();
|
||||
}
|
||||
|
||||
- (void)onClickCancelButtonAction:(UIButton *)cancelButton {
|
||||
!_cancelAction ?: _cancelAction();
|
||||
!_dismissAction ?: _dismissAction();
|
||||
}
|
||||
|
||||
- (UITableView *)tableView {
|
||||
if (!_tableView) {
|
||||
_tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
|
||||
_tableView.delegate = self;
|
||||
_tableView.dataSource = self;
|
||||
_tableView.separatorColor = [MewThemeColor mewActionSeparatorColor];
|
||||
_tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
|
||||
_tableView.rowHeight = kSheetViewCellHeight;
|
||||
_tableView.tableFooterView = [[UIView alloc] init];
|
||||
_tableView.backgroundColor = [UIColor whiteColor];
|
||||
_tableView.layer.cornerRadius = kSheetViewCornerRadius;
|
||||
_tableView.layer.masksToBounds = YES;
|
||||
_tableView.bounces = NO;
|
||||
[_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:kSheetViewCellConst];
|
||||
}
|
||||
return _tableView;
|
||||
}
|
||||
|
||||
- (UIButton *)cancelButton {
|
||||
if (!_cancelButton) {
|
||||
_cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
[_cancelButton setTitle:@"取消" forState:UIControlStateNormal];
|
||||
[_cancelButton setBackgroundColor:UIColor.whiteColor];
|
||||
[_cancelButton setTitleColor:[MewThemeColor mewAlertMessageColor] forState:UIControlStateNormal];
|
||||
[_cancelButton.titleLabel setFont:[UIFont systemFontOfSize:16]];
|
||||
_cancelButton.layer.cornerRadius = kSheetViewCornerRadius;
|
||||
_cancelButton.layer.masksToBounds = YES;
|
||||
[_cancelButton addTarget:self action:@selector(onClickCancelButtonAction:) forControlEvents:UIControlEventTouchUpInside];
|
||||
_cancelButton.hidden = YES;
|
||||
}
|
||||
return _cancelButton;
|
||||
}
|
||||
|
||||
@end
|
@@ -1,25 +0,0 @@
|
||||
//
|
||||
// TTAlertView.h
|
||||
// XC_TTChatViewKit
|
||||
//
|
||||
// Created by lee on 2019/5/20.
|
||||
// Copyright © 2019 YiZhuan. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "TTPopupConstants.h"
|
||||
|
||||
@class TTAlertConfig;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface TTAlertView : UIView
|
||||
@property (nonatomic, strong) TTAlertConfig *config;// 配置
|
||||
@property (nonatomic, assign) BOOL isConfigBoard;// 是否配置边框
|
||||
@property (nonatomic, copy) TTPopupCompletionHandler cancelAction;
|
||||
@property (nonatomic, copy) TTPopupCompletionHandler confirmAction;
|
||||
@property (nonatomic, copy) TTPopupCompletionHandler dismissAction;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,250 +0,0 @@
|
||||
//
|
||||
// TTAlertView.m
|
||||
// XC_TTChatViewKit
|
||||
//
|
||||
// Created by lee on 2019/5/20.
|
||||
// Copyright © 2019 YiZhuan. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TTAlertView.h"
|
||||
#import "TTAlertConfig.h"
|
||||
#import "MewThemeColor.h"
|
||||
#import <Masonry/Masonry.h>
|
||||
|
||||
static CGFloat const kMargin = 25.f;
|
||||
static CGFloat const kPadding = 20.f;
|
||||
static CGFloat const kBtnHeight = 38.f;
|
||||
|
||||
@interface TTAlertView ()
|
||||
|
||||
@property (nonatomic, strong) UILabel *titleLabel; // 标题
|
||||
@property (nonatomic, strong) UILabel *messageLabel; // 内容
|
||||
@property (nonatomic, strong) UIButton *cancelButton; // 取消按钮
|
||||
@property (nonatomic, strong) UIButton *confirmButton; // 确认按钮
|
||||
@property (nonatomic, strong) UIStackView *stackView;
|
||||
|
||||
@end
|
||||
|
||||
@implementation TTAlertView
|
||||
|
||||
#pragma mark - lifeCyle
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
[self mew_initViews];
|
||||
[self initConstraints];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)mew_initViews {
|
||||
[self addSubview:self.titleLabel];
|
||||
[self addSubview:self.messageLabel];
|
||||
[self addSubview:self.stackView];
|
||||
[self.stackView addSubview:self.cancelButton];
|
||||
[self.stackView addSubview:self.confirmButton];
|
||||
}
|
||||
|
||||
- (void)initConstraints {
|
||||
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.centerX.mas_equalTo(self);
|
||||
make.top.mas_equalTo(kPadding);
|
||||
make.left.right.mas_equalTo(self).inset(kPadding);
|
||||
}];
|
||||
|
||||
[self.messageLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.mas_equalTo(self.titleLabel.mas_bottom).offset(kMargin);
|
||||
make.left.right.mas_equalTo(self).inset(kPadding);
|
||||
}];
|
||||
|
||||
[self.stackView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.bottom.mas_equalTo(-kPadding);
|
||||
make.centerX.mas_equalTo(self);
|
||||
}];
|
||||
|
||||
[self.cancelButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.height.mas_equalTo(kBtnHeight);
|
||||
make.width.mas_equalTo(self.mas_width).multipliedBy(0.4);
|
||||
}];
|
||||
|
||||
[self.confirmButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.height.mas_equalTo(kBtnHeight);
|
||||
make.width.mas_equalTo(self.mas_width).multipliedBy(0.4);
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Button Events
|
||||
- (void)onClickmew_confirmButtonAction:(UIButton *)confirmButton {
|
||||
!_confirmAction ?: _confirmAction();
|
||||
!_dismissAction ?: _dismissAction();
|
||||
}
|
||||
|
||||
- (void)onClickCancelButtonAction:(UIButton *)cancelButton {
|
||||
!_cancelAction ?: _cancelAction();
|
||||
!_dismissAction ?: _dismissAction();
|
||||
}
|
||||
|
||||
#pragma mark - private method
|
||||
/**
|
||||
设置 messageLabel 需要显示的富文本效果
|
||||
@param config 弹窗配置
|
||||
@return 富文本内容
|
||||
*/
|
||||
- (NSMutableAttributedString *)messageAttributeString:(TTAlertConfig *)config {
|
||||
NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:config.message];
|
||||
if (config.messageLineSpacing > 0) { // 行间距
|
||||
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
|
||||
paragraphStyle.lineSpacing = config.messageLineSpacing;
|
||||
paragraphStyle.alignment = self.messageLabel.textAlignment;
|
||||
[attString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, config.message.length)];
|
||||
}
|
||||
|
||||
// 富文本显示效果
|
||||
[config.messageAttributedConfig enumerateObjectsUsingBlock:^(TTAlertMessageAttributedConfig * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
// 遍历数组,添加展示富文本效果
|
||||
if ([obj isKindOfClass:[TTAlertMessageAttributedConfig class]]) {
|
||||
if (obj.text && obj.text.length > 0) {
|
||||
NSRange range = [config.message rangeOfString:obj.text];
|
||||
// 如果外部指定了 range 。就不用查找出的 range
|
||||
if (obj.range.length != 0) {
|
||||
if (obj.range.location + obj.range.length > config.message.length) {
|
||||
NSAssert(NO, @"obj.range out of bounds");
|
||||
return;
|
||||
}
|
||||
range = obj.range;
|
||||
}
|
||||
if (obj.font) { // 字体
|
||||
[attString addAttribute:NSFontAttributeName value:obj.font range:range];
|
||||
}
|
||||
if (obj.color) { // 颜色
|
||||
[attString addAttribute:NSForegroundColorAttributeName value:obj.color range:range];
|
||||
}
|
||||
}
|
||||
}
|
||||
}];
|
||||
return attString;
|
||||
}
|
||||
|
||||
#pragma mark - getter && setter
|
||||
|
||||
- (void)setConfig:(TTAlertConfig *)config {
|
||||
_config = config;
|
||||
// cornerRadius
|
||||
if (config.cornerRadius > 0) {
|
||||
self.layer.cornerRadius = config.cornerRadius;
|
||||
self.layer.masksToBounds = YES;
|
||||
}
|
||||
//背景
|
||||
self.backgroundColor = config.backgroundColor;
|
||||
// title
|
||||
_titleLabel.text = config.title;
|
||||
_titleLabel.textColor = config.titleColor;
|
||||
_titleLabel.font = config.titleFont;
|
||||
|
||||
_cancelButton.hidden = config.actionStyle == TTAlertActionConfirmStyle;
|
||||
_confirmButton.hidden = config.actionStyle == TTAlertActionCancelStyle;
|
||||
|
||||
// cancel button
|
||||
[_cancelButton setTitle:config.cancelButtonConfig.title forState:UIControlStateNormal];
|
||||
[_cancelButton setTitleColor:config.cancelButtonConfig.titleColor forState:UIControlStateNormal];
|
||||
[_cancelButton.titleLabel setFont:config.cancelButtonConfig.font];
|
||||
[_cancelButton setBackgroundColor:config.cancelButtonConfig.backgroundColor];
|
||||
[_cancelButton setBackgroundImage:config.cancelButtonConfig.backgroundImage forState:UIControlStateNormal];
|
||||
if (config.cancelButtonConfig.cornerRadius > 0) {
|
||||
_cancelButton.layer.cornerRadius = config.cancelButtonConfig.cornerRadius;
|
||||
_cancelButton.layer.masksToBounds = YES;
|
||||
}
|
||||
|
||||
// confirm button
|
||||
[_confirmButton setTitle:config.confirmButtonConfig.title forState:UIControlStateNormal];
|
||||
[_confirmButton setTitleColor:config.confirmButtonConfig.titleColor forState:UIControlStateNormal];
|
||||
[_confirmButton.titleLabel setFont:config.confirmButtonConfig.font];
|
||||
[_confirmButton setBackgroundColor:config.confirmButtonConfig.backgroundColor];
|
||||
[_confirmButton setBackgroundImage:config.confirmButtonConfig.backgroundImage forState:UIControlStateNormal];
|
||||
if (config.confirmButtonConfig.cornerRadius > 0) {
|
||||
_confirmButton.layer.cornerRadius = config.confirmButtonConfig.cornerRadius;
|
||||
_confirmButton.layer.masksToBounds = YES;
|
||||
}
|
||||
|
||||
// message
|
||||
_messageLabel.font = config.messageFont;
|
||||
_messageLabel.textColor = config.messageColor;
|
||||
|
||||
if (config.messageAttributedConfig.count > 0) {
|
||||
_messageLabel.attributedText = [self messageAttributeString:config];
|
||||
_messageLabel.textAlignment = NSTextAlignmentCenter;
|
||||
} else if(config.messageAttributed.length > 0) {
|
||||
_messageLabel.attributedText = config.messageAttributed;
|
||||
_messageLabel.textAlignment = NSTextAlignmentCenter;
|
||||
} else {
|
||||
_messageLabel.text = config.message;
|
||||
}
|
||||
|
||||
_cancelButton.layer.borderColor = [MewThemeColor mewDividerColor].CGColor;
|
||||
_cancelButton.layer.borderWidth = 2.f;
|
||||
_confirmButton.layer.borderColor = [MewThemeColor mewDividerColor].CGColor;
|
||||
_confirmButton.layer.borderWidth = 2.f;
|
||||
}
|
||||
|
||||
- (void)setIsConfigBoard:(BOOL)isConfigBoard {
|
||||
_isConfigBoard = isConfigBoard;
|
||||
if (isConfigBoard) {
|
||||
//需要边框
|
||||
_cancelButton.layer.borderColor = [MewThemeColor mewDividerColor].CGColor;
|
||||
_cancelButton.layer.borderWidth = 2.f;
|
||||
_confirmButton.layer.borderColor = [MewThemeColor mewDividerColor].CGColor;
|
||||
_confirmButton.layer.borderWidth = 2.f;
|
||||
}else {
|
||||
//不需要边框
|
||||
_cancelButton.layer.borderColor = [MewThemeColor mewDividerColor].CGColor;
|
||||
_cancelButton.layer.borderWidth = 0;
|
||||
_confirmButton.layer.borderColor = [MewThemeColor mewDividerColor].CGColor;
|
||||
_confirmButton.layer.borderWidth = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (UILabel *)titleLabel {
|
||||
if (!_titleLabel) {
|
||||
_titleLabel = [[UILabel alloc] init];
|
||||
_titleLabel.textAlignment = NSTextAlignmentCenter;
|
||||
}
|
||||
return _titleLabel ;
|
||||
}
|
||||
|
||||
- (UILabel *)messageLabel {
|
||||
if (!_messageLabel) {
|
||||
_messageLabel = [[UILabel alloc] init];
|
||||
_messageLabel.numberOfLines = 0;
|
||||
_messageLabel.textAlignment = NSTextAlignmentCenter;
|
||||
}
|
||||
return _messageLabel;
|
||||
}
|
||||
|
||||
- (UIButton *)cancelButton {
|
||||
if (!_cancelButton) {
|
||||
_cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
[_cancelButton addTarget:self action:@selector(onClickCancelButtonAction:) forControlEvents:UIControlEventTouchUpInside];
|
||||
}
|
||||
return _cancelButton;
|
||||
}
|
||||
|
||||
- (UIButton *)confirmButton {
|
||||
if (!_confirmButton) {
|
||||
_confirmButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
[_confirmButton addTarget:self action:@selector(onClickmew_confirmButtonAction:) forControlEvents:UIControlEventTouchUpInside];
|
||||
}
|
||||
return _confirmButton;
|
||||
}
|
||||
|
||||
- (UIStackView *)stackView {
|
||||
if (!_stackView) {
|
||||
_stackView = [[UIStackView alloc] initWithArrangedSubviews:@[self.cancelButton, self.confirmButton]];
|
||||
_stackView.distribution = UIStackViewDistributionFillEqually;
|
||||
_stackView.alignment = UIStackViewAlignmentCenter;
|
||||
_stackView.spacing = 16;
|
||||
}
|
||||
return _stackView;
|
||||
}
|
||||
|
||||
@end
|
@@ -1,21 +0,0 @@
|
||||
//
|
||||
// NetImageConfig.h
|
||||
// mew-ios
|
||||
//
|
||||
// Created by 触海 on 2023/11/9.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "UIImageConstant.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface NetImageConfig : NSObject
|
||||
|
||||
@property (nonatomic, assign) BOOL autoLoad;
|
||||
@property (nonatomic, assign) ImageType imageType;
|
||||
@property (nonatomic, assign) CGFloat radius;
|
||||
@property (nonatomic, strong) UIImage * placeHolder;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,21 +0,0 @@
|
||||
//
|
||||
// NetImageConfig.m
|
||||
// mew-ios
|
||||
//
|
||||
// Created by 触海 on 2023/11/9.
|
||||
//
|
||||
|
||||
#import "NetImageConfig.h"
|
||||
|
||||
@implementation NetImageConfig
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_autoLoad = YES;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
@@ -1,36 +0,0 @@
|
||||
//
|
||||
// NetImageView.h
|
||||
// mew-ios
|
||||
//
|
||||
// Created by 触海 on 2023/11/9.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "UIImageConstant.h"
|
||||
#import "NetImageConfig.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef void(^LoadCompletion)(UIImage *image, NSURL * url);
|
||||
|
||||
typedef NS_ENUM(NSInteger, NetImageState){
|
||||
NetImageStateUnload = 1,
|
||||
NetImageStateLoading,
|
||||
NetImageStateLoaded,
|
||||
};
|
||||
|
||||
@interface NetImageView : UIImageView
|
||||
|
||||
@property (nonatomic, assign, readonly) NetImageState state;
|
||||
@property (nonatomic, copy) NSString* imageUrl;
|
||||
|
||||
- (instancetype)initWithUrl:(NSString * _Nonnull)imageUrl;
|
||||
- (instancetype)initWithConfig:(NetImageConfig * _Nullable)config;
|
||||
- (instancetype)initWithUrl:(NSString * _Nonnull)imageUrl config:(NetImageConfig * _Nullable)config;
|
||||
|
||||
- (void)loadImage:(LoadCompletion _Nullable)completion;
|
||||
- (void)loadImageWithUrl:(NSString * _Nonnull)imageUrl completion:(LoadCompletion _Nullable)completion;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,102 +0,0 @@
|
||||
//
|
||||
// NetImageView.m
|
||||
// mew-ios
|
||||
//
|
||||
// Created by 触海 on 2023/11/9.
|
||||
//
|
||||
|
||||
#import "NetImageView.h"
|
||||
#import <UIImageView+WebCache.h>
|
||||
#import <SDImageCache.h>
|
||||
|
||||
@interface NetImageView()
|
||||
|
||||
@property (nonatomic, assign, readwrite) NetImageState state;
|
||||
@property (nonatomic, copy) NSString * innerConfigedUrl;
|
||||
|
||||
@property (nonatomic, strong) NetImageConfig * config;
|
||||
|
||||
@end
|
||||
|
||||
@implementation NetImageView
|
||||
-(instancetype)initWithFrame:(CGRect)frame{
|
||||
self = [super initWithFrame:frame];
|
||||
if(self){
|
||||
self.contentMode = UIViewContentModeScaleAspectFill;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
-(instancetype)init{
|
||||
self = [super init];
|
||||
if(self){
|
||||
self.contentMode = UIViewContentModeScaleAspectFill;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
- (instancetype)initWithUrl:(NSString *)url {
|
||||
return [self initWithUrl:url config:nil];
|
||||
}
|
||||
|
||||
- (instancetype)initWithConfig:(NetImageConfig *)config {
|
||||
return [self initWithUrl:@"" config:config];
|
||||
}
|
||||
|
||||
- (instancetype)initWithUrl:(NSString *)url config:(NetImageConfig *)config {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_state = NetImageStateUnload;
|
||||
_config = config;
|
||||
self.contentMode = UIViewContentModeScaleAspectFill;
|
||||
if (_config.autoLoad) {
|
||||
[self setImageUrl:url];
|
||||
} else {
|
||||
[self initImageUrl:url];
|
||||
}
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)initImageUrl:(NSString *)imageUrl {
|
||||
_imageUrl = imageUrl;
|
||||
_innerConfigedUrl = [UIImageConstant configUrl:_imageUrl type:self.config.imageType radius:self.config.radius];
|
||||
}
|
||||
|
||||
- (void)setImageUrl:(NSString *)imageUrl {
|
||||
[self initImageUrl:imageUrl];
|
||||
UIImage * image = [[SDImageCache sharedImageCache] imageFromCacheForKey:_innerConfigedUrl];
|
||||
if (image) {
|
||||
self.image = image;
|
||||
self.state = NetImageStateLoaded;
|
||||
} else {
|
||||
[self loadImage:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)loadImage:(LoadCompletion)completion {
|
||||
self.state = NetImageStateLoading;
|
||||
[self sd_setImageWithURL:[NSURL URLWithString:_innerConfigedUrl] placeholderImage:self.config.placeHolder options:SDWebImageRetryFailed completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
|
||||
if (error) {
|
||||
self.state = NetImageStateUnload;
|
||||
} else {
|
||||
self.state = NetImageStateLoaded;
|
||||
if (completion) {
|
||||
completion(image, imageURL);
|
||||
};
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)loadImageWithUrl:(NSString * _Nonnull)imageUrl completion:(LoadCompletion)completion {
|
||||
[self initImageUrl:imageUrl];
|
||||
[self loadImage:completion];
|
||||
}
|
||||
|
||||
- (NetImageConfig *)config {
|
||||
if (!_config) {
|
||||
_config = [[NetImageConfig alloc] init];
|
||||
}
|
||||
return _config;
|
||||
}
|
||||
|
||||
@end
|
@@ -1,52 +0,0 @@
|
||||
//
|
||||
// UIImageConstant.h
|
||||
// mew-ios
|
||||
//
|
||||
// Created by 触海 on 2023/11/9.
|
||||
// 存放一些 加载图片 需要做的裁剪的key
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UIImageConstant : NSObject
|
||||
|
||||
#pragma mark - 图片相关的
|
||||
|
||||
UIKIT_EXTERN NSString * const kImageTypeRoomFace; //房间表情
|
||||
UIKIT_EXTERN NSString * const kImageTypeRoomGift; //房间礼物
|
||||
UIKIT_EXTERN NSString * const kImageTypeUserIcon; //用户头像60x60
|
||||
UIKIT_EXTERN NSString * const kImageTypeUserLibaryDetail;//用户相册大图nil
|
||||
UIKIT_EXTERN NSString * const kImageTypeCornerAvatar;//圆角图形,会先把图形裁剪成正方形,并且转换为png
|
||||
UIKIT_EXTERN NSString * const kImageTypeUserInfoAlbum;//用户信息里面相册
|
||||
UIKIT_EXTERN NSString * const kImageTypeUserCardLevel;///用户资料卡中 等级以高度20等比例缩放
|
||||
UIKIT_EXTERN NSString * const kImageTypeMonentsPhoto;///动态中的图片
|
||||
typedef NS_ENUM(NSUInteger, ImageType){
|
||||
ImageTypeRoomFace = 1, //房间表情
|
||||
ImageTypeRoomGift, //房间礼物
|
||||
ImageTypeUserIcon, //用户头像60x60
|
||||
ImageTypeUserLibaryDetail, //用户相册大图
|
||||
ImageTypeCornerAvatar, //圆角图形,会先把图形裁剪成正方形,并且转换为png
|
||||
ImageTypeUserInfoAlbum, ///用户信息里面相册
|
||||
ImageTypeUserCardLevel, /// 用户资料卡中 等级以高度20等比例缩放
|
||||
ImageTypeMonentsPhoto, ///动态中的图片
|
||||
};
|
||||
|
||||
///展位图
|
||||
|
||||
/// 头像的默认占位图
|
||||
+ (UIImage *)defaultAvatarPlaceholder;
|
||||
///空白头像缺省图
|
||||
+ (UIImage *)defaultEmptyAvatarPlaceholder;
|
||||
/// 空白图的占位图
|
||||
+ (UIImage *)defalutEmptyPlaceholder;
|
||||
/// banner的占位图
|
||||
+ (UIImage *)defalutBannerPlaceholder;
|
||||
|
||||
+ (NSString*)configUrl:(NSString*)url type:(ImageType)type;
|
||||
+ (NSString*)configUrl:(NSString*)url radius:(CGFloat)radius;
|
||||
+ (NSString*)configUrl:(NSString*)url type:(ImageType)type radius:(CGFloat)radius;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,108 +0,0 @@
|
||||
//
|
||||
// UIImageConstant.m
|
||||
// mew-ios
|
||||
//
|
||||
// Created by 触海 on 2023/11/9.
|
||||
//
|
||||
|
||||
#import "UIImageConstant.h"
|
||||
|
||||
@implementation UIImageConstant
|
||||
|
||||
/// 房间表情
|
||||
NSString * const kImageTypeRoomFace = @"";
|
||||
/// 房间礼物
|
||||
NSString * const kImageTypeRoomGift = @"";
|
||||
/// 用户头像150x150
|
||||
NSString * const kImageTypeUserIcon = @"imageMogr2/auto-orient/thumbnail/150x150";
|
||||
/// 用户相册大图
|
||||
NSString * const kImageTypeUserLibaryDetail = @"imageMogr2/auto-orient/thumbnail/300x300";
|
||||
NSString * const kImageTypeCornerAvatar = @"imageMogr2/auto-orient/thumbnail/300x300/format/png";
|
||||
/// 用户信息里面相册
|
||||
NSString * const kImageTypeUserInfoAlbum = @"imageMogr2/auto-orient/blur/375x375";
|
||||
/// 用户信息里面相册
|
||||
NSString * const kImageTypeUserCardLevel = @"imageMogr2/thumbnail/x40";
|
||||
/// 动态中的图片 400 * 400
|
||||
NSString * const kImageTypeMonentsPhoto = @"imageMogr2/auto-orient/thumbnail/400x400";
|
||||
|
||||
/// 头像的默认占位图
|
||||
+ (UIImage *)defaultAvatarPlaceholder {
|
||||
return [UIImage imageNamed:@"common_avatar"];
|
||||
}
|
||||
|
||||
///空白头像缺省图
|
||||
+ (UIImage *)defaultEmptyAvatarPlaceholder {
|
||||
return [UIImage imageNamed:@"common_empty_avatar"];
|
||||
}
|
||||
|
||||
/// 空白图的占位图
|
||||
+ (UIImage *)defalutEmptyPlaceholder {
|
||||
return [UIImage imageNamed:@"common_empty"];
|
||||
}
|
||||
/// banner的占位图
|
||||
+ (UIImage *)defalutBannerPlaceholder {
|
||||
return [UIImage imageNamed:@"common_banner"];
|
||||
}
|
||||
|
||||
+ (NSString *)configUrl:(NSString *)url type:(ImageType)type {
|
||||
return [self configUrl:url type:type radius:0];
|
||||
}
|
||||
|
||||
+ (NSString *)configUrl:(NSString *)url radius:(CGFloat)radius {
|
||||
return [self configUrl:url type:-1 radius:radius];
|
||||
}
|
||||
|
||||
+ (NSString *)configUrl:(NSString *)url type:(ImageType)type radius:(CGFloat)radius {
|
||||
if (!url || url.length <= 0) return nil;
|
||||
NSMutableString *urlString = [NSMutableString stringWithString:url];
|
||||
NSString *configUrl = nil;
|
||||
switch (type) {
|
||||
case ImageTypeUserIcon:
|
||||
configUrl = kImageTypeUserIcon;
|
||||
break;
|
||||
case ImageTypeCornerAvatar:
|
||||
configUrl = kImageTypeCornerAvatar;
|
||||
break;
|
||||
case ImageTypeRoomFace:
|
||||
configUrl = kImageTypeRoomFace;
|
||||
break;
|
||||
case ImageTypeUserLibaryDetail:
|
||||
configUrl = kImageTypeUserLibaryDetail;
|
||||
break;
|
||||
case ImageTypeRoomGift:
|
||||
configUrl = kImageTypeRoomGift;
|
||||
break;
|
||||
case ImageTypeUserInfoAlbum:
|
||||
configUrl = kImageTypeUserInfoAlbum;
|
||||
break;
|
||||
case ImageTypeUserCardLevel:
|
||||
configUrl = kImageTypeUserCardLevel;
|
||||
case ImageTypeMonentsPhoto:
|
||||
configUrl = kImageTypeMonentsPhoto;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (configUrl) {
|
||||
if ([url containsString:@"?"]) {
|
||||
[urlString appendString:@"|"];
|
||||
}else{
|
||||
[urlString appendString:@"?"];
|
||||
}
|
||||
[urlString appendString:configUrl];
|
||||
}
|
||||
|
||||
if (radius > 0) {
|
||||
[urlString appendString:[NSString stringWithFormat:@"|roundPic/radius/%f", radius]];
|
||||
}
|
||||
|
||||
return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
|
||||
(CFStringRef)urlString,
|
||||
NULL,
|
||||
(CFStringRef)@"|",
|
||||
kCFStringEncodingUTF8));
|
||||
}
|
||||
|
||||
@end
|
||||
|
@@ -1,42 +0,0 @@
|
||||
//
|
||||
// UIButton+MewEnlargeTouchArea.h
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/5.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UIButton (MewEnlargeTouchArea)
|
||||
@property (nonatomic, assign) NSTimeInterval mew_acceptEventInterval; // 重复点击的间隔
|
||||
|
||||
//图片frmae
|
||||
@property (strong, nonatomic) NSValue *imageFrame;
|
||||
//标题frmae
|
||||
@property (strong, nonatomic) NSValue *titleFrame;
|
||||
|
||||
/**
|
||||
通过 hitTest:withEvent: 扩大btn的点击范围
|
||||
注:填写的都是 在button 原frame 上面 扩大的对应的值
|
||||
|
||||
@param top 顶部 扩大的值
|
||||
@param right 右边 扩大的值
|
||||
@param bottom 底部 扩大的值
|
||||
@param left 左边 扩大的值
|
||||
*/
|
||||
- (void)mew_setEnlargeEdgeWithTop:(CGFloat)top right:(CGFloat)right bottom:(CGFloat)bottom left:(CGFloat)left;
|
||||
|
||||
/**
|
||||
扩大按钮点击范围
|
||||
|
||||
@discussion mew_setEnlargeEdgeWithTop:right:bottom:left:方法的包装
|
||||
*/
|
||||
- (void)mew_enlargeTouchArea:(UIEdgeInsets)insets;
|
||||
|
||||
|
||||
+(UIButton *)mew_buttonInitWithText:(NSString *)text font:(UIFont *)font textColor:(UIColor *)textColor image:(UIImage *)image bgImage:(UIImage *)bgImage;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,190 +0,0 @@
|
||||
//
|
||||
// UIButton+MewEnlargeTouchArea.m
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/5.
|
||||
//
|
||||
|
||||
#import "UIButton+MewEnlargeTouchArea.h"
|
||||
#import <objc/runtime.h>
|
||||
|
||||
|
||||
#define defaultInterval 0.0003 //默认时间间隔,不能太长,以免影响系统拍照等功能
|
||||
@interface UIButton ()
|
||||
/**
|
||||
* bool YES 忽略点击事件 NO 允许点击事件
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL isIgnoreEvent;
|
||||
@end
|
||||
@implementation UIButton (MewEnlargeTouchArea)
|
||||
static const char *UIControl_acceptEventInterval = "UIControl_acceptEventInterval";
|
||||
static const char *UIControl_enventIsIgnoreEvent = "UIControl_enventIsIgnoreEvent";
|
||||
|
||||
//定义常量 必须是C语言字符串
|
||||
static const char *imageFrameStr = "imageFrame";
|
||||
static const char *titleFrameStr = "titleFrame";
|
||||
|
||||
+ (void)load{
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
Method newImageMethod = class_getInstanceMethod(self, @selector(new_imageRectForContentRect:));
|
||||
Method oldImageMethod = class_getInstanceMethod(self, @selector(imageRectForContentRect:));
|
||||
method_exchangeImplementations(newImageMethod, oldImageMethod);
|
||||
|
||||
Method newTitleMethod = class_getInstanceMethod(self, @selector(new_titleRectForContentRect:));
|
||||
Method oldTitleMethod = class_getInstanceMethod(self, @selector(titleRectForContentRect:));
|
||||
method_exchangeImplementations(newTitleMethod, oldTitleMethod);
|
||||
|
||||
|
||||
//根据selector查找Method
|
||||
SEL selA = @selector(sendAction:to:forEvent:);
|
||||
SEL selB = @selector(new_sendAction:to:forEvent:);
|
||||
Method methodA = class_getInstanceMethod(self,selA);
|
||||
Method methodB = class_getInstanceMethod(self, selB);
|
||||
//添加自定义方法
|
||||
BOOL isAdd = class_addMethod(self, selA, method_getImplementation(methodB), method_getTypeEncoding(methodB));
|
||||
|
||||
if (isAdd) {//添加成功->替换
|
||||
class_replaceMethod(self, selB, method_getImplementation(methodA), method_getTypeEncoding(methodA));
|
||||
}else{//添加不成功->交换
|
||||
//添加失败了 说明本类中有methodB的实现,此时只需要将methodA和methodB的IMP互换一下即可。
|
||||
method_exchangeImplementations(methodA, methodB);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
- (void)new_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
|
||||
self.mew_acceptEventInterval = self.mew_acceptEventInterval == 0 ? defaultInterval : self.mew_acceptEventInterval;
|
||||
if (self.isIgnoreEvent){//默认可以响应点击事件
|
||||
return;
|
||||
}
|
||||
if (self.mew_acceptEventInterval > 0){//第一次点击,设定eventTimeInterval后,可以响应点击事件
|
||||
[self performSelector:@selector(setNoIgnoreEvent) withObject:nil afterDelay:self.mew_acceptEventInterval];
|
||||
}
|
||||
self.isIgnoreEvent = YES;//设置不可以响应点击事件
|
||||
[self new_sendAction:action to:target forEvent:event];
|
||||
}
|
||||
|
||||
// runtime 动态绑定 属性
|
||||
- (BOOL)isIgnoreEvent{
|
||||
return [objc_getAssociatedObject(self, UIControl_enventIsIgnoreEvent) boolValue];
|
||||
}
|
||||
-(void)setNoIgnoreEvent{
|
||||
self.isIgnoreEvent = NO;
|
||||
}
|
||||
- (void)setIsIgnoreEvent:(BOOL)isIgnoreEvent {
|
||||
objc_setAssociatedObject(self, UIControl_enventIsIgnoreEvent, @(isIgnoreEvent), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
-(void)setMew_acceptEventInterval:(NSTimeInterval)mew_acceptEventInterval{
|
||||
objc_setAssociatedObject(self, UIControl_acceptEventInterval, @(mew_acceptEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
-(NSTimeInterval)mew_acceptEventInterval{
|
||||
return [objc_getAssociatedObject(self, UIControl_acceptEventInterval) doubleValue];
|
||||
}
|
||||
- (void)setImageFrame:(NSValue *)imageFrame{
|
||||
objc_setAssociatedObject(self, imageFrameStr, imageFrame, OBJC_ASSOCIATION_RETAIN);
|
||||
}
|
||||
|
||||
- (NSValue *)imageFrame{
|
||||
return objc_getAssociatedObject(self, imageFrameStr);
|
||||
}
|
||||
|
||||
- (void)setTitleFrame:(NSValue *)titleFrame{
|
||||
objc_setAssociatedObject(self, titleFrameStr, titleFrame, OBJC_ASSOCIATION_RETAIN);
|
||||
}
|
||||
|
||||
- (NSValue *)titleFrame{
|
||||
return objc_getAssociatedObject(self, titleFrameStr);
|
||||
}
|
||||
|
||||
- (CGRect)new_imageRectForContentRect:(CGRect)contentRect{
|
||||
if (CGRectEqualToRect(self.imageFrame.CGRectValue, CGRectZero)) {
|
||||
return [self new_imageRectForContentRect:contentRect];
|
||||
}
|
||||
return self.imageFrame.CGRectValue;
|
||||
}
|
||||
|
||||
- (CGRect)new_titleRectForContentRect:(CGRect)contentRect{
|
||||
if (CGRectEqualToRect(self.titleFrame.CGRectValue, CGRectZero)) {
|
||||
return [self new_titleRectForContentRect:contentRect];
|
||||
}
|
||||
return self.titleFrame.CGRectValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static char topNameKey;
|
||||
static char rightNameKey;
|
||||
static char bottomNameKey;
|
||||
static char leftNameKey;
|
||||
|
||||
- (void)mew_setEnlargeEdgeWithTop:(CGFloat)top right:(CGFloat)right bottom:(CGFloat)bottom left:(CGFloat)left
|
||||
{
|
||||
objc_setAssociatedObject(self, &topNameKey, [NSNumber numberWithFloat:top], OBJC_ASSOCIATION_COPY_NONATOMIC);
|
||||
objc_setAssociatedObject(self, &rightNameKey, [NSNumber numberWithFloat:right], OBJC_ASSOCIATION_COPY_NONATOMIC);
|
||||
objc_setAssociatedObject(self, &bottomNameKey, [NSNumber numberWithFloat:bottom], OBJC_ASSOCIATION_COPY_NONATOMIC);
|
||||
objc_setAssociatedObject(self, &leftNameKey, [NSNumber numberWithFloat:left], OBJC_ASSOCIATION_COPY_NONATOMIC);
|
||||
}
|
||||
|
||||
- (void)mew_enlargeTouchArea:(UIEdgeInsets)insets
|
||||
{
|
||||
[self mew_setEnlargeEdgeWithTop:insets.top
|
||||
right:insets.right
|
||||
bottom:insets.bottom
|
||||
left:insets.left];
|
||||
}
|
||||
|
||||
- (CGRect)enlargedRect
|
||||
{
|
||||
NSNumber* topEdge = objc_getAssociatedObject(self, &topNameKey);
|
||||
NSNumber* rightEdge = objc_getAssociatedObject(self, &rightNameKey);
|
||||
NSNumber* bottomEdge = objc_getAssociatedObject(self, &bottomNameKey);
|
||||
NSNumber* leftEdge = objc_getAssociatedObject(self, &leftNameKey);
|
||||
if (topEdge && rightEdge && bottomEdge && leftEdge)
|
||||
{
|
||||
return CGRectMake(self.bounds.origin.x - leftEdge.floatValue,
|
||||
self.bounds.origin.y - topEdge.floatValue,
|
||||
self.bounds.size.width + leftEdge.floatValue + rightEdge.floatValue,
|
||||
self.bounds.size.height + topEdge.floatValue + bottomEdge.floatValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
return self.bounds;
|
||||
}
|
||||
}
|
||||
|
||||
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
|
||||
{
|
||||
if(self.hidden) return nil;
|
||||
CGRect rect = [self enlargedRect];
|
||||
if (CGRectEqualToRect(rect, self.bounds))
|
||||
{
|
||||
return [super hitTest:point withEvent:event];
|
||||
}
|
||||
return CGRectContainsPoint(rect, point) ? self : nil;
|
||||
}
|
||||
+(UIButton *)mew_buttonInitWithText:(NSString *)text font:(UIFont *)font textColor:(UIColor *)textColor image:(UIImage *)image bgImage:(UIImage *)bgImage{
|
||||
UIButton *button = [[UIButton alloc]initWithFrame:CGRectZero];
|
||||
if(text.length > 0){
|
||||
[button setTitle:text forState:UIControlStateNormal];
|
||||
}
|
||||
if(font != nil){
|
||||
button.titleLabel.font = font;
|
||||
}
|
||||
|
||||
if(textColor != nil){
|
||||
[button setTitleColor:textColor forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
if (image != nil){
|
||||
[button setImage:image forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
if(bgImage != nil){
|
||||
[button setBackgroundImage:bgImage forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
return button;
|
||||
}
|
||||
@end
|
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// MewSetButtomArea.h
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2024/1/18.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UIButton (MewSetButtomArea)
|
||||
- (void)mew_setEnlargeEdgeWithTop:(CGFloat)top right:(CGFloat)right bottom:(CGFloat)bottom left:(CGFloat)left;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// MewSetButtomArea.m
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2024/1/18.
|
||||
//
|
||||
#import "UIButton+MewSetButtomArea.h"
|
||||
#import <objc/runtime.h>
|
||||
@interface UIButton ()
|
||||
|
||||
@end
|
||||
@implementation UIButton (MewSetButtomArea)
|
||||
|
||||
static char topNameKey;
|
||||
static char rightNameKey;
|
||||
static char bottomNameKey;
|
||||
static char leftNameKey;
|
||||
|
||||
- (void)mew_setEnlargeEdgeWithTop:(CGFloat)top right:(CGFloat)right bottom:(CGFloat)bottom left:(CGFloat)left
|
||||
{
|
||||
objc_setAssociatedObject(self, &topNameKey, [NSNumber numberWithFloat:top], OBJC_ASSOCIATION_COPY_NONATOMIC);
|
||||
objc_setAssociatedObject(self, &rightNameKey, [NSNumber numberWithFloat:right], OBJC_ASSOCIATION_COPY_NONATOMIC);
|
||||
objc_setAssociatedObject(self, &bottomNameKey, [NSNumber numberWithFloat:bottom], OBJC_ASSOCIATION_COPY_NONATOMIC);
|
||||
objc_setAssociatedObject(self, &leftNameKey, [NSNumber numberWithFloat:left], OBJC_ASSOCIATION_COPY_NONATOMIC);
|
||||
}
|
||||
|
||||
|
||||
- (CGRect)enlargedRect
|
||||
{
|
||||
NSNumber* topEdge = objc_getAssociatedObject(self, &topNameKey);
|
||||
NSNumber* rightEdge = objc_getAssociatedObject(self, &rightNameKey);
|
||||
NSNumber* bottomEdge = objc_getAssociatedObject(self, &bottomNameKey);
|
||||
NSNumber* leftEdge = objc_getAssociatedObject(self, &leftNameKey);
|
||||
if (topEdge && rightEdge && bottomEdge && leftEdge)
|
||||
{
|
||||
return CGRectMake(self.bounds.origin.x - leftEdge.floatValue,
|
||||
self.bounds.origin.y - topEdge.floatValue,
|
||||
self.bounds.size.width + leftEdge.floatValue + rightEdge.floatValue,
|
||||
self.bounds.size.height + topEdge.floatValue + bottomEdge.floatValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
return self.bounds;
|
||||
}
|
||||
}
|
||||
|
||||
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
|
||||
{
|
||||
if(self.hidden) return nil;
|
||||
CGRect rect = [self enlargedRect];
|
||||
if (CGRectEqualToRect(rect, self.bounds))
|
||||
{
|
||||
return [super hitTest:point withEvent:event];
|
||||
}
|
||||
return CGRectContainsPoint(rect, point) ? self : nil;
|
||||
}
|
||||
|
||||
@end
|
@@ -1,24 +0,0 @@
|
||||
//
|
||||
// Api+MewMain.h
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/5.
|
||||
//
|
||||
|
||||
#import "Api.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface Api (MewMain)
|
||||
/// 请求Ticket
|
||||
+ (void)mew_requestTicket:(MewHttpRequestHelperCompletion)completion access_token:(NSString *)accessToken issue_type:(NSString *)issueType;
|
||||
|
||||
/// 初始化配置
|
||||
/// @param complection 完成
|
||||
+ (void)mew_clientInitConfig:(MewHttpRequestHelperCompletion)complection;
|
||||
|
||||
///心跳接口,每 30 秒调用一次,用来更新用户在线状态 登录成功之后调用
|
||||
+ (void)mew_requestClientHeartBrat:(MewHttpRequestHelperCompletion)completion;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,29 +0,0 @@
|
||||
//
|
||||
// Api+MewMain.m
|
||||
// yinmeng-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/5.
|
||||
//
|
||||
|
||||
#import "Api+MewMain.h"
|
||||
@implementation Api (MewMain)
|
||||
/// 请求Ticket
|
||||
+ (void)mew_requestTicket:(MewHttpRequestHelperCompletion)completion access_token:(NSString *)accessToken issue_type:(NSString *)issueType {
|
||||
NSString *getUrl = [MewEncryptManager mewAESDecryptText:@"G0vRJk+lM7aIFJdrDs1Xhg=="];///oauth/ticket
|
||||
[self makeRequest:getUrl method:MewHttpRequestHelperMethodPOST completion:completion, __FUNCTION__, accessToken, issueType, nil];
|
||||
}
|
||||
|
||||
/// 初始化配置
|
||||
/// @param complection 完成
|
||||
+ (void)mew_clientInitConfig:(MewHttpRequestHelperCompletion)complection {
|
||||
NSString *getUrl = [MewEncryptManager mewAESDecryptText:@"B0VaK5AAEVj2lGQmh7fdkg=="];///client/init
|
||||
[MewHttpRequestHelper request:getUrl method:MewHttpRequestHelperMethodGET params:[NSMutableDictionary dictionary] completion:complection];
|
||||
}
|
||||
|
||||
///心跳接口,每 30 秒调用一次,用来更新用户在线状态 登录成功之后调用
|
||||
+ (void)mew_requestClientHeartBrat:(MewHttpRequestHelperCompletion)completion {
|
||||
NSString *getUrl = [MewEncryptManager mewAESDecryptText:@"hq8XfxW9EwyMQW8i9Gu8SujFTd3xA+6qI6zbeP4xLnY="];///"client/heartbeat"
|
||||
[self makeRequest:getUrl method:MewHttpRequestHelperMethodPOST completion:completion, __FUNCTION__, nil];
|
||||
}
|
||||
|
||||
@end
|
@@ -14,18 +14,12 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@property (nonatomic,assign) BOOL iosPhoneBind;
|
||||
///配置信息
|
||||
@property (nonatomic,strong) MewClientDataModel *configInfo;
|
||||
///表情---
|
||||
@property (nonatomic, copy) NSString *version;
|
||||
@property (nonatomic, copy) NSString *zipMd5;
|
||||
@property (nonatomic, strong) NSURL *zipUrl;
|
||||
|
||||
|
||||
+ (instancetype)shareConfig;
|
||||
///初始化
|
||||
- (void)mew_clientInit;
|
||||
///添加心跳定时器
|
||||
- (void)mew_addHeartBratTimer;
|
||||
///重置心跳定时器
|
||||
- (void)mew_resetHeartBratTimer;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
@@ -6,8 +6,8 @@
|
||||
//
|
||||
|
||||
#import "MewClientConfig.h"
|
||||
#import "Api+MewMain.h"
|
||||
#import "MewTimer.h"
|
||||
|
||||
|
||||
#import "NSObject+MEWExtension.h"
|
||||
@interface MewClientConfig()
|
||||
///重试的次数 10次 如果你还是失败的话 那就算了 没办法了
|
||||
@@ -30,58 +30,41 @@
|
||||
#pragma mark - Public Method
|
||||
/// 获取配置信息
|
||||
- (void)mew_clientInit {
|
||||
[Api mew_clientInitConfig:^(MewBaseModel * _Nonnull data, NSInteger code, NSString * _Nonnull msg) {
|
||||
if (code == 200) {
|
||||
|
||||
[MewOCServerManager mewRequestInitInfo:^(MewBaseModel * _Nonnull obj, NSInteger num, NSString * _Nonnull text) {
|
||||
if (num == 200) {
|
||||
self.retryCount = 0;
|
||||
NSDictionary *initData = data.data;
|
||||
NSDictionary *initData = obj.data;
|
||||
self.iosPhoneBind = [initData[@"iosPhoneBind"] boolValue];
|
||||
MewClientDataModel *model = [MewClientDataModel mewModelWithDictionary:data.data];
|
||||
MewClientDataModel *model = [MewClientDataModel mewModelWithDictionary:obj.data];
|
||||
self.configInfo = model;
|
||||
// 表情
|
||||
|
||||
|
||||
// 配置App信息
|
||||
NSString *trtcAppId = [NSString stringWithFormat:@"%@", initData[@"trtcAppId"]];
|
||||
NSString *curTtcKey = [[NSUserDefaults standardUserDefaults] valueForKey:@"kTrtcAppId"];
|
||||
NSString *trtcAppId = [NSString stringWithFormat:@"%@", initData[[MewEncryptManager mewAESDecryptText:@"IFiOlC6Qw2kxiuP5iLUrXw=="]]];
|
||||
NSString *curTtcKey = [[NSUserDefaults standardUserDefaults] valueForKey:[MewEncryptManager mewAESDecryptText:@"o1/PeEYsNHSpIJ8pkmQkRA=="]];
|
||||
if (curTtcKey == nil && trtcAppId != nil) {
|
||||
[[NSUserDefaults standardUserDefaults] setValue:trtcAppId forKey:@"kTrtcAppId"];
|
||||
[[NSUserDefaults standardUserDefaults] setValue:trtcAppId forKey:[MewEncryptManager mewAESDecryptText:@"o1/PeEYsNHSpIJ8pkmQkRA=="]];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
} else {
|
||||
if (![trtcAppId isEqualToString:curTtcKey] && trtcAppId != nil) {
|
||||
[[NSUserDefaults standardUserDefaults] setValue:trtcAppId forKey:@"kTrtcAppId"];
|
||||
[[NSUserDefaults standardUserDefaults] setValue:trtcAppId forKey:[MewEncryptManager mewAESDecryptText:@"o1/PeEYsNHSpIJ8pkmQkRA=="]];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
if (self.retryCount < 10) {
|
||||
self.retryCount += 1;
|
||||
[self mew_clientInit];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}];
|
||||
}
|
||||
|
||||
///添加心跳定时器
|
||||
- (void)mew_addHeartBratTimer {
|
||||
if (_timer == nil) return;
|
||||
|
||||
_timer = [MewTimer MewScheduledTimerWithTimeInterval:30 block:^(id _Nonnull userInfo) {
|
||||
|
||||
[Api mew_requestClientHeartBrat:^(MewBaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
|
||||
|
||||
}];
|
||||
|
||||
} userInfo:nil repeats:YES];
|
||||
|
||||
|
||||
}
|
||||
|
||||
///重置心跳定时器
|
||||
- (void)mew_resetHeartBratTimer {
|
||||
if (_timer) {
|
||||
_timer = nil;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
@@ -11,12 +11,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MewClientDataModel : NSObject
|
||||
|
||||
/// 首页tag 配置
|
||||
@property (nonatomic,strong) NSArray<NSString *> *homeTabList;
|
||||
/// 进入房间拉取N条聊天数据
|
||||
@property(nonatomic, assign) NSInteger roomMessageCount;
|
||||
///启动图
|
||||
//@property (nonatomic,strong) AdvertiseModel *splashVo;
|
||||
///官方消息Uid列表
|
||||
@property (nonatomic, strong) NSArray<NSString *> *officialMsgUids;
|
||||
///官方账号 小秘书 红包消息
|
||||
|
@@ -36,5 +36,9 @@ typedef NS_ENUM(NSUInteger, MewSeatMicNumStateType) {
|
||||
Close = 1,
|
||||
|
||||
};
|
||||
typedef NS_ENUM(NSUInteger, MewOCServerManagerType) {
|
||||
MewOCServerManagerTypePOST,
|
||||
MewOCServerManagerTypeGET,
|
||||
|
||||
};
|
||||
#endif /* MewEnum_h */
|
||||
|
@@ -1,22 +0,0 @@
|
||||
//
|
||||
// Api+MewHomeApi.h
|
||||
// xplan-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/20.
|
||||
//
|
||||
|
||||
#import "Api.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface Api (MewHomeApi)
|
||||
///首页游戏点单分类
|
||||
+(void)mew_RequestMainHomeGameTabList:(MewHttpRequestHelperCompletion)complection;
|
||||
/// 发现新朋友列表
|
||||
/// @param complection 完成
|
||||
/// @param gender 性别. 1:男性 2:女性 null:不限定
|
||||
+ (void)mew_RequestMainHomeNewFriendListcomplection:(MewHttpRequestHelperCompletion)complection gender:(NSString *)gender gameId:(NSString *)gameId;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,33 +0,0 @@
|
||||
//
|
||||
// Api+MewHomeApi.m
|
||||
// xplan-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/20.
|
||||
//
|
||||
|
||||
#import "Api+MewHomeApi.h"
|
||||
|
||||
@implementation Api (MewHomeApi)
|
||||
|
||||
///首页游戏点单分类
|
||||
+(void)mew_RequestMainHomeGameTabList:(MewHttpRequestHelperCompletion)complection{
|
||||
[self makeRequest:[MewEncryptManager mewAESDecryptText:@"p6hShsDD1gduNfxvLDh40fGXNIVVYidusuyiqLoiE2E="] method:MewHttpRequestHelperMethodGET completion:complection, __FUNCTION__, nil];
|
||||
}
|
||||
/// 发现新朋友列表
|
||||
/// @param complection 完成
|
||||
/// @param gender 性别. 1:男性 2:女性 null:不限定
|
||||
+ (void)mew_RequestMainHomeNewFriendListcomplection:(MewHttpRequestHelperCompletion)complection gender:(NSString *)gender gameId:(NSString *)gameId{
|
||||
NSMutableDictionary * pararms = [NSMutableDictionary dictionary];
|
||||
if(gender != nil){
|
||||
[pararms mewSafeSetObject:gender forKey:@"gender"];
|
||||
}
|
||||
if(gameId != nil){
|
||||
[pararms mewSafeSetObject:gameId forKey:@"gameId"];
|
||||
}
|
||||
[MewHttpRequestHelper request:[MewEncryptManager mewAESDecryptText:@"snLITcKwwnlRGbuT+0t3Gw=="] method:MewHttpRequestHelperMethodGET params:pararms completion:complection];
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@end
|
@@ -1,18 +0,0 @@
|
||||
//
|
||||
// MewHomeManager.h
|
||||
// xplan-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/20.
|
||||
//
|
||||
|
||||
#import "MewBaseMvpPresenter.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MewHomeManager : MewBaseMvpPresenter
|
||||
-(void)mew_requsetMainHomeGameTabList;
|
||||
/// 发现新朋友
|
||||
- (void)mew_requestMainHomeNewFriendListWithGender:(nullable NSString *)gender gameId:(nullable NSString *)gameId;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,35 +0,0 @@
|
||||
//
|
||||
// MewHomeManager.m
|
||||
// xplan-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/20.
|
||||
//
|
||||
|
||||
#import "MewHomeManager.h"
|
||||
#import "MewMainHomeGameTabModel.h"
|
||||
#import "Api+MewHomeApi.h"
|
||||
#import "MewMainHomeProtocol.h"
|
||||
#import "MewMainHomeMakeFriendModel.h"
|
||||
|
||||
#import "MewMainHomeHotRoomModel.h"
|
||||
@implementation MewHomeManager
|
||||
///首页游戏点单分类
|
||||
-(void)mew_requsetMainHomeGameTabList{
|
||||
[Api mew_RequestMainHomeGameTabList:[self mew_createHttpCompletion:^(MewBaseModel * _Nonnull data) {
|
||||
NSArray *list = [MewMainHomeGameTabModel mewModelsWithArray:data.data];
|
||||
[[self mew_getView]mew_getMainHomeGameTabList:list];
|
||||
} fail:^(NSInteger code, NSString * _Nullable msg) {
|
||||
|
||||
}]];
|
||||
}
|
||||
/// 发现新朋友
|
||||
- (void)mew_requestMainHomeNewFriendListWithGender:(nullable NSString *)gender gameId:(nullable NSString *)gameId{
|
||||
[Api mew_RequestMainHomeNewFriendListcomplection:[self mew_createHttpCompletion:^(MewBaseModel * _Nonnull data) {
|
||||
NSArray * array = [MewMainHomeMakeFriendModel mewModelsWithArray:data.data];
|
||||
[[self mew_getView] mew_getNewFriendListSuccess:array gameId:gameId];
|
||||
}fail:^(NSInteger code, NSString * _Nullable msg) {
|
||||
[[self mew_getView] mew_getNewFriendListFailWithGameId:gameId];
|
||||
}] gender:gender gameId:gameId];
|
||||
}
|
||||
|
||||
@end
|
@@ -40,7 +40,6 @@
|
||||
if (!_mewEmptyView) {
|
||||
_mewEmptyView = [[UIImageView alloc] init];
|
||||
_mewEmptyView.userInteractionEnabled = YES;
|
||||
_mewEmptyView.image = [UIImageConstant defalutEmptyPlaceholder];
|
||||
_mewEmptyView.layer.masksToBounds = YES;
|
||||
_mewEmptyView.contentMode = UIViewContentModeScaleAspectFit;
|
||||
}
|
||||
|
@@ -7,8 +7,8 @@
|
||||
|
||||
#import "MewMainHomeMoreGameCell.h"
|
||||
@interface MewMainHomeMoreGameCell()
|
||||
@property(nonatomic,strong) NetImageView *mewBgImageView;
|
||||
@property(nonatomic,strong) NetImageView *mewIconView;
|
||||
@property(nonatomic,strong) UIImageView *mewBgImageView;
|
||||
@property(nonatomic,strong) UIImageView *mewIconView;
|
||||
@property(nonatomic,strong) UILabel *mewTitleView;
|
||||
@property(nonatomic,strong) UILabel *mewSubView;
|
||||
@property(nonatomic,strong) UIImageView *mewHotView;
|
||||
@@ -23,9 +23,10 @@
|
||||
[self installUI];
|
||||
[self installConstraints];
|
||||
for (int i = 0; i < 5; i++) {
|
||||
NetImageConfig *config = [NetImageConfig new];
|
||||
config.placeHolder = i == 4 ? kImage(@"mew_main_home_more_game_add"):kImage(@"mew_main_home_more_game_mic");
|
||||
NetImageView *imageView = [[NetImageView alloc]initWithConfig:config];
|
||||
|
||||
UIImage *placeHolder = i == 4 ? kImage(@"mew_main_home_more_game_add"):kImage(@"mew_main_home_more_game_mic");
|
||||
UIImageView *imageView = [[UIImageView alloc]init];
|
||||
imageView.image = placeHolder;
|
||||
[self.mewMicNumBgView addSubview:imageView];
|
||||
imageView.tag = 99+i;
|
||||
imageView.layer.cornerRadius = kGetScaleWidth(18)/2;
|
||||
@@ -100,9 +101,10 @@
|
||||
_mewHotNumView.text = @(arc4random() % 110).stringValue;
|
||||
_mewSubView.text = _moreGameModel.userGamePartnerVo.firstGameName;
|
||||
_mewIconView.image = nil;
|
||||
[_mewIconView loadImageWithUrl:_moreGameModel.avatar completion:^(UIImage * _Nonnull image, NSURL * _Nonnull url) {
|
||||
[_mewIconView sd_setImageWithURL:[NSURL URLWithString:_moreGameModel.avatar] placeholderImage:nil completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
|
||||
self.mewIconView.image = image;
|
||||
}];
|
||||
|
||||
if(_moreGameModel.userGamePartnerVo.firstGameName.length > 0){
|
||||
_mewSubView.text = [NSString stringWithFormat:@"标签:%@",_moreGameModel.userGamePartnerVo.firstGameName];
|
||||
}else{
|
||||
@@ -110,7 +112,7 @@
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
NetImageView *imageView = [self.mewMicNumBgView viewWithTag:99+i];
|
||||
UIImageView *imageView = [self.mewMicNumBgView viewWithTag:99+i];
|
||||
imageView.image = i == 4 ? kImage(@"mew_main_home_more_game_add"):kImage(@"mew_main_home_more_game_mic");
|
||||
imageView.layer.borderWidth = 0;
|
||||
|
||||
@@ -118,11 +120,10 @@
|
||||
|
||||
}
|
||||
#pragma mark - 懒加载
|
||||
- (NetImageView *)mewBgImageView{
|
||||
- (UIImageView *)mewBgImageView{
|
||||
if(!_mewBgImageView){
|
||||
NetImageConfig *config = [NetImageConfig new];
|
||||
config.placeHolder = [UIImageConstant defaultAvatarPlaceholder];
|
||||
_mewBgImageView = [[NetImageView alloc]initWithConfig:config];
|
||||
|
||||
_mewBgImageView = [[UIImageView alloc]init];
|
||||
_mewBgImageView.contentMode = UIViewContentModeScaleAspectFill;
|
||||
_mewBgImageView.clipsToBounds = YES ;
|
||||
_mewBgImageView.layer.cornerRadius = kGetScaleWidth(12);
|
||||
@@ -130,11 +131,10 @@
|
||||
}
|
||||
return _mewBgImageView;
|
||||
}
|
||||
- (NetImageView *)mewIconView{
|
||||
- (UIImageView *)mewIconView{
|
||||
if(!_mewIconView){
|
||||
NetImageConfig *config = [[NetImageConfig alloc]init];
|
||||
config.placeHolder = [UIImageConstant defaultAvatarPlaceholder];
|
||||
_mewIconView = [[NetImageView alloc]initWithConfig:config];
|
||||
|
||||
_mewIconView = [[UIImageView alloc]init];
|
||||
_mewIconView.layer.cornerRadius = kGetScaleWidth(40)/2;
|
||||
_mewIconView.layer.masksToBounds = YES;
|
||||
}
|
||||
|
@@ -7,8 +7,8 @@
|
||||
|
||||
#import "MewMainHomeMoreGameHeadCell.h"
|
||||
@interface MewMainHomeMoreGameHeadCell()
|
||||
@property(nonatomic,strong) NetImageView *mewUnclickView;
|
||||
@property(nonatomic,strong) NetImageView *mewClickView;
|
||||
@property(nonatomic,strong) UIImageView *mewUnclickView;
|
||||
@property(nonatomic,strong) UIImageView *mewClickView;
|
||||
@end
|
||||
@implementation MewMainHomeMoreGameHeadCell
|
||||
-(instancetype)initWithFrame:(CGRect)frame{
|
||||
@@ -37,28 +37,24 @@
|
||||
self.mewUnclickView.image = nil;
|
||||
self.mewClickView.hidden = !_tabModel.isOnClick;
|
||||
self.mewUnclickView.hidden = _tabModel.isOnClick;
|
||||
[self.mewClickView loadImageWithUrl:_tabModel.onClick completion:^(UIImage * _Nonnull image, NSURL * _Nonnull url) {
|
||||
self.mewClickView.image = image;
|
||||
}];
|
||||
[self.mewUnclickView loadImageWithUrl:_tabModel.onUnclick completion:^(UIImage * _Nonnull image, NSURL * _Nonnull url) {
|
||||
self.mewUnclickView.image = image;
|
||||
}];
|
||||
[self.mewClickView sd_setImageWithURL:[NSURL URLWithString:_tabModel.onClick]];
|
||||
[self.mewUnclickView sd_setImageWithURL:[NSURL URLWithString:_tabModel.onUnclick]];
|
||||
|
||||
|
||||
}
|
||||
#pragma mark - 懒加载
|
||||
- (NetImageView *)mewUnclickView{
|
||||
- (UIImageView *)mewUnclickView{
|
||||
if(!_mewUnclickView){
|
||||
NetImageConfig *config = [NetImageConfig new];
|
||||
config.placeHolder = [UIImageConstant defaultAvatarPlaceholder];
|
||||
_mewUnclickView = [[NetImageView alloc]initWithConfig:config];
|
||||
|
||||
_mewUnclickView = [[UIImageView alloc]init];
|
||||
|
||||
}
|
||||
return _mewUnclickView;
|
||||
}
|
||||
- (NetImageView *)mewClickView{
|
||||
- (UIImageView *)mewClickView{
|
||||
if(!_mewClickView){
|
||||
NetImageConfig *config = [NetImageConfig new];
|
||||
config.placeHolder = [UIImageConstant defaultAvatarPlaceholder];
|
||||
_mewClickView = [[NetImageView alloc]initWithConfig:config];
|
||||
|
||||
_mewClickView = [[UIImageView alloc]init];
|
||||
|
||||
}
|
||||
return _mewClickView;
|
||||
|
@@ -39,11 +39,11 @@
|
||||
}
|
||||
-(__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
|
||||
MewMainHomeMoreGameHeadCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([MewMainHomeMoreGameHeadCell class]) forIndexPath:indexPath];
|
||||
cell.tabModel = [self.mewGameList mewSafeObjectAtIndex:indexPath.row];
|
||||
cell.tabModel = [self.mewGameList objectAtIndex:indexPath.row];
|
||||
return cell;
|
||||
}
|
||||
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
|
||||
MewMainHomeGameTabModel *tapModel = [self.mewGameList mewSafeObjectAtIndex:indexPath.row];
|
||||
MewMainHomeGameTabModel *tapModel = [self.mewGameList objectAtIndex:indexPath.row];
|
||||
if(tapModel.isOnClick == YES){
|
||||
tapModel.isOnClick = NO;
|
||||
}else{
|
||||
|
@@ -5,11 +5,11 @@
|
||||
// Created by duoban on 2023/12/25.
|
||||
//
|
||||
|
||||
#import "MewMvpViewController.h"
|
||||
#import "MewBaseViewController.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MewMainHomeMoreGameVC : MewMvpViewController
|
||||
@interface MewMainHomeMoreGameVC : MewBaseViewController
|
||||
|
||||
@end
|
||||
|
||||
|
@@ -9,9 +9,9 @@
|
||||
#import "MewMainHomeMoreGameCell.h"
|
||||
#import "MewMainHomeEmptyCell.h"
|
||||
#import "MewMainHomeMoreGameHeadView.h"
|
||||
#import "MewHomeManager.h"
|
||||
|
||||
#import "Api+MewHomeApi.h"
|
||||
|
||||
|
||||
#import "MewMainHomeMenuDataModel.h"
|
||||
#import "MewMainHomeGameTabModel.h"
|
||||
#import <MJRefresh/MJRefresh.h>
|
||||
@@ -35,9 +35,7 @@
|
||||
@end
|
||||
|
||||
@implementation MewMainHomeMoreGameVC
|
||||
- (MewHomeManager *)createPresenter {
|
||||
return [[MewHomeManager alloc] init];
|
||||
}
|
||||
|
||||
- (BOOL)mew_isHiddenNavBar {
|
||||
return YES;
|
||||
}
|
||||
@@ -72,14 +70,32 @@
|
||||
header.lastUpdatedTimeLabel.textColor = [MewThemeColor mewSecondTextColor];
|
||||
self.mewCollectionView.mj_header = header;
|
||||
|
||||
|
||||
[self.presenter mew_requsetMainHomeGameTabList];
|
||||
[MewOCServerManager mewRequestMainHomeGameTabList:^(MewBaseModel * _Nonnull obj, NSInteger num, NSString * _Nonnull text) {
|
||||
if(obj.code == 200){
|
||||
NSArray *list = [MewMainHomeGameTabModel mewModelsWithArray:obj.data];
|
||||
self.mewGameList = [NSMutableArray arrayWithArray:list];
|
||||
[self.mewCollectionView reloadData];
|
||||
}
|
||||
|
||||
|
||||
}];
|
||||
|
||||
[self.mewCollectionView.mj_header beginRefreshing];
|
||||
|
||||
}
|
||||
-(void)mew_headerRefresh{
|
||||
[MewOCServerManager mewRequestMainHomeNewFriendList:^(MewBaseModel * _Nonnull obj, NSInteger num, NSString * _Nonnull text) {
|
||||
if(obj.code == 200){
|
||||
NSArray * array = [MewMainHomeMakeFriendModel mewModelsWithArray:obj.data];
|
||||
self.mewRoomList = [NSMutableArray arrayWithArray:array];
|
||||
[self.mewCollectionView reloadData];
|
||||
[self.mewCollectionView.mj_header endRefreshing];
|
||||
return;
|
||||
}
|
||||
[self.mewCollectionView.mj_header endRefreshing];
|
||||
} gender:self.mewSex gameId:self.gameId];
|
||||
|
||||
|
||||
[self.presenter mew_requestMainHomeNewFriendListWithGender:self.mewSex gameId:self.gameId];
|
||||
}
|
||||
-(void)mewChooseAllAction{
|
||||
self.mewSex = nil;
|
||||
@@ -102,23 +118,8 @@
|
||||
self.mewSelecteManBGView.backgroundColor = UIColorMewRGBAlpha(0xffffff, 0.4);
|
||||
[self.mewCollectionView.mj_header beginRefreshing];
|
||||
}
|
||||
///首页游戏点单分类
|
||||
-(void)mew_getMainHomeGameTabList:(NSArray *)list{
|
||||
self.mewGameList = [NSMutableArray arrayWithArray:list];
|
||||
[self.mewCollectionView reloadData];
|
||||
|
||||
}
|
||||
/// 发现新朋友成功
|
||||
-(void)mew_getNewFriendListSuccess:(NSArray *)list gameId:(nullable NSString *)gameId{
|
||||
self.gameId = gameId;
|
||||
self.mewRoomList = [NSMutableArray arrayWithArray:list];
|
||||
[self.mewCollectionView reloadData];
|
||||
[self.mewCollectionView.mj_header endRefreshing];
|
||||
}
|
||||
/// 发现新朋友失败
|
||||
-(void)mew_getNewFriendListFailWithGameId:(nullable NSString *)gameId{
|
||||
[self.mewCollectionView.mj_header endRefreshing];
|
||||
}
|
||||
|
||||
|
||||
-(void)installConstraints{
|
||||
CGFloat top = kStatusBarHeight + 11;
|
||||
[self.mewSelecteAllBGView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
@@ -165,7 +166,7 @@
|
||||
///选择游戏
|
||||
-(void)mew_selectGameFriendAction:(MewMainHomeGameTabModel *_Nullable)gameInfo type:(MewMainHomeMakeFriendHeadViewType)type sender:(UILabel *_Nullable)sender{
|
||||
self.gameId = type == MewMainHomeMakeFriendHeadViewTyep_Game_Select ? gameInfo.gameId : nil ;
|
||||
[self.presenter mew_requestMainHomeNewFriendListWithGender:self.mewSex gameId:self.gameId];
|
||||
[self mew_headerRefresh];
|
||||
|
||||
}
|
||||
|
||||
@@ -175,7 +176,7 @@
|
||||
}
|
||||
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section{
|
||||
|
||||
return CGSizeMake(0, kGetScaleWidth(67));
|
||||
return CGSizeMake(0, 0);
|
||||
}
|
||||
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
|
||||
return CGSizeMake(kGetScaleWidth(168), kGetScaleWidth(148));
|
||||
@@ -188,7 +189,7 @@
|
||||
|
||||
headView.mewGameList = self.mewGameList;
|
||||
headView.delegate = self;
|
||||
|
||||
headView.hidden = YES;
|
||||
return headView;
|
||||
}
|
||||
|
||||
@@ -199,13 +200,13 @@
|
||||
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
MewMainHomeMoreGameCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([MewMainHomeMoreGameCell class]) forIndexPath:indexPath];
|
||||
cell.moreGameModel = [self.mewRoomList mewSafeObjectAtIndex:indexPath.row];
|
||||
cell.moreGameModel = self.mewRoomList[indexPath.row] ;
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if(self.mewRoomList.count == 0)return;
|
||||
MewMainHomeMakeFriendModel *roomModel = [self.mewRoomList mewSafeObjectAtIndex:indexPath.row];
|
||||
MewMainHomeMakeFriendModel *roomModel = [self.mewRoomList objectAtIndex:indexPath.row];
|
||||
MewRoomPlayVC *roomVC = [[MewRoomPlayVC alloc]initWithMewRoomUid:roomModel.inRoomUid.length > 0 ? roomModel.inRoomUid : roomModel.uid];
|
||||
MewBaseNavigationController *baseNav = [[MewBaseNavigationController alloc] initWithRootViewController:roomVC];
|
||||
baseNav.modalPresentationStyle = UIModalPresentationFullScreen;
|
||||
|
@@ -1,24 +0,0 @@
|
||||
//
|
||||
// MewMainHomeProtocol.h
|
||||
// xplan-ios
|
||||
//
|
||||
// Created by duoban on 2023/12/21.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
@class UserInfoModel;
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol MewMainHomeProtocol <NSObject>
|
||||
|
||||
|
||||
///首页游戏点单分类
|
||||
-(void)mew_getMainHomeGameTabList:(NSArray *)list;
|
||||
/// 发现新朋友成功
|
||||
-(void)mew_getNewFriendListSuccess:(NSArray *)list gameId:(nullable NSString *)gameId;
|
||||
/// 发现新朋友失败
|
||||
-(void)mew_getNewFriendListFailWithGameId:(nullable NSString *)gameId;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,32 +0,0 @@
|
||||
//
|
||||
// Api+MewHome.h
|
||||
// mew-ios
|
||||
//
|
||||
// Created by 触海 on 2023/11/15.
|
||||
//
|
||||
|
||||
#import "Api.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface Api (MewHome)
|
||||
|
||||
/// Mew 首页随机列表
|
||||
+ (void)getMewHomeFriendListCompleted:(MewHttpRequestHelperCompletion)completed gender:(NSString *)gender ;
|
||||
|
||||
/// 获取首页用户的数据
|
||||
/// - Parameters:
|
||||
/// - complection: 数据回调
|
||||
/// - gender: 用户的性别
|
||||
+ (void)getNewFriendListComplection:(MewHttpRequestHelperCompletion)complection gender:(NSString *)gender;
|
||||
|
||||
|
||||
/// 上传七牛获取token
|
||||
/// @param completion 完成
|
||||
+ (void)qiniuUpLoadImage:(MewHttpRequestHelperCompletion)completion;
|
||||
|
||||
/// 音萌商店包的上传声音秀
|
||||
+ (void)mewPublishVoiceShow:(MewHttpRequestHelperCompletion)completion dura:(NSString *)dura desc:(NSString *)desc gender:(NSString *)gender url:(NSString *)url;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,38 +0,0 @@
|
||||
//
|
||||
// Api+MewHome.m
|
||||
// mew-ios
|
||||
//
|
||||
// Created by 触海 on 2023/11/15.
|
||||
//
|
||||
|
||||
#import "Api+MewHome.h"
|
||||
|
||||
@implementation Api (MewHome)
|
||||
|
||||
/// Mew 首页随机列表
|
||||
+ (void)getMewHomeFriendListCompleted:(MewHttpRequestHelperCompletion)completed gender:(NSString *)gender {
|
||||
NSString *getUrl = [MewEncryptManager mewAESDecryptText:@"ZnqkAkDTTXWcnvwqETmxzC3fgpK+OuH3kRHkQFI0HyM="];///voiceShow/listRandom
|
||||
[self makeRequest:getUrl method:MewHttpRequestHelperMethodGET completion:completed, __FUNCTION__, gender, nil];
|
||||
}
|
||||
|
||||
/// 获取新朋友列表
|
||||
+ (void)getNewFriendListComplection:(MewHttpRequestHelperCompletion)complection gender:(NSString *)gender {
|
||||
NSString *getUrl = [MewEncryptManager mewAESDecryptText:@"snLITcKwwnlRGbuT+0t3Gw=="];///home/newFriend
|
||||
[self makeRequest:getUrl method:MewHttpRequestHelperMethodGET completion:complection, __FUNCTION__, gender, nil];
|
||||
}
|
||||
|
||||
/// 上传七牛获取token
|
||||
/// @param completion 完成
|
||||
+ (void)qiniuUpLoadImage:(MewHttpRequestHelperCompletion)completion {
|
||||
NSString *getUrl = [MewEncryptManager mewAESDecryptText:@"V5gbqkWkuc4Fvzj9mYj/hBeoD5CULsPTsiK8Z8GieqY="];///qiniu/upload/getUploadToken
|
||||
[self makeRequest:getUrl method:MewHttpRequestHelperMethodGET completion:completion, __FUNCTION__, nil];
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// 音萌商店包的上传声音秀
|
||||
+ (void)mewPublishVoiceShow:(MewHttpRequestHelperCompletion)completion dura:(NSString *)dura desc:(NSString *)desc gender:(NSString *)gender url:(NSString *)url {
|
||||
[self makeRequest:@"voiceShow/publish" method:MewHttpRequestHelperMethodPOST completion:completion, __FUNCTION__, dura, desc, gender, url, nil];
|
||||
}
|
||||
|
||||
@end
|
@@ -1,45 +0,0 @@
|
||||
//
|
||||
// MewHomePresenter.h
|
||||
// mew-ios
|
||||
//
|
||||
// Created by 触海 on 2023/11/15.
|
||||
//
|
||||
|
||||
#import "MewBaseMvpPresenter.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MewHomePresenter : MewBaseMvpPresenter
|
||||
|
||||
- (void)mew_getNewFriendListWithGender:(NSString *)gender;
|
||||
|
||||
// 发布声音
|
||||
- (void)mew_uploadVoice:(NSString *)filePath;
|
||||
|
||||
|
||||
/// 关注用户/取消该关注
|
||||
/// - Parameters:
|
||||
/// - targetUid: 目标用户的uid
|
||||
/// - state: 是否关注 yes 关注 no 取消关注
|
||||
- (void)mew_attentionUser:(NSString *)targetUid state:(BOOL)state;
|
||||
/// 获取两个人的关注状态
|
||||
- (void)mew_getUserAttentionState:(NSString *)targetUid;
|
||||
|
||||
/// 获取用户信息
|
||||
- (void)mew_getUserInfoWithUid:(NSString *)uid;
|
||||
/// 获取用户详细信息
|
||||
- (void)mew_getUserDetailInfoWithUid:(NSString *)uid;
|
||||
|
||||
/// Mew 获取好友列表
|
||||
- (void)mew_getMewHomeFriendListWithGender:(NSString *)gender;
|
||||
|
||||
/// 用户关注列表
|
||||
/// @param page 当前的页数
|
||||
/// @param pageSize 一页多少个
|
||||
- (void)mew_getUserAttentionList:(int)page pageSize:(int)pageSize state:(int)state;
|
||||
|
||||
/// 音萌商店包的上传声音秀
|
||||
- (void)mewPublishVoiceShowDura:(NSString *)dura desc:(NSString *)desc gender:(NSString *)gender url:(NSString *)url;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -1,158 +0,0 @@
|
||||
//
|
||||
// MewHomePresenter.m
|
||||
// mew-ios
|
||||
//
|
||||
// Created by 触海 on 2023/11/15.
|
||||
//
|
||||
|
||||
#import "MewHomePresenter.h"
|
||||
#import "Api+MewHome.h"
|
||||
#import "Api+Mine.h"
|
||||
#import "MEWUploadFile.h"
|
||||
#import "MewUserInfoModel.h"
|
||||
#import "MewFansInfoModel.h"
|
||||
/// Protocol
|
||||
#import "MewHomeProtocol.h"
|
||||
#import "TTAlertConfig.h"
|
||||
#import "TTPopup.h"
|
||||
#import "MewAccountInfoStorage.h"
|
||||
#import "NSObject+MEWExtension.h"
|
||||
@implementation MewHomePresenter
|
||||
|
||||
/// Mew 获取好友列表
|
||||
- (void)mew_getMewHomeFriendListWithGender:(NSString *)gender {
|
||||
[Api getMewHomeFriendListCompleted:[self mew_createHttpCompletion:^(MewBaseModel * _Nonnull data) {
|
||||
NSArray *array = [MewUserInfoModel mewModelsWithArray:data.data[@"randomList"]];
|
||||
MewUserInfoModel *mineModel = [MewUserInfoModel mewModelWithDictionary:data.data[@"me"]];
|
||||
[[self mew_getView] mew_getMewHomeFriendListSuccesss:array selfMine:mineModel];
|
||||
} fail:^(NSInteger code, NSString * _Nullable msg) {
|
||||
|
||||
}] gender:gender];
|
||||
}
|
||||
|
||||
/// 获取新朋友
|
||||
- (void)mew_getNewFriendListWithGender:(NSString *)gender {
|
||||
[Api getNewFriendListComplection:[self mew_createHttpCompletion:^(MewBaseModel * _Nonnull data) {
|
||||
NSArray *array = [MewUserInfoModel mewModelsWithArray:data];
|
||||
[[self mew_getView] mew_getNewFriendListSuccess:array];
|
||||
} fail:^(NSInteger code, NSString * _Nullable msg) {
|
||||
[[self mew_getView] mew_getNewFriendListFail];
|
||||
}] gender:gender];
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// 上传声音
|
||||
- (void)mew_uploadVoice:(NSString *)filePath {
|
||||
[Api qiniuUpLoadImage:[self mew_createHttpCompletion:^(MewBaseModel * _Nonnull data) {
|
||||
NSString *key = data.data[@"key"];
|
||||
NSString *token = data.data[@"token"];
|
||||
[MEWUploadFile mewUploadFile:filePath named:key token:token success:^(NSString * _Nonnull key, NSDictionary * _Nonnull res) {
|
||||
NSString *url = res[@"path"];
|
||||
[[self mew_getView] mew_uploadVoiceFileToThirdSuccess:url];
|
||||
} failure:^(NSNumber * _Nonnull code, NSString * _Nonnull message) {
|
||||
[[self mew_getView] mew_uploadVoiceFileFail:message];
|
||||
}];
|
||||
|
||||
|
||||
NSLog(@"当前成功的数据是:%@",data);
|
||||
|
||||
} fail:^(NSInteger code, NSString * _Nullable msg) {
|
||||
NSLog(@"当前失败的数据是:%@ --- %ld",msg, code);
|
||||
}]];
|
||||
}
|
||||
|
||||
/// 关注用户/取消该关注
|
||||
/// - Parameters:
|
||||
/// - targetUid: 目标用户的uid
|
||||
/// - state: 是否关注 yes 关注 no 取消关注
|
||||
- (void)mew_attentionUser:(NSString *)targetUid state:(BOOL)state {
|
||||
|
||||
// if (state) {
|
||||
[self initiatemew_attentionUser:targetUid state:state];
|
||||
// return;
|
||||
// }
|
||||
|
||||
// self ini
|
||||
// TTAlertConfig *config = [[TTAlertConfig alloc]init];
|
||||
// config.title = @"提示";
|
||||
// config.message = @"确定取消关注该用户吗?";
|
||||
// [TTPopup alertWithConfig:config confirmHandler:^{
|
||||
// [self initiatemew_attentionUser:targetUid state:state];
|
||||
// } cancelHandler:^{
|
||||
//
|
||||
// }];
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// 获取两个人的关注状态
|
||||
- (void)mew_getUserAttentionState:(NSString *)targetUid {
|
||||
NSString *uid = [[MewAccountInfoStorage instance] mew_getUid];
|
||||
[Api Mew_AttentionStatusCompletion:[self mew_createHttpCompletion:^(MewBaseModel * _Nonnull data) {
|
||||
BOOL isLike = ((NSNumber *)data.data).boolValue;
|
||||
[[self mew_getView] mew_getUserAttentionSuccess:isLike];
|
||||
}] uid:uid isLikeUid:targetUid];
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// 获取用户信息
|
||||
- (void)mew_getUserInfoWithUid:(NSString *)uid {
|
||||
[Api Mew_GetUserInfo:[self mew_createHttpCompletion:^(MewBaseModel * _Nonnull data) {
|
||||
MewUserInfoModel *userInfo = [MewUserInfoModel mewModelWithDictionary:data.data];
|
||||
[[self mew_getView] mew_getUserInfoSuccess:userInfo];
|
||||
} fail:^(NSInteger code, NSString * _Nullable msg) {
|
||||
|
||||
}] uid:uid];
|
||||
}
|
||||
|
||||
/// 获取用户详细信息
|
||||
- (void)mew_getUserDetailInfoWithUid:(NSString *)uid {
|
||||
[Api Mew_UserDetailInfoCompletion:[self mew_createHttpCompletion:^(MewBaseModel * _Nonnull data) {
|
||||
MewUserInfoModel *infoModel = [MewUserInfoModel mewModelWithDictionary:data.data];
|
||||
[[self mew_getView] mew_getUserDetailInfoSuccess:infoModel];
|
||||
|
||||
}] uid:uid page:@"1" pageSize:@"20"];
|
||||
}
|
||||
|
||||
/// 用户关注列表
|
||||
/// @param page 当前的页数
|
||||
/// @param pageSize 一页多少个
|
||||
- (void)mew_getUserAttentionList:(int)page pageSize:(int)pageSize state:(int)state{
|
||||
NSString * uid= [MewAccountInfoStorage instance].mew_getUid;
|
||||
NSString * pageStr = [NSString stringWithFormat:@"%d", page];
|
||||
NSString * pageSizeStr = [NSString stringWithFormat:@"%d", pageSize];
|
||||
[Api Mew_GetAttentionListCompletion:[self mew_createHttpCompletion:^(MewBaseModel * _Nonnull data) {
|
||||
NSArray * array = [MewUserInfoModel mewModelsWithArray:data.data];
|
||||
[[self mew_getView] mew_getUserAttentionListSuccess:array state:state];
|
||||
}fail:^(NSInteger code, NSString * _Nullable msg) {
|
||||
// [[self mew_getView] mew_getUserAttentionListFail:state];
|
||||
}] uid:uid pageNo:pageStr pageSize:pageSizeStr];
|
||||
}
|
||||
|
||||
|
||||
/// 音萌商店包的上传声音秀
|
||||
- (void)mewPublishVoiceShowDura:(NSString *)dura desc:(NSString *)desc gender:(NSString *)gender url:(NSString *)url {
|
||||
|
||||
[Api mewPublishVoiceShow:[self mew_createHttpCompletion:^(MewBaseModel * _Nonnull data) {
|
||||
[[self mew_getView] mewPublishVoiceShowSuccess];
|
||||
|
||||
} fail:^(NSInteger code, NSString * _Nullable msg) {
|
||||
|
||||
}] dura:dura desc:desc gender:gender url: url];
|
||||
}
|
||||
|
||||
#pragma mark - Private Method
|
||||
- (void)initiatemew_attentionUser:(NSString *)targetUid state:(BOOL)state {
|
||||
NSString *uid = [[MewAccountInfoStorage instance] mew_getUid];
|
||||
NSString *ticket = [[MewAccountInfoStorage instance] mew_getTicket];
|
||||
NSString *type = state ? @"1" : @"2";
|
||||
[Api Mew_AttentionCompletion:[self mew_createHttpCompletion:^(MewBaseModel * _Nonnull data) {
|
||||
[[self mew_getView] mew_attentionUserSuccess:state];
|
||||
}] uid:uid likedUid:targetUid ticket:ticket type:type];
|
||||
|
||||
}
|
||||
|
||||
|
||||
@end
|
@@ -1,46 +0,0 @@
|
||||
//
|
||||
// MewHomeProtocol.h
|
||||
// mew-ios
|
||||
//
|
||||
// Created by 触海 on 2023/11/15.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
@class MewUserInfoModel;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol MewHomeProtocol <NSObject>
|
||||
|
||||
/// 获取发现好友列表成功
|
||||
- (void)mew_getNewFriendListSuccess:(NSArray *)array;
|
||||
/// 获取发现好友列表失败
|
||||
- (void)mew_getNewFriendListFail;
|
||||
|
||||
/// 上传声音成功
|
||||
- (void)mew_uploadVoiceFileToThirdSuccess:(NSString *)fileUrl;
|
||||
/// 上传声音秀失败
|
||||
/// @param message 失败消息
|
||||
- (void)mew_uploadVoiceFileFail:(NSString *)message;
|
||||
|
||||
/// 获取用户信息
|
||||
- (void)mew_getUserInfoSuccess:(MewUserInfoModel *)userInfo;;
|
||||
/// 获取用户详细信息
|
||||
- (void)mew_getUserDetailInfoSuccess:(MewUserInfoModel *)userInfo;;
|
||||
|
||||
/// 关注用户成功
|
||||
- (void)mew_attentionUserSuccess:(BOOL)status;
|
||||
/// 关注用户失败
|
||||
- (void)mew_attentionUserFail;
|
||||
/// 获取两个人的关注成功
|
||||
- (void)mew_getUserAttentionSuccess:(BOOL)status;
|
||||
|
||||
/// Mew 获取好友列表成功
|
||||
- (void)mew_getMewHomeFriendListSuccesss:(NSArray *)array selfMine:(MewUserInfoModel *)selfMineModel;
|
||||
///获取用户关注列表
|
||||
- (void)mew_getUserAttentionListSuccess:(NSArray *)array state:(int)state;
|
||||
|
||||
- (void)mewPublishVoiceShowSuccess;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@@ -5,11 +5,11 @@
|
||||
// Created by 触海 on 2023/11/10.
|
||||
//
|
||||
|
||||
#import "MewMvpViewController.h"
|
||||
#import "MewBaseViewController.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MewHomeViewController : MewMvpViewController
|
||||
@interface MewHomeViewController : MewBaseViewController
|
||||
|
||||
@end
|
||||
|
||||
|
@@ -24,9 +24,7 @@
|
||||
#import "MewMacro.h"
|
||||
#import "MewThemeColor.h"
|
||||
#import "MewHUDTool.h"
|
||||
/// P
|
||||
#import "MewHomePresenter.h"
|
||||
#import "MewHomeProtocol.h"
|
||||
|
||||
/// Model
|
||||
#import "MewFansInfoModel.h"
|
||||
#import "MewUserInfoModel.h"
|
||||
@@ -34,7 +32,7 @@
|
||||
#import <IQKeyboardManager/IQKeyboardManager.h>
|
||||
#import <NIMSDK/NIMSDK.h>
|
||||
|
||||
@interface MewHomeViewController ()<MewHeaderViewDelegate, MewShowVoiceViewDelegate,MewUserIntroductionViewDelegate,MewPushExclusiveVoiceViewDelegate, MewHomeProtocol,MewRightFollowVoiceViewDelegate>
|
||||
@interface MewHomeViewController ()<MewHeaderViewDelegate, MewShowVoiceViewDelegate,MewUserIntroductionViewDelegate,MewPushExclusiveVoiceViewDelegate,MewRightFollowVoiceViewDelegate>
|
||||
|
||||
/// 引导页
|
||||
@property (nonatomic, strong) MewVoiceGuideView *guideView;
|
||||
@@ -88,9 +86,7 @@
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (MewHomePresenter *)createPresenter {
|
||||
return [[MewHomePresenter alloc] init];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Life Cycle
|
||||
- (void)viewDidLoad {
|
||||
@@ -111,7 +107,16 @@
|
||||
|
||||
#pragma mark - Load Data (获取数据)
|
||||
- (void)mew_loadHomeDataWithGender:(NSString *)gender {
|
||||
[self.presenter mew_getMewHomeFriendListWithGender:gender];
|
||||
[MewOCServerManager mewRequestRandomFindFriendList:^(MewBaseModel * _Nullable obj, NSInteger num, NSString * _Nonnull text) {
|
||||
if(obj.code == 200){
|
||||
NSArray *array = [MewUserInfoModel mewModelsWithArray:obj.data[@"randomList"]];
|
||||
MewUserInfoModel *mineModel = [MewUserInfoModel mewModelWithDictionary:obj.data[@"me"]];
|
||||
self.MewUserInfoModels = array;
|
||||
self.showVoiceView.userInfoArrays = self.MewUserInfoModels;
|
||||
self.selfMineModel = mineModel;
|
||||
}
|
||||
} gender:gender];
|
||||
|
||||
}
|
||||
|
||||
- (void)setFilterString:(NSString *)filterString {
|
||||
@@ -124,7 +129,8 @@
|
||||
// 关注下拉刷新
|
||||
- (void)mew_loadFollownModelRefresh {
|
||||
self.page = 1;
|
||||
[self.presenter mew_getUserAttentionList:self.page pageSize:20 state:0];
|
||||
|
||||
[self mewGetFanListData:@(self.page).stringValue pageSize:@"20" state:@"0"];
|
||||
}
|
||||
|
||||
// 关注加载更多
|
||||
@@ -134,9 +140,35 @@
|
||||
return;
|
||||
}
|
||||
self.page++;
|
||||
[self.presenter mew_getUserAttentionList:self.page pageSize:20 state:1];
|
||||
|
||||
[self mewGetFanListData:@(self.page).stringValue pageSize:@"20" state:@"1"];
|
||||
}
|
||||
-(void)mewGetFanListData:(NSString *)page pageSize:(NSString *)pageSize state:(NSString *)state{
|
||||
NSString * uid= [MewSaveBaseUserModel share].mewGetUserId;
|
||||
|
||||
NSString * pageStr = [NSString stringWithFormat:@"%@", page];
|
||||
NSString * pageSizeStr = [NSString stringWithFormat:@"%@", pageSize];
|
||||
[MewOCServerManager mewGetLikeListInfo:^(MewBaseModel * _Nullable obj, NSInteger num, NSString * _Nonnull text) {
|
||||
if(obj.code == 200){
|
||||
NSArray * array = [MewUserInfoModel mewModelsWithArray:obj.data];
|
||||
if (state == 0) {
|
||||
[self.fansListModels removeAllObjects];
|
||||
[self.rightFollowVoiceView.followCollectionView.mj_header endRefreshing];
|
||||
} else {
|
||||
[self.rightFollowVoiceView.followCollectionView.mj_footer endRefreshing];
|
||||
}
|
||||
if (array.count > 0) {
|
||||
self.hasNoMoreData = NO;
|
||||
[self.fansListModels addObjectsFromArray:array];
|
||||
} else {
|
||||
self.hasNoMoreData = YES;
|
||||
[self.rightFollowVoiceView.followCollectionView.mj_footer endRefreshingWithNoMoreData];
|
||||
}
|
||||
|
||||
self.rightFollowVoiceView.fansListModel = [self.fansListModels copy];
|
||||
}
|
||||
} uid:uid pageNo:pageStr pageSize:pageSize];
|
||||
}
|
||||
|
||||
#pragma mark - MewHomeProtocol
|
||||
/// 获取用户的信息成功
|
||||
- (void)mew_getUserDetailInfoSuccess:(MewUserInfoModel *)userInfo {
|
||||
@@ -144,65 +176,14 @@
|
||||
// [self.userIntroductionView setCurrentUserModel:userInfo];
|
||||
}
|
||||
|
||||
// 关注 || 取消关注成功
|
||||
- (void)mew_attentionUserSuccess:(BOOL)status {
|
||||
[MewHUDTool showSuccessWithMessage: status ? @"关注成功" : @"取消关注成功"];
|
||||
[self.userIntroductionView updateAttentionState:status];
|
||||
}
|
||||
|
||||
// 获取两个人的关注
|
||||
- (void)mew_getUserAttentionSuccess:(BOOL)status {
|
||||
[self.userIntroductionView updateAttentionState:status];
|
||||
}
|
||||
|
||||
|
||||
/// 上传声音秀成功
|
||||
- (void)mew_uploadVoiceFileToThirdSuccess:(NSString *)fileUrl {
|
||||
|
||||
if (self.voiceString.length == 0 || self.voiceString == nil || [self.voiceString isEqualToString:@""]) {
|
||||
self.voiceString = @"这个人很懒还没有签名";
|
||||
}
|
||||
|
||||
[self.presenter mewPublishVoiceShowDura:[NSString stringWithFormat:@"%ld",self.duration] desc:self.voiceString gender:self.selfMineModel.gender == MewSexType_Male ? @"1" : @"2" url:fileUrl];
|
||||
|
||||
}
|
||||
|
||||
/// 上传mew声音秀成功
|
||||
- (void)mewPublishVoiceShowSuccess {
|
||||
[MewHUDTool showSuccessWithMessage:@"上传音频成功"];
|
||||
[MewPushExclusiveVoiceView removeExclusiveViewFromSuperView];
|
||||
}
|
||||
|
||||
/// 上传声音秀失败
|
||||
- (void)mew_uploadVoiceFileFail:(NSString *)message {
|
||||
[MewHUDTool showSuccessWithMessage:@"上传音频失败,请重新上传"];
|
||||
|
||||
}
|
||||
|
||||
- (void)mew_getMewHomeFriendListSuccesss:(NSArray *)array selfMine:(nonnull MewUserInfoModel *)selfMineModel {
|
||||
self.MewUserInfoModels = array;
|
||||
self.showVoiceView.userInfoArrays = self.MewUserInfoModels;
|
||||
self.selfMineModel = selfMineModel;
|
||||
}
|
||||
|
||||
/// 获取关注好友列表
|
||||
- (void)mew_getUserAttentionListSuccess:(NSArray *)array state:(int)state {
|
||||
if (state == 0) {
|
||||
[self.fansListModels removeAllObjects];
|
||||
[self.rightFollowVoiceView.followCollectionView.mj_header endRefreshing];
|
||||
} else {
|
||||
[self.rightFollowVoiceView.followCollectionView.mj_footer endRefreshing];
|
||||
}
|
||||
if (array.count > 0) {
|
||||
self.hasNoMoreData = NO;
|
||||
[self.fansListModels addObjectsFromArray:array];
|
||||
} else {
|
||||
self.hasNoMoreData = YES;
|
||||
[self.rightFollowVoiceView.followCollectionView.mj_footer endRefreshingWithNoMoreData];
|
||||
}
|
||||
|
||||
self.rightFollowVoiceView.fansListModel = [self.fansListModels copy];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma mark - MewHeaderViewDelegate
|
||||
@@ -227,7 +208,7 @@
|
||||
|
||||
} else if (target == 1) { //换一换
|
||||
//重调接口
|
||||
[self.presenter mew_getMewHomeFriendListWithGender:self.filterString];
|
||||
[self mew_loadHomeDataWithGender:self.filterString];
|
||||
|
||||
} else { //个人中心
|
||||
MewUserIntroductionView *view = [MewUserIntroductionView showUserIntroductionViewWithType:UserIntroductionView_SelfMine delegate: self];
|
||||
@@ -259,7 +240,18 @@
|
||||
[self.navigationController pushViewController:vc animated:YES];
|
||||
} else {
|
||||
|
||||
[self.presenter mew_attentionUser:self.targetUid state:optionType == 1];
|
||||
|
||||
NSString *uid = [[MewSaveBaseUserModel share]mewGetUserId];
|
||||
NSString *ticket = [[MewSaveBaseUserModel share]mewUserTicket];
|
||||
NSString *type = optionType == 1 ? @"1" : @"2";
|
||||
[MewOCServerManager mewLikeUsr:^(MewBaseModel * _Nullable obj, NSInteger num, NSString * _Nonnull text) {
|
||||
if(obj.code == 200){
|
||||
[MewHUDTool showSuccessWithMessage: type ? @"关注成功" : @"取消关注成功"];
|
||||
[self.userIntroductionView updateAttentionState:type];
|
||||
}
|
||||
|
||||
} uid:uid likedUid:self.targetUid ticket:ticket type:type];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,7 +281,32 @@
|
||||
[MewHUDTool mew_showLoadingWithMessage:@"正在上传音频中请稍等"];
|
||||
self.voiceString = voiceIntroString;
|
||||
self.duration = dura;
|
||||
[self.presenter mew_uploadVoice:filePath];
|
||||
|
||||
|
||||
[MewOCServerManager mewRequestUploadPhotoToken:^(MewBaseModel * _Nullable obj, NSInteger num, NSString * _Nonnull text) {
|
||||
NSString *mewKey = obj.data[@"key"];
|
||||
NSString *mewToken = obj.data[@"token"];
|
||||
[MewOCServerManager mewUploadPhotoAction:filePath name:mewKey token:mewToken successBlock:^(NSString * _Nonnull key, NSDictionary * _Nonnull res) {
|
||||
NSString *url = res[@"path"];
|
||||
if (self.voiceString.length == 0 || self.voiceString == nil || [self.voiceString isEqualToString:@""]) {
|
||||
self.voiceString = @"这个人很懒还没有签名";
|
||||
}
|
||||
[MewOCServerManager mewPublishSoundInfo:^(MewBaseModel * _Nonnull data, NSInteger code, NSString * _Nonnull msg) {
|
||||
if(code == 200){
|
||||
[MewHUDTool showSuccessWithMessage:@"上传音频成功"];
|
||||
[MewPushExclusiveVoiceView removeExclusiveViewFromSuperView];
|
||||
return;
|
||||
}
|
||||
[MewHUDTool showSuccessWithMessage:@"上传音频失败,请重新上传"];
|
||||
|
||||
} dura:[NSString stringWithFormat:@"%ld",self.duration] desc:self.voiceString gender:self.selfMineModel.gender == MewSexType_Male ? @"1" : @"2" url:url];
|
||||
|
||||
} failureBlock:^(NSNumber * _Nonnull code, NSString * _Nonnull message) {
|
||||
|
||||
}];
|
||||
}];
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -335,9 +352,18 @@
|
||||
// if (self.MewUserInfoModels.count > index) {
|
||||
self.targetUid = [NSString stringWithFormat:@"%ld",userInfo.uid];
|
||||
// 获取当前用户的详细信息
|
||||
[self.presenter mew_getUserDetailInfoWithUid:self.targetUid];
|
||||
[MewOCServerManager mewGetDetailData:^(MewBaseModel * _Nullable obj, NSInteger num, NSString * _Nonnull text) {
|
||||
|
||||
} uid:self.targetUid page:@"1" pageSize:@"20"];
|
||||
// 获取与当前用户的关注状态
|
||||
[self.presenter mew_getUserAttentionState:self.targetUid];
|
||||
NSString *uid = [[MewSaveBaseUserModel share]mewGetUserId];
|
||||
[MewOCServerManager mewGetListStatus:^(MewBaseModel * _Nullable obj, NSInteger num, NSString * _Nonnull text) {
|
||||
if(obj.code == 200){
|
||||
BOOL isLike = ((NSNumber *)obj.data).boolValue;
|
||||
[self.userIntroductionView updateAttentionState:isLike];
|
||||
}
|
||||
} uid:uid isLikeUid:self.targetUid];
|
||||
|
||||
// }
|
||||
}
|
||||
|
||||
|
@@ -84,6 +84,11 @@
|
||||
[self.personCenterButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.center.equalTo(self.personCenterBgImageView);
|
||||
}];
|
||||
[self.voiceBgImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.width.mas_equalTo(260);
|
||||
make.height.mas_equalTo(23);
|
||||
make.left.mas_equalTo(20);
|
||||
}];
|
||||
[self.filterButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.centerY.equalTo(self.personCenterBgImageView);
|
||||
make.width.mas_equalTo(61);
|
||||
|
@@ -6,7 +6,7 @@
|
||||
//
|
||||
|
||||
#import "MewPlayVoiceView.h"
|
||||
#import "NetImageView.h"
|
||||
|
||||
#import "MewVoiceDiscView.h"
|
||||
/// Third
|
||||
#import <Masonry/Masonry.h>
|
||||
@@ -15,7 +15,7 @@
|
||||
#import "MewThemeColor.h"
|
||||
#import "MewMacro.h"
|
||||
#import "MewHUDTool.h"
|
||||
#import "MewButton.h"
|
||||
|
||||
|
||||
@interface MewPlayVoiceView()
|
||||
@property (nonatomic, strong) UIImageView *bgImageView;
|
||||
@@ -27,7 +27,7 @@
|
||||
/// 唱片机柄
|
||||
@property (nonatomic, strong) UIImageView *playVoiceImageView;
|
||||
/// 发布声音秀
|
||||
@property (nonatomic, strong) MewButton *pushVoiceButton;
|
||||
@property (nonatomic, strong) UIButton *pushVoiceButton;
|
||||
|
||||
@property (nonatomic, strong) UIView *optionVoiceBgView;
|
||||
/// 暂停
|
||||
@@ -187,10 +187,12 @@
|
||||
return _playVoiceButton;
|
||||
}
|
||||
|
||||
- (MewButton *)pushVoiceButton {
|
||||
- (UIButton *)pushVoiceButton {
|
||||
if (!_pushVoiceButton) {
|
||||
_pushVoiceButton = [[MewButton alloc] initWithImagePosition:MewButtonImagePositionRight];
|
||||
[_pushVoiceButton setImage:[UIImage imageNamed:@"mew_home_push_voice"] forState:UIControlStateNormal];
|
||||
_pushVoiceButton = [UIButton new];
|
||||
[_pushVoiceButton setImage: [UIImage imageNamed:@"mew_home_push_voice"] forState:UIControlStateNormal];
|
||||
[_pushVoiceButton setImageEdgeInsets:UIEdgeInsetsMake(0, 150, 0, 0)];
|
||||
[_pushVoiceButton setTitleEdgeInsets:UIEdgeInsetsMake(0, -50, 0, 0)];
|
||||
[_pushVoiceButton setTitle:@"发布声音秀" forState:UIControlStateNormal];
|
||||
_pushVoiceButton.layer.cornerRadius = 52.0/2;
|
||||
_pushVoiceButton.layer.masksToBounds = YES;
|
||||
@@ -198,7 +200,7 @@
|
||||
[MewThemeColor mewColorWithHexString:@"#FF60FD"],
|
||||
[MewThemeColor mewColorWithHexString:@"##8974FF"],
|
||||
[MewThemeColor mewColorWithHexString:@"#69EBFF"]
|
||||
] gradientType:MewGradientTypeLeftToRight imgSize:CGSizeMake(200, 52)];
|
||||
] gradientType:MewGradientTypeLeftToRight imgSize:CGSizeMake(250, 52)];
|
||||
_pushVoiceButton.backgroundColor = [UIColor colorWithPatternImage:backgroundImage];
|
||||
[_pushVoiceButton addTarget:self action:@selector(pushVoiceButtonAction) forControlEvents:UIControlEventTouchUpInside];
|
||||
}
|
||||
|
@@ -11,8 +11,8 @@
|
||||
#import "MewThemeColor.h"
|
||||
#import "UIImage+MewUtils.h"
|
||||
#import "MewUtility.h"
|
||||
#import "MewAccountInfoStorage.h"
|
||||
#import "NSArray+MewSafe.h"
|
||||
|
||||
|
||||
#import "MewHUDTool.h"
|
||||
/// Third
|
||||
#import <Masonry/Masonry.h>
|
||||
@@ -338,10 +338,10 @@ static MewPushExclusiveVoiceView *_exclusiveVoiceView = nil;
|
||||
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
|
||||
[dateFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
|
||||
NSString *date = [dateFormat stringFromDate:[NSDate date]];
|
||||
self.fileName = [NSString stringWithFormat:@"voiceShow_%@_%@.wav", [MewAccountInfoStorage instance].mew_getUid, date];
|
||||
self.fileName = [NSString stringWithFormat:@"voiceShow_%@_%@.wav", [MewSaveBaseUserModel share].mewGetUserId, date];
|
||||
NSFileManager *fileMgr = [[NSFileManager alloc] init];
|
||||
//创建文件管理器
|
||||
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) mewSafeObjectAtIndex:0] stringByAppendingPathComponent:@"voiceShow"];
|
||||
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"voiceShow"];
|
||||
self.totalFilePath = [filePath stringByAppendingPathComponent:self.fileName];
|
||||
if (![fileMgr fileExistsAtPath:filePath]) {
|
||||
//如果不存在,则说明是第一次运行这个程序,那么建立这个文件夹
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user