iOS —— 3Gshare项目总结与思考

发布于:2025-07-22 ⋅ 阅读:(19) ⋅ 点赞:(0)

登陆注册及推出主页面

这部分有两种写法:一种是在SceneDelegate中推出LoginVC,后在判断登陆成功后退去主要程序。另一种则是先加载主程序,后推出登陆页面。通过同组同学实践证明,后者在推出登陆页面时会闪一下,因此还是建议采用第一种方法。

本人的登陆页面在最初使用数组储存用户名和密码,后来发现在修改密码时会较为困难,因此我创建了一个单例类。

同时我简单了解了一种轻量化本地存储方式 setObject: forKey: 

他支持的对象类型包括:

类型

示例

NSString

用户名、token 等

NSNumber

整数、布尔值等

NSArray

字符串数组、数字数组等

NSDictionary

键值对结构

NSDate

时间

NSData

二进制数据(如图片、加密)

- (void)saveLoginStatus {
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:@"wutong" forKey:@"username"];
    [defaults setBool:YES forKey:@"isLoggedIn"];
    [defaults synchronize]; // 可选
}


//读取时

NSString *name = [[NSUserDefaults standardUserDefaults] objectForKey:@"username"];
BOOL isLoggedIn = [[NSUserDefaults standardUserDefaults] boolForKey:@"isLoggedIn"];
NSUserDefaults 的 setObject:forKey: 是用于保存简单用户数据的 API,轻量、易用,适合设置类数据(如用户名、偏好设置、登录状态等)。 
//  UserManager.m
//  3GShareee
//
//  Created by 吴桐 on 2025/7/18.
//

#import "UserManager.h"

@implementation UserManager

//单例
+ (instancetype)sharedManager {
    static UserManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[UserManager alloc] init];
        [manager loadUserData];
    });
    return manager;
}

- (id)init {
    self = [super init];
    if (self) {
        _usernames = [NSMutableArray array];
        _passwords = [NSMutableArray array];
        [_usernames addObject:@"1"];
        [_passwords addObject:@"1"];
    }
    return self;
}


//保存到本地
- (void)saveUserData {
    [[NSUserDefaults standardUserDefaults] setObject:self.usernames forKey:@"savedUsernames"];
    [[NSUserDefaults standardUserDefaults] setObject:self.passwords forKey:@"savedPasswords"];
    [[NSUserDefaults standardUserDefaults] synchronize];    //不懂,好像是保存
}

- (void)loadUserData {
    NSArray *savedUsernames = [[NSUserDefaults standardUserDefaults] objectForKey:@"savedUsernames"];
    NSArray *savedPasswords = [[NSUserDefaults standardUserDefaults] objectForKey:@"savedPasswords"];
    NSDictionary *savedGenders = [[NSUserDefaults standardUserDefaults] objectForKey:@"savedUserGenders"];
    
    if (savedUsernames) {
        self.usernames = [savedUsernames mutableCopy];
    }
    if (savedPasswords) {
        self.passwords = [savedPasswords mutableCopy];
    }
    
    if (![self.usernames containsObject:@"1"]) {
        [self.usernames addObject:@"1"];
        [self.passwords addObject:@"1"];
    }
}


- (BOOL)updatePasswordForUser:(NSString *)username oldPassword:(NSString *)oldPassword newPassword:(NSString *)newPassword {
    NSUInteger index = [self.usernames indexOfObject:username];
    
    if (index == NSNotFound) {  //NSNotFound 是 Objective-C 中的一个常量,表示“没有找到”的情况,常用于查找操作的结果。
        return NO;
    }
    if (![oldPassword isEqualToString:self.passwords[index]]) {
        return NO;
    }
    
    // 更新密码
    self.passwords[index] = newPassword;
    [self saveUserData];
    
    return YES;
}

@end

同时,我设置了管理员密码1 1,用于绕过调试时便捷登陆,不必输入较长密码。注册功能和修改密码功能中,密码为不小于6位的数字或字母。

自动登录

我设置了autoBtn,和autoBtn01。前者为切换的按钮主体,后者为一个辅助按钮,当用户点击文字时,也会触发和前者相同的函数从而实现按钮图标的切换,更加人性化。

[self.autoBtn setImage: [UIImage imageNamed: @"autoreserved.png"] forState: UIControlStateNormal];
    [self.autoBtn setImage: [UIImage imageNamed: @"autohighlighted.png"] forState: UIControlStateSelected];
    self.autoBtn.selected = NO;
    [self.autoBtn addTarget: self action: @selector(pressAuto) forControlEvents: UIControlEventTouchUpInside];

