欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

项目总结(一)

程序员文章站 2022-07-03 12:07:01
...
  • 圆角阴影的使用导致界面卡顿尤其是在UICollectionView和UITableView中的使用,以下代码大部分情况下可以马上把你的帧数提高在55帧每秒以上,它会使视图渲染内容被缓存起来,下次绘制的时候可以直接显示缓存,当然要在视图内容不改变的情况下。
self.layer.shouldRasterize = YES;  
self.layer.rasterizationScale = [UIScreen mainScreen].scale;
  • 同时实现阴影和圆角(弄一个和图片大小一样的view,然后把UIImageView放到里面,代码如下)
self.headImage.layer.cornerRadius = 10;
    self.headImage.layer.masksToBounds = YES;
    
    self.shadowView.layer.shadowColor = RGB(40, 45, 65).CGColor;
    self.shadowView.layer.shadowOffset = CGSizeMake(1, 2);
    self.shadowView.layer.shadowOpacity = 0.1;
    self.shadowView.layer.shadowRadius = 4.0;
    self.shadowView.layer.cornerRadius = 4.0;
    self.shadowView.clipsToBounds = NO;
  • 使用 plist 存储的自定义对象时需要注意得时取出来的对象为不可变的,直接修改可能失败报错
    存储自定义对象要进行编解码把需要存储的数据转换为NSData类型,取出来的时候再将NSData转换成自己的类型 Model需要继承NSCoding,实现以下方法
/** 给自定义Model进行编码 */
- (void)encodeWithCoder:(NSCoder *)aCoder{
    [aCoder encodeObject:self.ID forKey:@"id"];
    [aCoder encodeObject:self.userCode forKey:@"userCode"];
    [aCoder encodeObject:self.userName forKey:@"userName"];
    [aCoder encodeObject:self.password forKey:@"password"];
    [aCoder encodeObject:self.status forKey:@"status"];
    [aCoder encodeObject:self.createTime forKey:@"createTime"];
    [aCoder encodeObject:self.mobileNumber forKey:@"mobileNumber"];
    [aCoder encodeObject:self.headImageName forKey:@"headImageName"];
    [aCoder encodeBool:self.isOnWiFiDownLoad forKey:@"isOnWiFiDownLoad"];
    [aCoder encodeBool:self.isAcceptInfo forKey:@"isAcceptInfo"];
}

/** 使用的时候还要进行解码 */
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder{
    if (self = [super init]) {
        self.ID = [aDecoder decodeObjectForKey:@"id"];
        self.userCode = [aDecoder decodeObjectForKey:@"userCode"];
        self.userName = [aDecoder decodeObjectForKey:@"userName"];
        self.password = [aDecoder decodeObjectForKey:@"password"];
        self.status = [aDecoder decodeObjectForKey:@"status"];
        self.createTime = [aDecoder decodeObjectForKey:@"createTime"];
        self.mobileNumber = [aDecoder decodeObjectForKey:@"mobileNumber"];
        self.headImageName = [aDecoder decodeObjectForKey:@"headImageName"];
        self.isAcceptInfo = [aDecoder decodeBoolForKey:@"isAcceptInfo"];
        self.isOnWiFiDownLoad = [aDecoder decodeBoolForKey:@"isOnWiFiDownLoad"];
    }
    return self;
}

如果需要修改存储到plist 文件中的自定义模型的数据,必须要把从plist文件中取出来的自定义对象变为可变对象,这样操作才会有效,把不可变对象变为可变对象 需要使Model继承NSMutableCopying 实现以下方法

- (id)mutableCopyWithZone:(NSZone *)zone{
    FXUserInfoModel *model = [[FXUserInfoModel allocWithZone:zone] init];
    model.ID = self.ID;
    model.userCode = self.userCode;
    model.userName =  self.userName;
    model.password =  self.password;
    model.status    =self.status;
    model.createTime = self.createTime;
    model.mobileNumber = self.mobileNumber;
    model.headImageName = self.headImageName;
    model.isAcceptInfo = self.isAcceptInfo;
    model.isOnWiFiDownLoad = self.isOnWiFiDownLoad;
    return model;
}
  • 具体操作:
/** 从plist 中取出自定义对象*/
 FXUserInfoModel *model = [[FXManager loadCustomObjectWithKey:[NSString stringWithFormat:@"%@+%@",@"FXUserInfoModel",[UserDefaultsUtils valueWithKey:@"userID"]]] mutableCopy];

