2025-11-11 14:56:57 +08:00
|
|
|
|
//
|
|
|
|
|
|
// KBPersonInfoVC.m
|
|
|
|
|
|
// keyBoard
|
|
|
|
|
|
//
|
|
|
|
|
|
// Created by Mac on 2025/11/11.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// KBPersonInfoVC.m
|
|
|
|
|
|
// 个人资料
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
#import "KBPersonInfoVC.h"
|
|
|
|
|
|
#import <Masonry/Masonry.h>
|
|
|
|
|
|
#import "KBPersonInfoItemCell.h"
|
2025-11-11 15:13:43 +08:00
|
|
|
|
#import <PhotosUI/PhotosUI.h>
|
2025-11-11 15:28:22 +08:00
|
|
|
|
#import "LSTPopView.h"
|
|
|
|
|
|
#import "KBChangeNicknamePopView.h"
|
2025-11-11 15:55:52 +08:00
|
|
|
|
#import "KBGenderPickerPopView.h"
|
2025-11-11 14:56:57 +08:00
|
|
|
|
|
2025-11-11 15:13:43 +08:00
|
|
|
|
@interface KBPersonInfoVC () <UITableViewDelegate, UITableViewDataSource, PHPickerViewControllerDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate>
|
2025-11-11 14:56:57 +08:00
|
|
|
|
|
|
|
|
|
|
// 列表
|
|
|
|
|
|
@property (nonatomic, strong) BaseTableView *tableView; // 懒加载
|
|
|
|
|
|
|
|
|
|
|
|
// 头像区(表头)
|
|
|
|
|
|
@property (nonatomic, strong) UIView *headerView;
|
|
|
|
|
|
@property (nonatomic, strong) UIImageView *avatarView; // 头像
|
|
|
|
|
|
@property (nonatomic, strong) UIButton *editBadge; // 头像右下角的小铅笔
|
|
|
|
|
|
@property (nonatomic, strong) UILabel *modifyLabel; // “Modify” 文案
|
|
|
|
|
|
|
2025-11-11 15:13:43 +08:00
|
|
|
|
// 底部退出按钮(固定在屏幕底部)
|
2025-11-11 14:56:57 +08:00
|
|
|
|
@property (nonatomic, strong) UIButton *logoutBtn;
|
|
|
|
|
|
|
|
|
|
|
|
// 数据
|
|
|
|
|
|
@property (nonatomic, copy) NSArray<NSDictionary *> *items; // {title,value,arrow,copy}
|
2025-11-11 15:13:43 +08:00
|
|
|
|
// 压缩后的头像 JPEG 数据(可用于上传)
|
|
|
|
|
|
@property (nonatomic, strong) NSData *avatarJPEGData;
|
2025-11-11 14:56:57 +08:00
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
@implementation KBPersonInfoVC
|
|
|
|
|
|
|
|
|
|
|
|
- (void)viewDidLoad {
|
|
|
|
|
|
[super viewDidLoad];
|
|
|
|
|
|
self.kb_titleLabel.text = @"Settings"; // 导航标题
|
|
|
|
|
|
self.kb_navView.backgroundColor = [UIColor clearColor];
|
|
|
|
|
|
self.view.backgroundColor = [UIColor colorWithHex:0xF8F8F8];
|
|
|
|
|
|
|
|
|
|
|
|
// 构造数据
|
|
|
|
|
|
self.items = @[
|
|
|
|
|
|
@{ @"title": @"Nickname", @"value": @"Nickname", @"arrow": @YES, @"copy": @NO },
|
|
|
|
|
|
@{ @"title": @"Gender", @"value": @"Choose", @"arrow": @YES, @"copy": @NO },
|
|
|
|
|
|
@{ @"title": @"User ID", @"value": @"8888888", @"arrow": @NO, @"copy": @YES },
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
[self.view addSubview:self.tableView];
|
|
|
|
|
|
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.right.bottom.equalTo(self.view);
|
|
|
|
|
|
make.top.equalTo(self.view).offset(KB_NAV_TOTAL_HEIGHT + 10);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
2025-11-11 15:13:43 +08:00
|
|
|
|
// 表头
|
2025-11-11 14:56:57 +08:00
|
|
|
|
self.tableView.tableHeaderView = self.headerView;
|
2025-11-11 15:13:43 +08:00
|
|
|
|
|
|
|
|
|
|
// 底部退出按钮固定在屏幕底部
|
|
|
|
|
|
[self.view addSubview:self.logoutBtn];
|
|
|
|
|
|
[self.logoutBtn mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.equalTo(self.view).offset(16);
|
|
|
|
|
|
make.right.equalTo(self.view).offset(-16);
|
|
|
|
|
|
make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom).offset(-12);
|
|
|
|
|
|
make.height.mas_equalTo(56);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
// 列表底部腾出空间,避免被按钮挡住
|
|
|
|
|
|
UIEdgeInsets inset = self.tableView.contentInset;
|
|
|
|
|
|
inset.bottom = 56 + 24; // 按钮高度 + 额外间距
|
|
|
|
|
|
self.tableView.contentInset = inset;
|
2025-11-11 14:56:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#pragma mark - UITableView
|
|
|
|
|
|
|
|
|
|
|
|
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; }
|
|
|
|
|
|
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.items.count; }
|
|
|
|
|
|
|
|
|
|
|
|
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
|
|
|
|
|
|
return 56.0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 12.0; }
|
|
|
|
|
|
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { return [UIView new]; }
|
|
|
|
|
|
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { return 0.01; }
|
|
|
|
|
|
|
|
|
|
|
|
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
|
|
|
|
|
static NSString *cid = @"KBPersonInfoItemCell";
|
|
|
|
|
|
KBPersonInfoItemCell *cell = [tableView dequeueReusableCellWithIdentifier:cid];
|
|
|
|
|
|
if (!cell) { cell = [[KBPersonInfoItemCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cid]; }
|
|
|
|
|
|
NSDictionary *it = self.items[indexPath.row];
|
|
|
|
|
|
BOOL isTop = (indexPath.row == 0);
|
|
|
|
|
|
BOOL isBottom = (indexPath.row == self.items.count - 1);
|
|
|
|
|
|
[cell configWithTitle:it[@"title"]
|
|
|
|
|
|
value:it[@"value"]
|
|
|
|
|
|
showArrow:[it[@"arrow"] boolValue]
|
|
|
|
|
|
showCopy:[it[@"copy"] boolValue]
|
|
|
|
|
|
isTop:isTop
|
|
|
|
|
|
isBottom:isBottom];
|
|
|
|
|
|
return cell;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
|
|
|
|
|
if (indexPath.row == 0) {
|
2025-11-11 15:28:22 +08:00
|
|
|
|
// 昵称编辑 -> 弹窗
|
2025-11-11 15:55:52 +08:00
|
|
|
|
CGFloat width = KB_SCREEN_WIDTH;
|
2025-11-11 15:28:22 +08:00
|
|
|
|
KBChangeNicknamePopView *content = [[KBChangeNicknamePopView alloc] initWithFrame:CGRectMake(0, 0, width, 230)];
|
|
|
|
|
|
content.prefillNickname = self.items.firstObject[@"value"] ?: @"";
|
|
|
|
|
|
|
|
|
|
|
|
LSTPopView *pop = [LSTPopView initWithCustomView:content
|
|
|
|
|
|
parentView:self.view
|
|
|
|
|
|
popStyle:LSTPopStyleSmoothFromBottom
|
|
|
|
|
|
dismissStyle:LSTDismissStyleScale];
|
|
|
|
|
|
pop.bgColor = [[UIColor blackColor] colorWithAlphaComponent:0.4];
|
2025-11-11 15:55:52 +08:00
|
|
|
|
pop.hemStyle = LSTHemStyleBottom; // 居中
|
2025-11-11 15:28:22 +08:00
|
|
|
|
pop.isClickBgDismiss = YES; // 点击背景关闭
|
|
|
|
|
|
pop.isAvoidKeyboard = YES; // 规避键盘
|
|
|
|
|
|
pop.avoidKeyboardSpace = 10;
|
|
|
|
|
|
|
|
|
|
|
|
__weak typeof(self) weakSelf = self;
|
|
|
|
|
|
__weak typeof(pop) weakPop = pop;
|
|
|
|
|
|
content.closeHandler = ^{ [weakPop dismiss]; };
|
|
|
|
|
|
content.saveHandler = ^(NSString *nickname) {
|
|
|
|
|
|
if (nickname.length > 0) {
|
|
|
|
|
|
// 更新第一行展示
|
|
|
|
|
|
NSMutableArray *m = [weakSelf.items mutableCopy];
|
|
|
|
|
|
NSMutableDictionary *d0 = [m.firstObject mutableCopy];
|
|
|
|
|
|
d0[@"value"] = nickname; m[0] = d0; weakSelf.items = m;
|
|
|
|
|
|
[weakSelf.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
|
|
|
|
|
|
}
|
|
|
|
|
|
[weakPop dismiss];
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
[pop pop];
|
2025-11-11 15:55:52 +08:00
|
|
|
|
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.15 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [content focusInput]; });
|
2025-11-11 14:56:57 +08:00
|
|
|
|
} else if (indexPath.row == 1) {
|
2025-11-11 15:55:52 +08:00
|
|
|
|
// 性别选择 -> 弹窗
|
|
|
|
|
|
NSArray *genders = @[ @{@"id":@"1",@"name":@"Male"}, @{@"id":@"2",@"name":@"Female"}, @{@"id":@"3",@"name":@"The Third Gender"} ];
|
|
|
|
|
|
CGFloat width = KB_SCREEN_WIDTH;
|
|
|
|
|
|
KBGenderPickerPopView *content = [[KBGenderPickerPopView alloc] initWithFrame:CGRectMake(0, 0, width, 300)];
|
|
|
|
|
|
content.items = genders;
|
|
|
|
|
|
// 取当前展示值对应的 id(如果有的话)
|
|
|
|
|
|
NSString *curName = self.items[1][@"value"];
|
|
|
|
|
|
NSString *selId = nil;
|
|
|
|
|
|
for (NSDictionary *d in genders) { if ([d[@"name"] isEqualToString:curName]) { selId = d[@"id"]; break; } }
|
|
|
|
|
|
content.selectedId = selId;
|
|
|
|
|
|
|
|
|
|
|
|
LSTPopView *pop = [LSTPopView initWithCustomView:content
|
|
|
|
|
|
parentView:nil
|
|
|
|
|
|
popStyle:LSTPopStyleSmoothFromBottom
|
|
|
|
|
|
dismissStyle:LSTDismissStyleSmoothToBottom];
|
|
|
|
|
|
pop.bgColor = [[UIColor blackColor] colorWithAlphaComponent:0.4];
|
|
|
|
|
|
pop.hemStyle = LSTHemStyleBottom;
|
|
|
|
|
|
pop.isClickBgDismiss = YES;
|
|
|
|
|
|
|
|
|
|
|
|
__weak typeof(self) weakSelf = self; __weak typeof(pop) weakPop = pop;
|
|
|
|
|
|
content.closeHandler = ^{ [weakPop dismiss]; };
|
|
|
|
|
|
content.saveHandler = ^(NSDictionary *selected) {
|
|
|
|
|
|
NSString *name = selected[@"name"] ?: @"";
|
|
|
|
|
|
NSMutableArray *m = [weakSelf.items mutableCopy];
|
|
|
|
|
|
NSMutableDictionary *d1 = [m[1] mutableCopy];
|
|
|
|
|
|
d1[@"value"] = name; m[1] = d1; weakSelf.items = m;
|
|
|
|
|
|
[weakSelf.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:1 inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
|
|
|
|
|
|
[weakPop dismiss];
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
[pop pop];
|
2025-11-11 15:59:19 +08:00
|
|
|
|
}else if (indexPath.row == 2){
|
|
|
|
|
|
NSString *userID = self.items[2][@"value"];
|
|
|
|
|
|
if (userID.length == 0) return;
|
|
|
|
|
|
UIPasteboard.generalPasteboard.string = userID;
|
|
|
|
|
|
[KBHUD showInfo:@"复制成功"];
|
2025-11-11 14:56:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#pragma mark - Actions
|
|
|
|
|
|
|
2025-11-11 15:13:43 +08:00
|
|
|
|
- (void)onTapAvatarEdit { [self presentImagePicker]; }
|
2025-11-11 14:56:57 +08:00
|
|
|
|
|
|
|
|
|
|
- (void)onTapLogout {
|
|
|
|
|
|
// 示例:退出登录
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#pragma mark - Lazy UI(懒加载)
|
|
|
|
|
|
|
|
|
|
|
|
- (UITableView *)tableView {
|
|
|
|
|
|
if (!_tableView) {
|
|
|
|
|
|
// 使用 Plain,自行实现卡片留白与圆角,更贴近设计图
|
|
|
|
|
|
_tableView = [[BaseTableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
|
|
|
|
|
|
_tableView.backgroundColor = UIColor.clearColor;
|
|
|
|
|
|
_tableView.showsVerticalScrollIndicator = NO;
|
|
|
|
|
|
_tableView.separatorStyle = UITableViewCellSeparatorStyleNone; // 自定义分割
|
|
|
|
|
|
_tableView.dataSource = self; _tableView.delegate = self;
|
|
|
|
|
|
_tableView.contentInset = UIEdgeInsetsMake(8, 0, 16, 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
return _tableView;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (UIView *)headerView {
|
|
|
|
|
|
if (!_headerView) {
|
|
|
|
|
|
CGFloat w = UIScreen.mainScreen.bounds.size.width;
|
|
|
|
|
|
UIView *hv = [[UIView alloc] initWithFrame:CGRectMake(0, 0, w, 180)];
|
|
|
|
|
|
hv.backgroundColor = UIColor.clearColor;
|
|
|
|
|
|
|
|
|
|
|
|
[hv addSubview:self.avatarView];
|
|
|
|
|
|
[hv addSubview:self.editBadge];
|
|
|
|
|
|
[hv addSubview:self.modifyLabel];
|
|
|
|
|
|
|
|
|
|
|
|
[self.avatarView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.centerX.equalTo(hv);
|
|
|
|
|
|
make.top.equalTo(hv).offset(12);
|
|
|
|
|
|
make.width.height.mas_equalTo(96);
|
|
|
|
|
|
}];
|
|
|
|
|
|
[self.editBadge mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.width.height.mas_equalTo(24);
|
2025-11-11 15:13:43 +08:00
|
|
|
|
make.centerX.equalTo(self.avatarView.mas_right).offset(-15);
|
|
|
|
|
|
make.centerY.equalTo(self.avatarView.mas_bottom).offset(-15);
|
2025-11-11 14:56:57 +08:00
|
|
|
|
}];
|
|
|
|
|
|
[self.modifyLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.top.equalTo(self.avatarView.mas_bottom).offset(10);
|
|
|
|
|
|
make.centerX.equalTo(hv);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
2025-11-11 15:13:43 +08:00
|
|
|
|
// 头像可点击:弹系统相册
|
|
|
|
|
|
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapAvatarEdit)];
|
|
|
|
|
|
[self.avatarView addGestureRecognizer:tap];
|
|
|
|
|
|
|
2025-11-11 14:56:57 +08:00
|
|
|
|
_headerView = hv;
|
|
|
|
|
|
}
|
|
|
|
|
|
return _headerView;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (UIImageView *)avatarView {
|
|
|
|
|
|
if (!_avatarView) {
|
|
|
|
|
|
_avatarView = [[UIImageView alloc] init];
|
|
|
|
|
|
_avatarView.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0];
|
|
|
|
|
|
_avatarView.layer.cornerRadius = 48; _avatarView.layer.masksToBounds = YES;
|
|
|
|
|
|
// 外白描边
|
|
|
|
|
|
_avatarView.layer.borderWidth = 3.0; _avatarView.layer.borderColor = UIColor.whiteColor.CGColor;
|
|
|
|
|
|
// 占位图
|
|
|
|
|
|
UIGraphicsBeginImageContextWithOptions(CGSizeMake(96, 96), NO, 0);
|
|
|
|
|
|
CGContextRef ctx = UIGraphicsGetCurrentContext();
|
|
|
|
|
|
[[UIColor colorWithRed:0.86 green:0.95 blue:0.90 alpha:1] setFill];
|
|
|
|
|
|
CGContextFillEllipseInRect(ctx, CGRectMake(0, 0, 96, 96));
|
|
|
|
|
|
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
|
|
|
|
|
|
UIGraphicsEndImageContext();
|
|
|
|
|
|
_avatarView.image = img;
|
|
|
|
|
|
_avatarView.userInteractionEnabled = YES;
|
|
|
|
|
|
}
|
|
|
|
|
|
return _avatarView;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (UIButton *)editBadge {
|
|
|
|
|
|
if (!_editBadge) {
|
|
|
|
|
|
_editBadge = [UIButton buttonWithType:UIButtonTypeCustom];
|
|
|
|
|
|
_editBadge.layer.cornerRadius = 12; _editBadge.layer.masksToBounds = YES;
|
2025-11-11 15:13:43 +08:00
|
|
|
|
UIImage *img = [UIImage imageNamed:@"myperson_edit_icon"];
|
2025-11-11 14:56:57 +08:00
|
|
|
|
[_editBadge setImage:img forState:UIControlStateNormal];
|
|
|
|
|
|
[_editBadge addTarget:self action:@selector(onTapAvatarEdit) forControlEvents:UIControlEventTouchUpInside];
|
|
|
|
|
|
}
|
|
|
|
|
|
return _editBadge;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (UILabel *)modifyLabel {
|
|
|
|
|
|
if (!_modifyLabel) {
|
|
|
|
|
|
_modifyLabel = [UILabel new];
|
|
|
|
|
|
_modifyLabel.text = @"Modify";
|
2025-11-11 15:13:43 +08:00
|
|
|
|
_modifyLabel.textColor = [UIColor colorWithHex:KBBlackValue];
|
2025-11-11 14:56:57 +08:00
|
|
|
|
_modifyLabel.font = [UIFont systemFontOfSize:18 weight:UIFontWeightSemibold];
|
|
|
|
|
|
}
|
|
|
|
|
|
return _modifyLabel;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-11 15:13:43 +08:00
|
|
|
|
- (UIButton *)logoutBtn {
|
|
|
|
|
|
if (!_logoutBtn) {
|
|
|
|
|
|
_logoutBtn = [UIButton buttonWithType:UIButtonTypeSystem];
|
|
|
|
|
|
[_logoutBtn setTitle:@"Log Out" forState:UIControlStateNormal];
|
|
|
|
|
|
[_logoutBtn setTitleColor:[UIColor colorWithHex:0xFF0000] forState:UIControlStateNormal];
|
|
|
|
|
|
_logoutBtn.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold];
|
|
|
|
|
|
_logoutBtn.backgroundColor = UIColor.whiteColor;
|
|
|
|
|
|
_logoutBtn.layer.cornerRadius = 12; _logoutBtn.layer.masksToBounds = YES;
|
|
|
|
|
|
[_logoutBtn addTarget:self action:@selector(onTapLogout) forControlEvents:UIControlEventTouchUpInside];
|
|
|
|
|
|
}
|
|
|
|
|
|
return _logoutBtn;
|
|
|
|
|
|
}
|
2025-11-11 14:56:57 +08:00
|
|
|
|
|
2025-11-11 15:13:43 +08:00
|
|
|
|
#pragma mark - Image Picker
|
|
|
|
|
|
|
|
|
|
|
|
- (void)presentImagePicker {
|
|
|
|
|
|
if (@available(iOS 14.0, *)) {
|
|
|
|
|
|
PHPickerConfiguration *config = [[PHPickerConfiguration alloc] init];
|
|
|
|
|
|
config.selectionLimit = 1; // 只选一张
|
|
|
|
|
|
config.filter = [PHPickerFilter imagesFilter];
|
|
|
|
|
|
PHPickerViewController *picker = [[PHPickerViewController alloc] initWithConfiguration:config];
|
|
|
|
|
|
picker.delegate = self;
|
|
|
|
|
|
[self presentViewController:picker animated:YES completion:nil];
|
|
|
|
|
|
} else {
|
|
|
|
|
|
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
|
|
|
|
|
|
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
|
|
|
|
|
|
picker.delegate = self;
|
|
|
|
|
|
[self presentViewController:picker animated:YES completion:nil];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-11 14:56:57 +08:00
|
|
|
|
|
2025-11-11 15:13:43 +08:00
|
|
|
|
#pragma mark - PHPickerViewControllerDelegate
|
|
|
|
|
|
|
|
|
|
|
|
- (void)picker:(PHPickerViewController *)picker didFinishPicking:(NSArray<PHPickerResult *> *)results API_AVAILABLE(ios(14.0)) {
|
|
|
|
|
|
[picker dismissViewControllerAnimated:YES completion:nil];
|
|
|
|
|
|
PHPickerResult *first = results.firstObject; if (!first) return;
|
|
|
|
|
|
NSItemProvider *p = first.itemProvider;
|
|
|
|
|
|
if ([p canLoadObjectOfClass:UIImage.class]) {
|
|
|
|
|
|
__weak typeof(self) weakSelf = self;
|
|
|
|
|
|
[p loadObjectOfClass:UIImage.class completionHandler:^(__kindof id<NSItemProviderReading> _Nullable object, NSError * _Nullable error) {
|
|
|
|
|
|
UIImage *img = ([object isKindOfClass:UIImage.class] ? (UIImage *)object : nil);
|
|
|
|
|
|
if (!img) return;
|
|
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
|
|
UIImage *compressed = [weakSelf kb_compressImage:img maxPixel:512 quality:0.85];
|
|
|
|
|
|
weakSelf.avatarView.image = compressed;
|
|
|
|
|
|
weakSelf.avatarJPEGData = UIImageJPEGRepresentation(compressed, 0.85);
|
|
|
|
|
|
});
|
|
|
|
|
|
}];
|
2025-11-11 14:56:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-11 15:13:43 +08:00
|
|
|
|
#pragma mark - UIImagePickerControllerDelegate
|
|
|
|
|
|
|
|
|
|
|
|
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *)info {
|
|
|
|
|
|
UIImage *img = info[UIImagePickerControllerEditedImage] ?: info[UIImagePickerControllerOriginalImage];
|
|
|
|
|
|
if (img) {
|
|
|
|
|
|
UIImage *compressed = [self kb_compressImage:img maxPixel:512 quality:0.85];
|
|
|
|
|
|
self.avatarView.image = compressed;
|
|
|
|
|
|
self.avatarJPEGData = UIImageJPEGRepresentation(compressed, 0.85);
|
2025-11-11 14:56:57 +08:00
|
|
|
|
}
|
2025-11-11 15:13:43 +08:00
|
|
|
|
[picker dismissViewControllerAnimated:YES completion:nil];
|
2025-11-11 14:56:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-11 15:13:43 +08:00
|
|
|
|
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
|
|
|
|
|
|
[picker dismissViewControllerAnimated:YES completion:nil];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// 压缩图片:最长边不超过 maxPixel,输出近似 quality 的 JPEG
|
|
|
|
|
|
- (UIImage *)kb_compressImage:(UIImage *)image maxPixel:(CGFloat)maxPixel quality:(CGFloat)quality {
|
|
|
|
|
|
if (!image) return nil;
|
|
|
|
|
|
maxPixel = MAX(64, maxPixel);
|
|
|
|
|
|
CGSize size = image.size;
|
|
|
|
|
|
CGFloat maxSide = MAX(size.width, size.height);
|
|
|
|
|
|
CGSize target = size;
|
|
|
|
|
|
if (maxSide > maxPixel) {
|
|
|
|
|
|
CGFloat scale = maxPixel / maxSide;
|
|
|
|
|
|
target = CGSizeMake(floor(size.width * scale), floor(size.height * scale));
|
2025-11-11 14:56:57 +08:00
|
|
|
|
}
|
2025-11-11 15:13:43 +08:00
|
|
|
|
UIGraphicsBeginImageContextWithOptions(target, YES, 1.0);
|
|
|
|
|
|
[image drawInRect:CGRectMake(0, 0, target.width, target.height)];
|
|
|
|
|
|
UIImage *scaled = UIGraphicsGetImageFromCurrentImageContext();
|
|
|
|
|
|
UIGraphicsEndImageContext();
|
|
|
|
|
|
|
|
|
|
|
|
NSData *jpeg = UIImageJPEGRepresentation(scaled ?: image, MIN(MAX(quality, 0.2), 0.95));
|
|
|
|
|
|
UIImage *result = [UIImage imageWithData:jpeg] ?: scaled ?: image;
|
|
|
|
|
|
return result;
|
2025-11-11 14:56:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@end
|