self.autoBtn1 = [UIButton buttonWithType: UIButtonTypeRoundedRect];
    self.autoBtn1.frame = CGRectMake(67, 550, 64, 16);
    [self.autoBtn1 setTitle: @"自动登录" forState: UIControlStateNormal];
    [self.autoBtn1 setTintColor: [UIColor colorWithDisplayP3Red: 14.0 / 255 green: 46.0 / 255 blue: 121.0 / 255 alpha: 1.0]];
    [self.autoBtn1 addTarget: self action: @selector(pressAuto) forControlEvents: UIControlEventTouchUpInside];

登陆

UserManager *userManager = [UserManager sharedManager];
    self.arrayUsername = userManager.usernames;
    self.arrayPassword = userManager.passwords;
-(void) pressLeft:(UIButton *) button{
    NSString *username = self.userName.text;
    NSString *password = self.passWord.text;

    // 非空检查
    if (username.length == 0 || password.length == 0) {
        [self showAlertWithMessage:@"用户名和密码不能为空"];
        return;
    }

    // 长度限制
    if (username.length > 10 || password.length > 10) {
        [self showAlertWithMessage:@"用户名和密码不能超过10个字符"];
        return;
    }

    // 正则判断是否仅包含字母、数字、下划线
    // 本人暂时还没学...
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^[A-Za-z0-9_]+$" options:0 error:nil];
    if ([regex numberOfMatchesInString:username options:0 range:NSMakeRange(0, username.length)] == 0 ||
        [regex numberOfMatchesInString:password options:0 range:NSMakeRange(0, password.length)] == 0) {
        [self showAlertWithMessage:@"用户名和密码只能包含字母、数字和下划线"];
        return;
    }

    BOOL correct = NO;
    for (int i = 0; i < self.arrayUsername.count; i++) {
            if ([self.arrayUsername[i] isEqualToString: self.userName.text] &&
                [self.arrayPassword[i] isEqualToString: self.passWord.text] &&
                (self.userName.text != nil) &&
                (self.passWord.text != nil)) {
                correct = YES;
                
                // 保存当前登录用户
                UserManager *userManager = [UserManager sharedManager];
                userManager.currentUser = self.userName.text;
                
                break;
            }
        }
    if (!correct) {
        UIAlertController* wrongWarning  = [UIAlertController alertControllerWithTitle:@"❗️" message:@"账号密码错误!" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction* sure = [UIAlertAction actionWithTitle:@"O K" style:UIAlertActionStyleDefault handler:nil];
        [wrongWarning addAction:sure];
        [self presentViewController:wrongWarning animated:YES completion:nil];
    } else {
        FirstVC* firstView = [[FirstVC alloc] init];
        firstView.view.backgroundColor = [UIColor colorWithRed: (230.0 / 255) green: (222.0 / 255) blue: (220.0 / 255) alpha: 1];
        firstView.tabBarItem = [[UITabBarItem alloc] initWithTitle: nil image: [[UIImage imageNamed: @"FirstVC.png"]  imageWithRenderingMode: UIImageRenderingModeAlwaysOriginal] selectedImage: [[UIImage imageNamed: @"FirstVC_tapped.png"] imageWithRenderingMode: UIImageRenderingModeAlwaysOriginal] ];
        SecondVC* secondView = [[SecondVC alloc] init];
        secondView.view.backgroundColor = [UIColor colorWithRed: (230.0 / 255) green: (222.0 / 255) blue: (220.0 / 255) alpha: 1];
        secondView.tabBarItem = [[UITabBarItem alloc] initWithTitle: nil image: [[UIImage imageNamed: @"SecondVC.png"] imageWithRenderingMode: UIImageRenderingModeAlwaysOriginal] selectedImage: [[UIImage imageNamed: @"SecondVC_tapped.png"] imageWithRenderingMode: UIImageRenderingModeAlwaysOriginal] ];
        ThirdVC* thirdView = [[ThirdVC alloc] init];
        thirdView.view.backgroundColor = [UIColor colorWithRed: (230.0 / 255) green: (222.0 / 255) blue: (220.0 / 255) alpha: 1];
        thirdView.tabBarItem = [[UITabBarItem alloc] initWithTitle: nil image: [[UIImage imageNamed: @"ThirdVC.png"] imageWithRenderingMode: UIImageRenderingModeAlwaysOriginal] selectedImage: [[UIImage imageNamed: @"ThirdVC_tapped.png"] imageWithRenderingMode: UIImageRenderingModeAlwaysOriginal] ];
        FourthVC* fourthView = [[FourthVC alloc] init];
        fourthView.view.backgroundColor = [UIColor colorWithRed: (230.0 / 255) green: (222.0 / 255) blue: (220.0 / 255) alpha: 1];
        fourthView.tabBarItem = [[UITabBarItem alloc] initWithTitle: nil image: [[UIImage imageNamed: @"FourthVC.png"] imageWithRenderingMode: UIImageRenderingModeAlwaysOriginal] selectedImage: [[UIImage imageNamed: @"FourthVC_tapped.png"] imageWithRenderingMode: UIImageRenderingModeAlwaysOriginal] ];
        FifthVC* fifthView = [[FifthVC alloc] init];
        fifthView.view.backgroundColor = [UIColor colorWithRed: (230.0 / 255) green: (222.0 / 255) blue: (220.0 / 255) alpha: 1];
        fifthView.tabBarItem = [[UITabBarItem alloc] initWithTitle: nil image: [[UIImage imageNamed: @"FifthVC.png"] imageWithRenderingMode: UIImageRenderingModeAlwaysOriginal] selectedImage: [[UIImage imageNamed: @"FifthVC_tapped.png"] imageWithRenderingMode: UIImageRenderingModeAlwaysOriginal] ];
        
        //用NavigationController将每个视图包起来
        UINavigationController* navigationFirst = [[UINavigationController alloc] initWithRootViewController:firstView];
        UINavigationController* navigationSecond = [[UINavigationController alloc] initWithRootViewController:secondView];
        UINavigationController* navigationThird = [[UINavigationController alloc] initWithRootViewController:thirdView];
        UINavigationController* navigationFourth = [[UINavigationController alloc] initWithRootViewController:fourthView];
        UINavigationController* navigationFifth = [[UINavigationController alloc] initWithRootViewController:fifthView];
        
        //组装
        UINavigationBarAppearance* appearance = [[UINavigationBarAppearance alloc] init];
        appearance.backgroundColor = [UIColor colorWithRed: (43.0 / 255) green: (123.0 / 255) blue: (191.0 / 255) alpha: 1];
        firstView.navigationController.navigationBar.standardAppearance = appearance;
        firstView.navigationController.navigationBar.barStyle = UIBarStyleDefault;

        firstView.navigationController.navigationBar.scrollEdgeAppearance = appearance;
        secondView.navigationController.navigationBar.scrollEdgeAppearance = appearance;
        thirdView.navigationController.navigationBar.scrollEdgeAppearance = appearance;
        fourthView.navigationController.navigationBar.scrollEdgeAppearance = appearance;
        fifthView.navigationController.navigationBar.scrollEdgeAppearance = appearance;
        
        NSArray* arrayViewController = [NSArray arrayWithObjects: navigationFirst, navigationSecond, navigationThird, navigationFourth, navigationFifth, nil];
        UITabBarController* tabBarViewController = [[UITabBarController alloc] init];
        tabBarViewController.viewControllers = arrayViewController;
        // 在tabBar上方添加自定义覆盖视图
        UIView* overlayView = [[UIView alloc] initWithFrame:CGRectMake(0, 50, WIDTH, tabBarViewController.tabBar.bounds.size.height)];
        overlayView.backgroundColor = [UIColor blackColor];
        overlayView.tag = 1001;
        [tabBarViewController.tabBar addSubview:overlayView];
        [tabBarViewController.tabBar bringSubviewToFront:overlayView];
        tabBarViewController.modalPresentationStyle = UIModalPresentationFullScreen;
        [self presentViewController: tabBarViewController animated: YES completion: nil];
    }
        
}

自动收起键盘

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [self.view endEditing:YES];
}

