当前位置: 移动技术网 > 移动技术>移动开发>IOS > iOS实现“摇一摇”与“扫一扫”功能示例代码

iOS实现“摇一摇”与“扫一扫”功能示例代码

2019年07月24日  | 移动技术网移动技术  | 我要评论

“摇一摇”功能的实现:

iphone对 “摇一摇”有很好的支持,总体说来就两步:

在视图控制器中打开接受“摇一摇”的开关;

 - (void)viewdidload {
  // 设置允许摇一摇功能
  [uiapplication sharedapplication].applicationsupportsshaketoedit = yes;
  // 并让自己成为第一响应者
  [self becomefirstresponder];
}

在“摇一摇”触发的制定的方法中实现需要实现的功能(”摇一摇“检测方法)。

// 摇一摇开始摇动 
- (void)motionbegan:(uieventsubtype)motion withevent:(uievent *)event { 
  nslog(@"开始摇动");
  //添加“摇一摇”动画
  [self addanimations];
  //音效
  audioservicesplaysystemsound (soundid); 
  return; 
} 

// “摇一摇”取消摇动 
- (void)motioncancelled:(uieventsubtype)motion withevent:(uievent *)event { 
  nslog(@"取消摇动"); 
  return; 
} 

// “摇一摇”摇动结束 
- (void)motionended:(uieventsubtype)motion withevent:(uievent *)event { 
  if (event.subtype == uieventsubtypemotionshake) { // 判断是否是摇动结束 
    nslog(@"摇动结束"); 
  } 
  return; 
} 

”摇一摇“的动画效果:

- (void)addanimations {
  //音效
  audioservicesplaysystemsound (soundid);
  //让上面图片的上下移动
  cabasicanimation *translation2 = [cabasicanimation animationwithkeypath:@"position"];
  translation2.timingfunction = [camediatimingfunction functionwithname:kcamediatimingfunctioneaseineaseout];
  translation2.fromvalue = [nsvalue valuewithcgpoint:cgpointmake(160, 115)];
  translation2.tovalue = [nsvalue valuewithcgpoint:cgpointmake(160, 40)];
  translation2.duration = 0.4;
  translation2.repeatcount = 1;
  translation2.autoreverses = yes;

  //让下面的图片上下移动
  cabasicanimation *translation = [cabasicanimation animationwithkeypath:@"position"];
  translation.timingfunction = [camediatimingfunction functionwithname:kcamediatimingfunctioneaseineaseout];
  translation.fromvalue = [nsvalue valuewithcgpoint:cgpointmake(160, 345)];
  translation.tovalue = [nsvalue valuewithcgpoint:cgpointmake(160, 420)];
  translation.duration = 0.4;
  translation.repeatcount = 1;
  translation.autoreverses = yes;

  [imgdown.layer addanimation:translation forkey:@"translation"];
  [imgup.layer addanimation:translation2 forkey:@"translation2"];  
}

注意:在模拟器中运行时,可以通过「hardware」-「shake gesture」来测试「摇一摇」功能。如下:

“扫一扫”功能的实现:

基于avcapturedevice做的二维码扫描器,基本步骤如下:

初始化相机,生成扫描器

 设置参数

 - (void)setupcamera {

  dispatch_async(dispatch_get_global_queue(dispatch_queue_priority_default, 0), ^{

    _device = [avcapturedevice defaultdevicewithmediatype:avmediatypevideo];

    _input = [avcapturedeviceinput deviceinputwithdevice:_device error:nil];

    _output = [[avcapturemetadataoutput alloc]init];
    [_output setmetadataobjectsdelegate:self queue:dispatch_get_main_queue()];

    _session = [[avcapturesession alloc]init];
    [_session setsessionpreset:avcapturesessionpresethigh];
    if ([_session canaddinput:self.input])
    {
      [_session addinput:self.input];
    }

    if ([_session canaddoutput:self.output])
    {
      [_session addoutput:self.output];
    }

    // 条码类型 avmetadataobjecttypeqrcode
    _output.metadataobjecttypes = [nsarray arraywithobjects:avmetadataobjecttypeean13code, avmetadataobjecttypeean8code, avmetadataobjecttypecode128code, avmetadataobjecttypeqrcode, nil];

    dispatch_async(dispatch_get_main_queue(), ^{
      //更新界面
      _preview =[avcapturevideopreviewlayer layerwithsession:self.session];
      _preview.videogravity = avlayervideogravityresizeaspectfill;
      _preview.frame = cgrectmake(0, 0, cgrectgetwidth(self.centerview.frame), cgrectgetheight(self.centerview.frame));
      [self.centerview.layer insertsublayer:self.preview atindex:0];
      [_session startrunning];
    });
  });
}

在viewwillappear和viewwilldisappear里对session做优化(timer是个扫描动画的计时器)

 - (void)viewwillappear:(bool)animated {
  [super viewwillappear:animated];

  if (_session && ![_session isrunning]) {
    [_session startrunning];
  }
  timer = [nstimer scheduledtimerwithtimeinterval:0.02 target:self selector:@selector(scanninganimation) userinfo:nil repeats:yes];
  [self setupcamera];
}

 - (void)viewwilldisappear:(bool)animated {
  [super viewwilldisappear:animated];
  _count = 0;
  [timer invalidate];
  [self stopreading];
}

