源代码:
链接:
https://pan.baidu.com/s/1RbBCULYZX3IcueN9dGBClQ 密码:gkhs
主要代码:
//
// ViewController.m
// 密码解锁---优化
//
// Created by 许磊 on 2019/2/23.
// Copyright © 2019年 xulei. All rights reserved.
//
#import "ViewController.h"
#import "ChangablemageView.h"
@interface ViewController ()
//不想被外部访问的信息
/**定义一个保存九个点的可变数组*/
@property (nonatomic,strong) NSMutableArray *dotViewArray;
/**定义一个保存所有线的Tag值得可变数组*/
@property (nonatomic,strong) NSMutableArray *lineTagsArray;
/**定义一个保存所有被选中的点或线的可变数组*/
@property (nonatomic,strong) NSMutableArray *selectedViewsArray;
/**保存上一个被点亮的点的Tag值*/
@property (nonatomic,assign) NSInteger lastSelectedDotTag;
/**定义一个提示接下来的操作的文本框*/
@property (nonatomic,strong) UILabel *hintLabel;
/**记录密码*/
@property (nonatomic,strong) NSMutableString *pwdString;
/**定义一个变量存储密码*/
@property (nonatomic,strong) NSString *password;
/**定义一个变量存储第一次设置的密码*/
@property (nonatomic,strong) NSString *firstPassword;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//初始化
[self arrayAndStringInit];
//界面布局
[self UIInit];
}
#pragma mark -------creatImageViewWithFrame ---------
//创建UIImageView呈现图片
- (UIImageView *)creatImageViewWithFrame:(CGRect) frame name:(NSString *)imageName{
//创建
UIImageView *imageView = [[ UIImageView alloc] initWithFrame:frame];
//添加图片
imageView.image = [UIImage imageNamed:imageName];
//不显示
imageView.hidden = YES;
//添加
[self.view addSubview:imageView];
return imageView;
}
#pragma mark -------arrayAndStringInit ---------
//数组初始化
- (void)arrayAndStringInit{
//初始化存放点的数组
self.dotViewArray = [NSMutableArray arrayWithCapacity:9];
//初始化存放Tag值得数组
self.lineTagsArray = [NSMutableArray array];
//初始化存放被选中的点或者线
self.selectedViewsArray = [NSMutableArray array];
//初始化字符串
self.pwdString = [NSMutableString string];
}
#pragma mark -------UIInit ---------
//界面布局
- (void)UIInit{
//创建背景图片
{
UIImageView *bgView = [self creatImageViewWithFrame:self.view.bounds name:@"DotLock_Normal"];
bgView.contentMode = UIViewContentModeScaleAspectFit;
//不隐藏
bgView.hidden = NO;
}
//添加操作图片
{
//添加九个点
[self addDot];
//添加六条横线
[self addTransverseLine];
//添加六条竖线
[self addVerticalLine];
//添加八条斜线
[self addSlantLine];
}
//提示框布局
{
//创建
self.hintLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 124, self.view.frame.size.width, 50)];
//文本
// _hintLabel.text = @"请绘制密码";
//字体颜色
_hintLabel.textColor = [UIColor blackColor];
//对齐方式
_hintLabel.textAlignment = NSTextAlignmentCenter;
//添加
[self.view addSubview:_hintLabel];
}
//密码操作
{
//获取密码
//[[NSUserDefaults standardUserDefaults] setObject:@"" forKey:@"password"];
self.password = [[NSUserDefaults standardUserDefaults] objectForKey:@"password"];
if (_password.length == 0) {
//设置密码
_hintLabel.text = @"请设置解锁图案";
} else {
//输入密码
_hintLabel.text = @"请绘制解锁图案";
}
}
}
#pragma mark -------addDot ---------
//添加九个点
- (void)addDot{
int index = 1;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//循环创建九个点
ChangablemageView *dotImageView = [ChangablemageView imageViewwithNormalImageName:@"DotLock_Selected" andWrongImageName:@"DotLock_Wrong" frame:CGRectMake(31+j*98, 214+i*97, 62, 62) father:self.view];
//dotImageView.hidden = NO;
//设置Tag值
dotImageView.tag = index;
index++;
//放到存放点的数组中
[self.dotViewArray addObject:dotImageView];
}
}
}
#pragma mark -------addTransverseLine ---------
//添加横线
//12 23 45 56 78 89
-(void)addTransverseLine{
int index = 12;
for (int i = 0; i < 6; i++) {
//循环创建六条横线
ChangablemageView *transverseImageView = [ChangablemageView imageViewwithNormalImageName:@"DotLock_Normal_Highlight1" andWrongImageName:@"DotLock_Wrong_Highlight1" frame:CGRectMake(90+i%2*97, 233+i/2*99, 38, 22) father:self.view];
//transverseImageView.hidden = NO;
//赋予Tag值
transverseImageView.tag = index;
//将Tag值添加到数组中
[self.lineTagsArray addObject:@(index)];
if ((i+1)%2 == 0 && i != 0) {
index = index + 11;
}
index = index + 11;
}
}
#pragma mark -------addVerticalLine ---------
//添加竖线
//14 25 36 47 58 69
-(void)addVerticalLine{
int index = 14;
for (int i = 0; i < 6; i++) {
//循环创建六条竖线
ChangablemageView *verticalImageView = [ChangablemageView imageViewwithNormalImageName:@"DotLock_Normal_Highlight2" andWrongImageName:@"DotLock_Wrong_Highlight2" frame:CGRectMake(51+i%3*99, 273+i/3*98, 20, 38) father:self.view];
//verticalImageView.hidden = NO;
//赋予Tag值
verticalImageView.tag = index;
//将Tag值添加到数组中
[self.lineTagsArray addObject:@(index)];
index = index + 11;
}
}
#pragma mark -------addSlantLine ---------
//添加斜线
//右斜 24 35 57 68
//左斜 15 26 48 59
-(void)addSlantLine{
int indexR = 15;
int indexL = 24;
for (int i = 0; i < 4; i++) {
//循环创建四条右斜线
ChangablemageView *rSlantLine = [ChangablemageView imageViewwithNormalImageName:@"DotLock_Normal_Highlight3" andWrongImageName:@"DotLock_Wrong_Highlight3" frame:CGRectMake(73+i%2*99, 255+i/2*99, 64, 64) father:self.view];
//rSlantLine.hidden = NO;
//赋予Tag值
rSlantLine.tag = indexR;
//将Tag值添加到数组中
[self.lineTagsArray addObject:@(indexR)];
indexR = indexR +11;
//循环创建四条左斜线
ChangablemageView *lSlantLine = [ChangablemageView imageViewwithNormalImageName:@"DotLock_Normal_Highlight4" andWrongImageName:@"DotLock_Wrong_Highlight4" frame:CGRectMake(82+i%2*99, 255+i/2*99, 64, 64) father:self.view];
//lSlantLine.hidden = NO;
//赋予Tag值
lSlantLine.tag = indexL;
//将Tag值添加到数组中
[self.lineTagsArray addObject:@(indexL)];
indexL = indexL +11;
if (i + 1 == 2) {
indexL = indexL + 11;
indexR = indexR + 11;
}
}
}
#pragma mark -------touchesBegan ---------
//开始触摸
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//获取触摸点的坐标
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self.view];
//判断触摸点有没有在摸一个圆点上
for (UIImageView *dotView in _dotViewArray) {
//判断
if (CGRectContainsPoint(dotView.frame, location)) {
//点亮
dotView.hidden = NO;
//记录这个点的Tag
_lastSelectedDotTag = dotView.tag;
//保存点亮的点
[_selectedViewsArray addObject:dotView];
//保存密码 拼接字符串
[self.pwdString appendFormat:@"%ld", (long)dotView.tag];
}
}
}
#pragma mark -------touchesMoved ---------
//滑动时
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//获取触摸点的坐标
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self.view];
//判断触摸点有没有在摸一个圆点上
for (UIImageView *dotView in _dotViewArray) {
//判断
if (CGRectContainsPoint(dotView.frame, location)) {
//如果这个点没有被点亮
if (dotView.hidden == YES) {
//是第一个点
if (_lastSelectedDotTag == 0) {
//直接点亮
dotView.hidden = NO;
//记录这个点的Tag
_lastSelectedDotTag = dotView.tag;
//保存点亮的点
[_selectedViewsArray addObject:dotView];
//保存密码 拼接字符串
[self.pwdString appendFormat:@"%ld", (long)dotView.tag];
} else {//不是第一个点
//判断上一个点和当前这个点之间有没有直接的线路
//获取上一个点和当前这个点的Tag组成的最小两位数
NSInteger lineTag = _lastSelectedDotTag > dotView.tag?dotView.tag*10+_lastSelectedDotTag:_lastSelectedDotTag*10+dotView.tag;
NSLog(@"%ld",(long)lineTag);
//数组里面有这条线
if ([_lineTagsArray containsObject:@(lineTag)]) {
//点亮
dotView.hidden = NO;
//点亮线
UIImageView *lineImageView = [self.view viewWithTag:lineTag];
lineImageView.hidden = NO;
//记录这个点的Tag
_lastSelectedDotTag = dotView.tag;
//保存点亮的点
[_selectedViewsArray addObject:dotView];
//保存密码 拼接字符串
[self.pwdString appendFormat:@"%ld", (long)dotView.tag];
//保存点亮的线
[_selectedViewsArray addObject:lineImageView];
}
}
}
}
}
}
#pragma mark -------touchesEnded ---------
//结束触摸
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//设置密码
if (_password.length == 0) {
//第一次
if (_firstPassword.length == 0) {
//保存刚才输入的密码
self.firstPassword = [NSString stringWithString:_pwdString];
[self hideAllViews];
_hintLabel.text = @"请确认密码图案";
} else {//第二次
//设置成功
if ([_firstPassword isEqualToString:_pwdString]) {
self.hintLabel.text = @"设置成功";
//保存密码
[[NSUserDefaults standardUserDefaults] setObject:_pwdString forKey:@"password"];
} else {
//不一致 重新设置
self.hintLabel.text = @"两次图案不一致 请重新绘制";
//换色
[self showWrong];
//self.firstPassword = @"";
}
}
} else {//解锁
//密码正确
if ([self.pwdString isEqualToString:_password]) {
self.hintLabel.text = @"解锁成功";
} else {//密码错误
self.hintLabel.text = @"密码错误";
//换色
[self showWrong];
}
}
}
-(void)showWrong{
for (ChangablemageView *imgView in _selectedViewsArray) {
//更换状态
[imgView changeImageWithStatus:kImageViewStatusWrong];
self.hintLabel.textColor = [UIColor redColor];
//延长一段时间后
[self performSelector:@selector(hideAllViews) withObject:nil afterDelay:1];
}
}
#pragma mark -------hideAllViews ---------
//隐藏所有的视图
-(void)hideAllViews{
for (ChangablemageView *imgView in _selectedViewsArray) {
//隐藏
imgView.hidden = YES;
//图片换回去
[imgView changeImageWithStatus:kImageViewStatusNormal];
}
self.hintLabel.textColor = [UIColor blackColor];
if ([_hintLabel.text isEqualToString:@"密码错误"]) {
_hintLabel.text = @"请重新输入";
}
if ([_hintLabel.text isEqualToString:@"两次图案不一致 请重新绘制"]) {
_hintLabel.text = @"请重新绘制确认密码";
}
//清空
[_selectedViewsArray removeAllObjects];
_lastSelectedDotTag = 0;
[_pwdString setString:@""];
}
@end
//
// ChangablemageView.h
// 密码解锁---优化
//
// Created by 许磊 on 2019/2/23.
// Copyright © 2019年 xulei. All rights reserved.
//
#import <UIKit/UIKit.h>
//图片的状态
typedef enum {
kImageViewStatusNormal,
kImageViewStatusWrong
} kImageViewStatus;
@interface ChangablemageView : UIImageView
/**表示正常图片的名字*/
@property (nonatomic,strong) NSString *normalImageName;
/**表示错误图片的名字*/
@property (nonatomic,strong) NSString *wrongImageName;
//根据状态改变
- (void)changeImageWithStatus:(kImageViewStatus)status;
//类方法创建图片
+(ChangablemageView *)imageViewwithNormalImageName:(NSString *)normal andWrongImageName:(NSString *)wrong frame:(CGRect)frame father:(UIView *)fatherView;
@end
//
// ChangablemageView.m
// 密码解锁---优化
//
// Created by 许磊 on 2019/2/23.
// Copyright © 2019年 xulei. All rights reserved.
//
#import "ChangablemageView.h"
@implementation ChangablemageView
-(void)changeImageWithStatus:(kImageViewStatus)status {
//正确图片
if (status == kImageViewStatusNormal) {
self.image = [UIImage imageNamed:_normalImageName];
} else{//错误图片
self.image = [UIImage imageNamed:_wrongImageName];
}
}
+(ChangablemageView *)imageViewwithNormalImageName:(NSString *)normal andWrongImageName:(NSString *)wrong frame:(CGRect)frame father:(UIView *)fatherView{
//创建
ChangablemageView *imgView = [[ChangablemageView alloc] initWithFrame:frame];
//图片名称
imgView.normalImageName = normal;
imgView.wrongImageName = wrong;
//图片
imgView.image = [UIImage imageNamed:normal];
//状态
imgView.hidden = YES;
//添加
[fatherView addSubview:imgView];
return imgView;
}
@end
运行结果:
附一:界面布局
1.背景图片
2.操作图片
3.加点
4.加线
附二:逻辑
1.如何记录密码
图案->密码2.如何点量点
用一个数组保存九个点的对象 滑动过程中 实时判断触摸点有没有在九个对象中的某一个上3.点亮线
a.触摸点必须在一个圆点上
b.上一个点和当前这个点得有线路
c.当前这个点没有被点亮过
(给每一条线添加一个Tag值,两个点的Tag值组成的最小两位数)
(用一个数组保存所有线条的Tag值)4.路径是否可到达
只需要判断连个点组成的两位数有没有在数组里面
如果在数组里面 说明有这条路径
如果不在说明没有线路 记录上一个被点亮的点
附三:步骤
1.添加线条的Tag值
2.将Tag值添加到数组里面NSNumber(或转化)
3.定义一个变量 记录 上一个被点亮的点的Tag值
4.定义一个数组用于保存所有点亮的点和线
5.记录密码---每一个圆点的Tag值拼接的字符串
6.设置密码过程
7.密码错误 显示红色 切换图片视图显示的图片,自定义一个继承于UIImageView的类
附四:个人改进点
可以重写initWithFrame,自定义图案解锁