这两个方法笔者暂时也不算很清楚讲述,只算一知半解,只知道能实现这个功能 

- (void)keyboardWillAppear:(NSNotification *)notification{
    CGRect keyboardFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGFloat keyboardY = keyboardFrame.origin.y;
    [UIView animateWithDuration:0.3 animations:^{
        self.view.transform = CGAffineTransformMakeTranslation(0, keyboardY - self.view.frame.size.height + 20);
    }];
}

- (void)keyboardWillDisAppear:(NSNotification *)notification{
    [UIView animateWithDuration:0.3 animations:^{
        self.view.transform = CGAffineTransformIdentity;
    }];
}

注册

核心代码如下

-(void) pressConfirm {
    NSString *username = self.usernameTextField.text;
    NSString *password = self.passwordTextField.text;
    UserManager *userManager = [UserManager sharedManager];
    

    if (username.length == 0 || password.length == 0) {
        UIAlertController* warning = [UIAlertController alertControllerWithTitle:@"提示"
                                                                         message:@"账号或密码不能为空"
                                                                  preferredStyle:UIAlertControllerStyleAlert];
        
        UIAlertAction* warn = [UIAlertAction actionWithTitle:@"确定"
                                                       style:UIAlertActionStyleDefault
                                                     handler:nil];
        
        [warning addAction:warn];
        [self presentViewController:warning animated:YES completion:nil];
        return;
    }
    
    // 检查密码长度是否大于6位
    if (password.length < 6) {
        UIAlertController* warning = [UIAlertController alertControllerWithTitle:@"提示"
                                                                         message:@"密码长度必须大于6位"
                                                                  preferredStyle:UIAlertControllerStyleAlert];
        
        UIAlertAction* warn = [UIAlertAction actionWithTitle:@"确定"
                                                       style:UIAlertActionStyleDefault
                                                     handler:nil];
        
        [warning addAction:warn];
        [self presentViewController:warning animated:YES completion:nil];
        return;
    }
    
    // 检查用户名是否已存在
    if ([userManager.usernames containsObject:username]) {
        UIAlertController* warning = [UIAlertController alertControllerWithTitle:@"提示"
                                                                         message:@"该用户名已被注册"
                                                                  preferredStyle:UIAlertControllerStyleAlert];
        
        UIAlertAction* warn = [UIAlertAction actionWithTitle:@"确定"
                                                       style:UIAlertActionStyleDefault
                                                     handler:nil];
        [warning addAction:warn];
        [self presentViewController:warning animated:YES completion:nil];
        return;
    }
    
    // 所有检查通过,注册新用户
    [userManager.usernames addObject:username];
    [userManager.passwords addObject:password];
    [userManager saveUserData]; // 保存到磁盘
    
    // 显示注册成功提示
    UIAlertController* successAlert = [UIAlertController alertControllerWithTitle:@"注册成功"
                                                                         message:@"您已成功注册"
                                                                  preferredStyle:UIAlertControllerStyleAlert];
    
    UIAlertAction* okAction = [UIAlertAction actionWithTitle:@"确定"
                                                       style:UIAlertActionStyleDefault
                                                     handler:^(UIAlertAction * _Nonnull action) {
        // 关闭注册页面
        [self dismissViewControllerAnimated:YES completion:nil];
    }];
    
    [successAlert addAction:okAction];
    [self presentViewController:successAlert animated:YES completion:nil];
    
    // 清空输入框
    self.usernameTextField.text = @"";
    self.passwordTextField.text = @"";
    self.emailTextField.text = @"";
}