处理扫描结果

 - (void)captureoutput:(avcaptureoutput *)captureoutput didoutputmetadataobjects:(nsarray *)metadataobjects fromconnection:(avcaptureconnection *)connection {

  nsstring *stringvalue;
  if ([metadataobjects count] >0){
    avmetadatamachinereadablecodeobject * metadataobject = [metadataobjects objectatindex:0];
    stringvalue = metadataobject.stringvalue;
    nslog(@"%@",stringvalue);
  }
  [_session stoprunning];
  [timer invalidate];
  _count ++ ;
  [self stopreading];
  if (stringvalue && _count == 1) {
    //扫描完成
  }
}

用二维码扫描器扫描自己的二维码:

nsstring *url = [nsurl urlwithstring:@"html/judgement.html" relativetourl:[zxapiclient sharedclient].baseurl].absolutestring;

  if ([stringvalue hasprefix:url]) {
    //如果扫出来的url是自己的域名开头的,那么做如下的处理
  }

最后附上自己完整的源码:

// created by ydw on 16/3/15. 
// copyright © 2016年 izhuo.net. all rights reserved. 
//

import “viewcontroller.h” 
import <avfoundation/avfoundation.h>

@interface viewcontroller () 
{ 
int number; 
nstimer *timer; 
nsinteger _count; 
bool upordown; 
avcapturedevice *lightdevice; 
}

@property (nonatomic,strong) uiview *centerview;//扫描的显示视图

/** 
* 二维码扫描参数 
*/ 
@property (strong,nonatomic) avcapturedevice *device; 
@property (strong,nonatomic) avcapturedeviceinput *input; 
@property (strong,nonatomic) avcapturemetadataoutput *output; 
@property (strong,nonatomic) avcapturesession *session; 
@property (strong,nonatomic) avcapturevideopreviewlayer *preview; 
@property (nonatomic,retain) uiimageview *imageview;//扫描线

(void)setupcamera;
(void)stopreading;
@end 

@implementation viewcontroller

- (void)viewwillappear:(bool)animated {
  [super viewwillappear:animated];

  if (_session && ![_session isrunning]) {
    [_session startrunning];
  }
  timer = [nstimer scheduledtimerwithtimeinterval:0.02 target:self selector:@selector(scanninganimation) userinfo:nil repeats:yes];
  [self setupcamera];
}

- (void)viewdidload {
  [super viewdidload];

  self.view.backgroundcolor = [uicolor clearcolor];
  self.automaticallyadjustsscrollviewinsets = no;

  _count = 0 ;
  //初始化闪光灯设备
  lightdevice = [avcapturedevice defaultdevicewithmediatype:avmediatypevideo];
  //扫描范围
  _centerview = [[uiview alloc]initwithframe:cgrectmake(0, 0, cgrectgetwidth(self.view.frame), cgrectgetheight(self.view.frame))];
  _centerview.backgroundcolor = [uicolor clearcolor];
  [self.view addsubview:_centerview];

  //扫描的视图加载
  uiview *scanningviewone = [[uiview alloc]initwithframe:cgrectmake(0, 0, self.view.frame.size.width, 120)];
  scanningviewone.backgroundcolor= [[uicolor blackcolor] colorwithalphacomponent:0.4];
  [self.centerview addsubview:scanningviewone];

  uiview *scanningviewtwo = [[uiview alloc]initwithframe:cgrectmake(0, 120, (self.view.frame.size.width-300)/2, 300)];
  scanningviewtwo.backgroundcolor= [[uicolor blackcolor] colorwithalphacomponent:0.4];
  [self.centerview addsubview:scanningviewtwo];

  uiview *scanningviewthree = [[uiview alloc]initwithframe:cgrectmake(cgrectgetwidth(self.view.frame)/2+150, 120, (self.view.frame.size.width-300)/2, 300)];
  scanningviewthree.backgroundcolor= [[uicolor blackcolor] colorwithalphacomponent:0.4];
  [self.centerview addsubview:scanningviewthree];

  uiview *scanningviewfour = [[uiview alloc]initwithframe:cgrectmake(0, 420, self.view.frame.size.width,cgrectgetheight(self.view.frame)- 420)];
  scanningviewfour.backgroundcolor= [[uicolor blackcolor] colorwithalphacomponent:0.4];
  [self.centerview addsubview:scanningviewfour];


  uilabel *labintroudction= [[uilabel alloc] initwithframe:cgrectmake(15, 430, self.view.frame.size.width - 30, 30)];
  labintroudction.backgroundcolor = [uicolor clearcolor];
  labintroudction.textalignment = nstextalignmentcenter;
  labintroudction.textcolor = [uicolor whitecolor];
  labintroudction.text = @"请将企业邀请码放入扫描框内";
  [self.centerview addsubview:labintroudction];

  uibutton *openlight = [[uibutton alloc]initwithframe:cgrectmake(cgrectgetwidth(self.view.frame)/2-25, 470, 50, 50)];
  [openlight setimage:[uiimage imagenamed:@"灯泡"] forstate:uicontrolstatenormal];
  [openlight setimage:[uiimage imagenamed:@"灯泡2"] forstate:uicontrolstateselected];
  [openlight addtarget:self action:@selector(openlightway:) forcontrolevents:uicontroleventtouchupinside];
  [self.centerview addsubview:openlight];

  //扫描线
  _imageview = [[uiimageview alloc] initwithframe:cgrectmake(cgrectgetwidth(self.view.frame)/2-110, 130, 220, 5)];
  _imageview.image = [uiimage imagenamed:@"scanning@3x"];
  [self.centerview addsubview:_imageview];
}