/** 修改从plist中取出来的值 */
model.isOnWiFiDownLoad = NO;

/** 把修改后的值重新存回去 */
 [FXManager saveCustomObject:model withKey:[NSString stringWithFormat:@"%@+%@",@"FXUserInfoModel",[UserDefaultsUtils valueWithKey:@"userID"]]];

······完美解决
  • 如何实现互斥登陆,即同一账号只能同时在线一个用户,实现原理,服务器+友盟推送 实现同时只能在线一个账号
  1. 移动端需要我们设置HTTP请求头,给请求头传入和服务器端事先约定好的参数,这里我们传入两个参数:apiKey ,userId。第一个参数传注册友盟推送的时候系统回调传回来的deviceToken 这个参数是为了让后太推送确定把消息推送给指定的被下线的用户,第二个参数是为了确定用户的ID登录状态,我们还需要监听收到的通知,届时让服务器端配置一个自定义参数用于识别是否是下线通知,如果是,我们在当前界面做出响应,提示用户已下线。2.服务器端根据请求头的数据做出是否推送消息的动作,如果需要推送消息,则发送与移动端约定好的识别参数的通知。 具体代码如下
/** 第一步 在Application.m获取手机注册成功友盟推送回调得到deviceToken并保存 */
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    NSString *deviceTokenStr = [[[[deviceToken description] stringByReplacingOccurrencesOfString: @"<" withString: @""]
                                             stringByReplacingOccurrencesOfString: @">" withString: @""]
                                            stringByReplacingOccurrencesOfString: @" " withString: @""];
    
    [UserDefaultsUtils saveValue:deviceTokenStr forKey:@"apiKey"];
    NSDictionary *parameters = [[NSMutableDictionary alloc] init];
    NSString *userStr =[NSString stringWithFormat:@"%@",[UserDefaultsUtils valueWithKey:@"userID"]];
    if (!userStr || [userStr isEqualToString:@""]) {
        [parameters setValue:userStr forKey:@"userId"];
    }else{
        [parameters setValue:@"" forKey:@"userId"];
    }
    [parameters setValue:[UserDefaultsUtils valueWithKey:@"apiKey"] forKey:@"apiKey"];
    /** 动态设置请求头必须每次调用 updateBaseUrl 方法*/
    [HYBNetworking updateBaseUrl:BaseUrl];
    [HYBNetworking configCommonHttpHeaders:parameters];
}

/** 在前后台收到通知的时候判断是否为下线通知,如果是提示用户已下线,并且退出当前账号 */
//iOS10新增:处理前台收到通知的代理方法
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler{
    NSDictionary * userInfo = notification.request.content.userInfo;
    if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        //应用处于前台时的远程推送接受
        //关闭U-Push自带的弹出框
        [UMessage setAutoAlert:NO];
        //必须加这句代码
        [UMessage didReceiveRemoteNotification:userInfo];
        
        if ([userInfo[@"operationError"] isEqualToString:@"1001"]) {
            UIAlertController *alercConteoller = [UIAlertController alertControllerWithTitle:@"提示" message:@"当前账号已在其他设备登录,您已*下线" preferredStyle:UIAlertControllerStyleAlert];
            UIAlertAction *actionYes = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                [self signOutCurrentAccount];
            }];
            [alercConteoller addAction:actionYes];
            [[FXManager getCurrentVC] presentViewController:alercConteoller animated:YES completion:nil];
        }
        
    }else{
        //应用处于前台时的本地推送接受
    }
    //当应用处于前台时提示设置,需要哪个可以设置哪一个
    completionHandler(UNNotificationPresentationOptionSound|UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionAlert);
}

//iOS10新增:处理后台点击通知的代理方法
-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler{
    NSDictionary * userInfo = response.notification.request.content.userInfo;
    if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        //应用处于后台时的远程推送接受
        //必须加这句代码
        [UMessage didReceiveRemoteNotification:userInfo];
        if ([userInfo[@"operationError"] isEqualToString:@"1001"]) {
            UIAlertController *alercConteoller = [UIAlertController alertControllerWithTitle:@"提示" message:@"当前账号已在其他设备登录,您已*下线" preferredStyle:UIAlertControllerStyleAlert];
            UIAlertAction *actionYes = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                [self signOutCurrentAccount];
            }];
            [alercConteoller addAction:actionYes];
            [[FXManager getCurrentVC] presentViewController:alercConteoller animated:YES completion:nil];
        }
    }else{
        //应用处于后台时的本地推送接受
    }
}