FirstVC

因为文章的格式类似如图,我新建了一个cell用于设置所有类似的页面,textTableViewCell

首页中,我们需要在点击假日时跳转到另一个页面,同时实现两个页面之间的点赞同步。


先来说说推出假日页面。

我在texttableView中添加了一个手势识别

UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]
                                                    initWithTarget:self
                                                    action:@selector(CellTap)];
                [self.contentView addGestureRecognizer:tapGesture];
// 告诉我被点击了
- (void)CellTap {
    if ([self.delegate respondsToSelector:@selector(textTableViewCellDidTap:)]) {
        [self.delegate textTableViewCellDidTap:self];
    }
}

在首页中: 我们只处理第一行的情况

- (void)textTableViewCellDidTap:(textTableViewCell *)cell {
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    if (indexPath.section == 1 && indexPath.row == 0) {
        NSMutableDictionary *holidayData = [self.dataArray[0] mutableCopy];

        HolidayDetailViewController *detailVC = [[HolidayDetailViewController alloc] init];
        detailVC.holidayData = holidayData;
        detailVC.delegate = self;
        detailVC.isLiked = [holidayData[@"isLiked"] boolValue]; // 传递当前点赞状态
        
        // 推入导航栈
        [self.navigationController pushViewController:detailVC animated:YES];
    }
}

再来说说点赞。

其实下图中的方法更为简便,不需要我的多重传值

列表页点赞:
textTableViewCell (按钮点击) → FirstVC (更新数据源) → 刷新UI

详情页点赞:
HolidayDetailViewController → FirstVC (通过代理回调) → 更新数据源 → 刷新列表页单元格

传值法:

列表页点赞:

在textCell中:

- (void)likeButtonTapped:(UIButton *)sender {
    sender.selected = !sender.selected;
    
    //一种保护 检查是否实现方法
    if ([self.delegate respondsToSelector:@selector(textTableViewCell:didChangeLikeStatus:)]) {
            [self.delegate textTableViewCell:self didChangeLikeStatus:sender.selected];
        //调用代理方法
        }
}

对应FirstVC中:

- (void)textTableViewCell:(textTableViewCell *)cell didChangeLikeStatus:(BOOL)isLiked {
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    if (indexPath.row < self.dataArray.count) {
        NSMutableDictionary *item = [self.dataArray[indexPath.row] mutableCopy];
        item[@"isLiked"] = @(isLiked);
        self.dataArray[indexPath.row] = item;
    }
}

详情页点赞:

holidayVC: 

- (void)pressLike {
    self.isLiked = !self.isLiked;
    self.likeIcon.selected = self.isLiked;
    //通过代理通知列表页
    if ([self.delegate respondsToSelector:@selector(holidayDetail:didChangeLikeStatus:)]) {
        [self.delegate holidayDetail:self didChangeLikeStatus:self.isLiked];
    }
}

FirstVC:

- (void)holidayDetail:(HolidayDetailViewController *)detail didChangeLikeStatus:(BOOL)isLiked {
    NSMutableDictionary *holidayData = [self.dataArray[0] mutableCopy];
    holidayData[@"isLiked"] = @(isLiked);
    self.dataArray[0] = holidayData;
    
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:1];
    //这个函数可以刷新单元格
    [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}

SecondVC

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    if ([self.searchBar.text isEqualToString:@"大白"]) {
        SearchResultViewController* searchResultsView = [[SearchResultViewController alloc] init];
        [self.navigationController pushViewController: searchResultsView animated: YES];
    }
}

还有一部分是上传页面 

实现效果如图。两个textField用来输入作品名称和文章内容

折叠cell:

   self.foldButton = [UIButton buttonWithType:UIButtonTypeCustom];
    self.foldButton.frame = CGRectMake(315, 168, 48, 48);
    UIImage *foldImage = [UIImage imageNamed:@"guanbi.png"];
    [self.foldButton setImage:foldImage forState:UIControlStateNormal];
    [self.foldButton setTintColor:[UIColor colorWithRed:0.2 green:0.6 blue:0.9 alpha:1.0]];
    [self.foldButton addTarget:self action:@selector(pressUnfold) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.foldButton];
- (void)pressUnfold {
    [UIView animateWithDuration:0.3 animations:^{
        if (self.isFolded) {
            self.foldTableView.frame = CGRectMake(225, 180, 110, self.foldCellArray.count * 25);
            [self.foldButton setImage:[UIImage imageNamed:@"kaiqi.png"] forState:UIControlStateNormal];
        } else {
            self.foldTableView.frame = CGRectMake(225, 180, 110, 25);
            [self.foldButton setImage:[UIImage imageNamed:@"guanbi.png"] forState:UIControlStateNormal];
        }
    }];
    
    self.isFolded = !self.isFolded;
    [self.foldTableView reloadData]; // 刷新表格以显示正确行数
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    if (!self.isFolded) {
        NSString *selectedCategory = self.foldCellArray[indexPath.row];
        if (indexPath.row != 0) {
            [self.foldCellArray removeObjectAtIndex:indexPath.row];
            [self.foldCellArray insertObject:selectedCategory atIndex:0];
        }
        [self pressUnfold];
    } else {
        [self pressUnfold];
    }
}

上传图片: 

一个choosePhoto按钮用来弹出照片墙,另一个numbersOfPhotolabel用来显示选中的照片数量。如上文示范图。

- (void)pressChoosePhotoButton {
    PhotoWallViewController* photoWallViewController = [[PhotoWallViewController alloc] init];
    photoWallViewController.delegate = self;
    [self.navigationController pushViewController: photoWallViewController animated: YES];
}
- (void)pressPhoto: (UIButton*)button {
    if (button.selected == NO) {
        int selectNumber = (int)(button.tag - 100);
        self.numbersOfPhoto++;
        [self.imageNameArray addObject: [NSString stringWithFormat: @"photo%d.jpg", selectNumber]];
        button.selected = YES;
    } else {
        int selectNumber = (int)(button.tag - 100);
        self.numbersOfPhoto--;
        [self.imageNameArray removeObject: [NSString stringWithFormat: @"photo%d.jpg", selectNumber]];
        button.selected = NO;
    }
}
NSString* message = [NSString stringWithFormat: @"成功上传 %d 张图片!", self.numbersOfPhoto];
        UIAlertController* boomAlert = [UIAlertController alertControllerWithTitle: @"提示" message: message preferredStyle: UIAlertControllerStyleAlert];
        UIAlertAction* boomAction= [UIAlertAction actionWithTitle: @"确定" style: UIAlertActionStyleDefault handler: ^(UIAlertAction *action) {
            // 返回前调用代理方法
            if ([self.delegate respondsToSelector:@selector(changedPhotoName:andNumber:)]) {
                [self.delegate changedPhotoName:self.imageNameArray.firstObject andNumber:self.numbersOfPhoto];
            }
            [self.navigationController popViewControllerAnimated: YES];
        }];
        [boomAlert addAction: boomAction];
        [self presentViewController: boomAlert animated:YES completion:nil];