- (void)viewwilldisappear:(bool)animated {
  _count= 0;
  [timer invalidate];
  [self stopreading];
}

pragma mark -- 设置参数
- (void)setupcamera {

  dispatch_async(dispatch_get_global_queue(dispatch_queue_priority_default, 0), ^{

    _device = [avcapturedevice defaultdevicewithmediatype:avmediatypevideo];

    _input = [avcapturedeviceinput deviceinputwithdevice:_device error:nil];

    _output = [[avcapturemetadataoutput alloc]init];
    [_output setmetadataobjectsdelegate:self queue:dispatch_get_main_queue()];

    _session = [[avcapturesession alloc]init];
    [_session setsessionpreset:avcapturesessionpresethigh];
    if ([_session canaddinput:self.input])
    {
      [_session addinput:self.input];
    }

    if ([_session canaddoutput:self.output])
    {
      [_session addoutput:self.output];
    }

    // 条码类型 avmetadataobjecttypeqrcode
    _output.metadataobjecttypes = [nsarray arraywithobjects:avmetadataobjecttypeean13code, avmetadataobjecttypeean8code, avmetadataobjecttypecode128code, avmetadataobjecttypeqrcode, nil];

    dispatch_async(dispatch_get_main_queue(), ^{
      //更新界面
      _preview =[avcapturevideopreviewlayer layerwithsession:self.session];
      _preview.videogravity = avlayervideogravityresizeaspectfill;
      _preview.frame = cgrectmake(0, 0, cgrectgetwidth(self.centerview.frame), cgrectgetheight(self.centerview.frame));
      [self.centerview.layer insertsublayer:self.preview atindex:0];
      [_session startrunning];
    });
  });
}

//扫描动画
- (void)scanninganimation {
  if (upordown == no) {
    number ++;
    _imageview.frame = cgrectmake(cgrectgetwidth(self.view.frame)/2-115, 130+2*number, 230, 5);
    if (2*number == 280) {
      upordown = yes;
    }
  }
  else {
    number --;
    _imageview.frame = cgrectmake(cgrectgetwidth(self.view.frame)/2-115, 130+2*number, 230, 5);
    if (number == 0) {
      upordown = no;
    }
  }
}

- (void)stopreading {
  [_session stoprunning];
  _session = nil;
  [_preview removefromsuperlayer];
  [timer invalidate];
  timer = nil ;
}

-(void)openlightway:(uibutton *)sender {

  if (![lightdevice hastorch]) {//判断是否有闪光灯
    uialertcontroller *alert = [uialertcontroller alertcontrollerwithtitle:@"当前设备没有闪光灯,不能提供手电筒功能" message:nil preferredstyle:uialertcontrollerstylealert];
    uialertaction *sureaction = [uialertaction actionwithtitle:@"确定" style:uialertactionstylecancel handler:nil];
    [alert addaction:sureaction];
    [self presentviewcontroller:alert animated:yes completion:nil];
    return;
  }
  sender.selected = !sender.selected;
  if (sender.selected == yes) {
    [lightdevice lockforconfiguration:nil];
    [lightdevice settorchmode:avcapturetorchmodeon];
    [lightdevice unlockforconfiguration];
  }
  else
  {
    [lightdevice lockforconfiguration:nil];
    [lightdevice settorchmode: avcapturetorchmodeoff];
    [lightdevice unlockforconfiguration];
  }
}

pragma mark -- avcapturemetadataoutputobjectsdelegate
- (void)captureoutput:(avcaptureoutput *)captureoutput didoutputmetadataobjects:(nsarray *)metadataobjects fromconnection:(avcaptureconnection *)connection {

  nsstring *stringvalue;
  if ([metadataobjects count] >0){
    avmetadatamachinereadablecodeobject * metadataobject = [metadataobjects objectatindex:0];
    stringvalue = metadataobject.stringvalue;
    nslog(@"%@",stringvalue);
  }
  [_session stoprunning];
  [timer invalidate];
  _count ++ ;
  [self stopreading];
  if (stringvalue && _count == 1) {
    //扫描完成
  }
}

- (void)didreceivememorywarning {
  [super didreceivememorywarning];
  // dispose of any resources that can be recreated.
}

@end

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网