注意,在这里我们传回来的是数组的第一个元素

- (void)changedPhotoName:(NSString *)nameOfPhoto andNumber:(int)numbersOfPhoto {
    self.numbersOfPhoto = numbersOfPhoto;
    if (nameOfPhoto) {
        [self.choosePhoto setBackgroundImage:[UIImage imageNamed:nameOfPhoto] forState:UIControlStateNormal];
        [self.choosePhoto setTitle:@"" forState:UIControlStateNormal];
    }
    
    // 更新图片数量标签
    self.numbersOfPhotoLabel.text = [NSString stringWithFormat:@"%d", numbersOfPhoto];
    self.numbersOfPhotoLabel.hidden = (numbersOfPhoto == 0);
}

 在发布页面修改照片数量,同时修改那个背景。

ThirdVC

直接注册三个一模一样的cell,以实现互不干涉。古老简单但是有效

- (void)setupTableViews {
    CGFloat tableHeight = HEIGHT - 150;
    
    self.tableView01 = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, WIDTH, tableHeight) style:UITableViewStylePlain];
    self.tableView01.delegate = self;
    self.tableView01.dataSource = self;
    self.tableView01.backgroundColor = [UIColor whiteColor];
    self.tableView01.showsVerticalScrollIndicator = NO;
    self.tableView01.separatorStyle = UITableViewCellSeparatorStyleNone;
    
    self.tableView02 = [[UITableView alloc] initWithFrame:CGRectMake(WIDTH, 0, WIDTH, tableHeight) style:UITableViewStylePlain];
    self.tableView02.delegate = self;
    self.tableView02.dataSource = self;
    self.tableView02.backgroundColor = [UIColor whiteColor];
    self.tableView02.showsVerticalScrollIndicator = NO;
    self.tableView02.separatorStyle = UITableViewCellSeparatorStyleNone;
    
    self.tableView03 = [[UITableView alloc] initWithFrame:CGRectMake(WIDTH * 2, 0, WIDTH, tableHeight) style:UITableViewStylePlain];
    self.tableView03.delegate = self;
    self.tableView03.dataSource = self;
    self.tableView03.backgroundColor = [UIColor whiteColor];
    self.tableView03.showsVerticalScrollIndicator = NO;
    self.tableView03.separatorStyle = UITableViewCellSeparatorStyleNone;
    
    // 注册cell
    [self.tableView01 registerClass:[textTableViewCell class] forCellReuseIdentifier:@"cell"];
    [self.tableView02 registerClass:[textTableViewCell class] forCellReuseIdentifier:@"cell"];
    [self.tableView03 registerClass:[textTableViewCell class] forCellReuseIdentifier:@"cell"];
    
    [self.scrollView addSubview:self.tableView01];
    [self.scrollView addSubview:self.tableView02];
    [self.scrollView addSubview:self.tableView03];
}

- (void)createArticles {
    UIImage *defaultImage = [UIImage systemImageNamed:@"photo"];
    
    self.articlesSection0 = [NSMutableArray arrayWithArray:@[
        @{@"thumbnail": [UIImage imageNamed:@"article1"] ?: defaultImage, @"title": @"如期而至", @"author": @"SHARE 钢蛋", @"category": @"", @"time": @"16", @"isLiked": @NO},
        @{@"thumbnail": [UIImage imageNamed:@"article2"] ?: defaultImage, @"title": @"duck的学问", @"author": @"SHARE 王二麻", @"category": @"", @"time": @"20", @"isLiked": @NO},
        @{@"thumbnail": [UIImage imageNamed:@"article3"] ?: defaultImage, @"title": @"您的故事", @"author": @"SHARE 和尚", @"category": @"", @"time": @"25", @"isLiked": @NO},
        @{@"thumbnail": [UIImage imageNamed:@"article4"] ?: defaultImage, @"title": @"八月的故事", @"author": @"SHARE 二五", @"category": @"", @"time": @"60", @"isLiked": @NO},
        @{@"thumbnail": [UIImage imageNamed:@"article5"] ?: defaultImage, @"title": @"我们终将再见", @"author": @"SHARE 小唐", @"category": @"", @"time": @"60", @"isLiked": @NO}
    ]];
    
    self.articlesSection1 = [self.articlesSection0 mutableCopy];
    self.articlesSection2 = [self.articlesSection0 mutableCopy];
}

FourthVC

FifthVC

我上传的

直接调用ThirdVC中的页面

我的信息

评论 && 活动通知 && 我的推荐

这段代码我也没有很懂,只知道能实现一个类似这样的效果

UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:@"没有新内容" preferredStyle:UIAlertControllerStyleAlert];
        [self presentViewController:alert animated:YES completion:nil];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [alert dismissViewControllerAnimated:YES completion:nil];
        });

新关注的

这部分需要实现一个关注的留存如下图

 通过如下方式可以确保只创建一个followVC,进而保存之前的关注。

@property (nonatomic, strong) followViewController *followVC;



else if ([messageType isEqualToString:@"新关注的"]) {
        // 使用强引用确保只创建一次 followViewController
        if (!_followVC) {
            _followVC = [[followViewController alloc] init];
            _followVC.title = @"关注列表";
            _followVC.view.backgroundColor = [UIColor whiteColor];
        }
        [self.navigationController pushViewController:_followVC animated:YES];
私信:

首先要隐藏tabBar

// 隐藏tabBar
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    self.tabBarController.tabBar.hidden = YES;
}

// 恢复tabBar
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    self.tabBarController.tabBar.hidden = NO;
}

- (void)setupMessages {
    _messageArray = [NSMutableArray array];
    _rowHeightArray = [NSMutableArray array];
    
    [self addMessage:@"1~365选一个数字" isOutgoing:NO];
    [self addMessage:@"52" isOutgoing:YES];
    [self addMessage:@"我会在接下来的365天一直爱你" isOutgoing:NO];
    [self addMessage:@"我能不能重新选" isOutgoing:YES];
    [self addMessage:@"能" isOutgoing:NO];
    [self addMessage:@"1" isOutgoing:YES];
    [self addMessage:@"你只需要爱我一天,剩下的364天我来爱你" isOutgoing:YES];
    [self scrollToBottom];
}



- (void)addMessage:(NSString *)message isOutgoing:(BOOL)isOutgoing {
    //添加
    NSDictionary *messageDict = @{
        @"text": message,
        @"outgoing": @(isOutgoing)
    };
    [_messageArray addObject:messageDict];
    
    NSDictionary *attri = @{NSFontAttributeName: [UIFont systemFontOfSize:16]};  //16号字体
    
    
    //boundingRectWithSize:... 是 NSString 的一个方法:“请你告诉我最大容纳的尺寸,我会帮你计算出这段字符串在这些限制下需要多大的空间。”
    
    CGSize size = [message boundingRectWithSize:CGSizeMake(WIDTH * 0.6, CGFLOAT_MAX)
                                       options:NSStringDrawingUsesLineFragmentOrigin //绘图时请考虑换行,按段落来布局文字
                                    attributes:attri    //就是第1行设置的字体属性字典。告诉系统你用什么样的字体来绘制这段文字。
                                       context:nil].size;  //一般用于绘图时提供额外信息,但我们这里只是“量尺寸”,所以设置为 nil。
    
    CGFloat height = MAX(60, size.height + 40);//行高
    [_rowHeightArray addObject:@(height)];
}


- (void)sendMessage {
    if (self.textField.text.length == 0) return;

    [self addMessage:self.textField.text isOutgoing:self.isNextOutgoing];
    self.isNextOutgoing = !self.isNextOutgoing; //实现交替发送

    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.messageArray.count - 1 inSection:0];
    [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationBottom];
    
    //滑到底部
    [self scrollToBottom];
    self.textField.text = @"";
}

- (void)scrollToBottom {
    if (self.messageArray.count > 0) {
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.messageArray.count - 1 inSection:0];
        [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
    }
}


 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    //cell复用
    static NSString *cellIdentifier = @"MessageCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        cell.backgroundColor = [UIColor clearColor];
    } else {
        //清除原先的子视图
        for (UIView *subview in cell.contentView.subviews) {
            [subview removeFromSuperview];
        }
    }

设置

基本资料需要保存之前修改后的男女性别 不能人家改成女的推出去以后又成男的了

还是以前那个方法,只创建一次

- (void)showBasicInfo {
    if (!_basicsVC) {
            _basicsVC = [[basicsViewController alloc] init];
            _basicsVC.view.backgroundColor = [UIColor whiteColor];
        }
        [self.navigationController pushViewController:_basicsVC animated:YES];
}

修改密码:

- (void)pressButton {
    NSString *oldPassword = self.firstTextField.text;
    NSString *newPassword = self.secondTextField.text;
    NSString *confirmPassword = self.thirdTextField.text;
    
    UserManager *userManager = [UserManager sharedManager];
    NSString *currentUser = userManager.currentUser;
    
    if (currentUser.length == 0) {
        // 没有当前登录用户
        self.alertController = [UIAlertController alertControllerWithTitle:@"错误"
                                                                   message:@"无法获取当前登录用户信息"
                                                            preferredStyle:UIAlertControllerStyleAlert];
    }
    // 检查新密码长度
    else if (newPassword.length < 6 || newPassword.length > 20) {
        self.alertController = [UIAlertController alertControllerWithTitle:@"通知"
                                                                   message:@"密码需为6-20位英文或数字组合"
                                                            preferredStyle:UIAlertControllerStyleAlert];
    }
    // 检查两次密码是否一致
    else if (![newPassword isEqualToString:confirmPassword]) {
        self.alertController = [UIAlertController alertControllerWithTitle:@"通知"
                                                                   message:@"两次新密码输入不同"
                                                            preferredStyle:UIAlertControllerStyleAlert];
    }
    // 检查新密码是否与旧密码相同
    else if ([oldPassword isEqualToString:newPassword]) {
        self.alertController = [UIAlertController alertControllerWithTitle:@"通知"
                                                                   message:@"新密码不能与旧密码相同"
                                                            preferredStyle:UIAlertControllerStyleAlert];
    }
    // 尝试修改密码
    else {
        // 调用用户管理类修改密码
        if ([userManager updatePasswordForUser:currentUser oldPassword:oldPassword newPassword:newPassword]) {
            self.alertController = [UIAlertController alertControllerWithTitle:@"成功"
                                                                       message:@"密码修改成功"
                                                                preferredStyle:UIAlertControllerStyleAlert];
            
            // 修改成功后清空密码框
            self.firstTextField.text = @"";
            self.secondTextField.text = @"";
            self.thirdTextField.text = @"";
        } else {
            self.alertController = [UIAlertController alertControllerWithTitle:@"错误"
                                                                       message:@"旧密码不正确"
                                                                preferredStyle:UIAlertControllerStyleAlert];
        }
    }
    
    UIAlertAction *sure = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
    [self.alertController addAction:sure];
    [self presentViewController:self.alertController animated:YES completion:nil];
}

对应UserManger中:

- (BOOL)updatePasswordForUser:(NSString *)username oldPassword:(NSString *)oldPassword newPassword:(NSString *)newPassword {
    NSUInteger index = [self.usernames indexOfObject:username];
    
    if (index == NSNotFound) {  //NSNotFound 是 Objective-C 中的一个常量,表示“没有找到”的情况,常用于查找操作的结果。
        return NO;
    }
    if (![oldPassword isEqualToString:self.passwords[index]]) {
        return NO;
    }
    
    // 更新密码
    self.passwords[index] = newPassword;
    [self saveUserData];
    
    return YES;
}

其他页面:在此不过多赘述了

Tips:

self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; // 移除分隔线

这个代码可以用来移除cell间的分界线

 UIBarButtonItem* btn = [[UIBarButtonItem alloc] initWithImage: [UIImage imageNamed: @"holidayfanhui.png"] style: UIBarButtonItemStylePlain target: self action: @selector(pressReturn)];
    self.navigationItem.leftBarButtonItem = btn;
    btn.tintColor = [UIColor whiteColor];


- (void)pressReturn {
    [self.navigationController popViewControllerAnimated: YES];
}

这段代码可以用来自定义返回键类

// 在tabBar上方添加自定义覆盖视图
        UIView* overlayView = [[UIView alloc] initWithFrame:CGRectMake(0, 50, WIDTH, tabBarViewController.tabBar.bounds.size.height)];
        overlayView.backgroundColor = [UIColor blackColor];
        [tabBarViewController.tabBar addSubview:overlayView];

这个代码可以实现遮挡tabBar和屏幕底部之间的区域,更加美观,当然如果为了更加自然可以自己调颜色。 


网站公告

今日签到

点亮在社区的每一天
去签到