Github上Fork代码,及源码修改

iOS开发中经常遇到这种情况,你使用的第三方库不能完全满足自己项目需要,只能修改源码来解决。
我们以前的解决办法是,添加到项目中直接修改源码。这样就有一个问题,不能和源库同步,当作者更新后你不能(pod update)更新,否则自己原来的修改就被冲掉了。所以只能选择不更新,或者更新后重新修改源码。

当第三方库更新时如何同步更新?Git的Fork功能解决了这种问题,当你fork别人的开源代码后,你可以随意的修改。当然你对自己的修改满意还可以请求合并到(pull request)原作者项目中去。

今天具体讲解如何在Github上Fork别人的代码,进行二次开发。下面以iOS-Charts为例,上一篇文章中我对这个开源库做了介绍。

  1. 首先你要有自己的Github账号
  2. 进入https://github.com/danielgindi/Charts 你要Fork项目的首页点击右上角Fork
  3. 到自己项目列表就可以看到刚刚Fork的项目了

234.png
234.png

现在你就可以当做自己的项目,随意的更改了。如果修改完之后你想和原来库合并,贡献自己的代码,就点击自己项目中的“New Pull Request”请求合并。作者同意后就可以在项目中看到自己贡献的代码了。

png

下面讲解本文的重点,如何修改源码满足自己项目需求。修改时注意一下几点:

  1. 改源码首先当然是读懂源码了,读懂后才知道从何下手。
  2. 查看源码时一开始不止如何下手,对于一些UI控件我的解决方式是采用“注释法”,先把不知道的代码注释掉然后运行查看效果,通过对比界面可以简单直接的看到代码在操控那里。
  3. 修改时要考虑如何最小的改动满足自己需求,可以尝试添加子类或者分类的形式解决。
  4. 实在没办法只能修改源码了,修改源码的地方最好做上标记,方便自己查看、修改。

举个例子,我们想要修改点击Charts高亮时的高亮线的形式,改之前的效果如下:

png

我们想要隐藏掉水平高亮线,只显示垂直高亮线,如下图所示:
png

通过查看源码我们可以知道LineChartDateSet的属性drawVerticalHighlightIndicatorEnabled是控制是否显示垂直高亮线的,我们简单推理,通过搜索这个属性我们应该能找到如何绘制高亮线的代码。

通过全局搜索 drawVerticalHighlightIndicatorEnabled结果如下图:

png

并没有找到绘制高亮线的代码,查看属性定义的地方发现drawVerticalHighlightIndicatorEnabled是存储属性,还有一个对应的计算性属性isVerticalHighlightIndicatorEnabled,我们接下来全局搜索isVerticalHighlightIndicatorEnabled ,结果如下:

通过注意查看,我们可以确定LineScatterCandleRadarChartRenderer.swift有绘制高亮线的地方,如下图:

png
可以发现35-38行是控制如何绘制竖直高亮线的代码,我们注释掉,

png
换成使用图片来绘制的代码,修改成如下代码(前提准备一张高亮图”highlight_line”):

1
2
3
4
5
6
7
CGContextSaveGState(context);
//获得高亮线图片
let lineImage = NSUIImage(named: "highlight_line")
//绘制
lineImage?.drawInRect(CGRectMake(point.x-5.0/2.0, viewPortHandler.contentTop, 5, viewPortHandler.contentBottom - viewPortHandler.contentTop))

CGContextRestoreGState( context );

运行看下效果轻松搞定。


更多iOS、Swift开发文章请关注微信公众账号 lecoding ,欢迎大家订阅,有什么问题可以在此一起交流。公众号搜索: 乐Coding 或者 lecoding 或者微信扫描下方二维码:

icon

iOS-Charts

001

最近很多读者问我为什么公众号最近一直没有更新,我在次对大家表示道歉,前段时间工作上比较忙,周末还要去学驾照(不到两个月就拿到本了,还是很开心),平时还在帮助朋友做点小项目,所以就没时间更新了。前边都是在扯淡,主要原因还是因为现在订阅用户太少,自己太懒,哈哈…

今天一时兴起给大家介绍一个好用的数据图开源库:iOS-Charts,github链接https://github.com/danielgindi/Charts,这个开源库是用Swift实现的,作者相当🐂,这个项目有9435个Star,Android也有他写的相应开源库:MPAndroidChart

001

001

001

001

001

001

001

001

001

001

001

001

001

###进店须知
先上几个美图,给大家个视觉感受,看看是不是你的菜,现在毕竟是看脸的时代。然后我再介绍她能提供哪些“特殊服务”。如果你满意接下来再具体给你介绍如何把“她”抱回家(具体配置和使用)。

###店长介绍
看完艳压群芳、技压群芳的姑凉们,如果感觉还不错,接下来听我具体介绍本店的”特殊服务”。本店特色、店长推荐,免除你独自撸码实现的烦恼。

  1. 可以实现8各不同类型的数据图
  2. 支持图形缩放(使用你勤劳的手指双击或者双指撑开)
  3. 支持拖拽和滑动
  4. 双轴线
  5. 自定义x轴或者y轴
  6. 高亮数据(自定义 popup-views)
  7. 以PNG、JPEG格式保存到相册
  8. 预定义颜色模板
  9. 图例(自动生成或者自定义)
  10. 动画(支持x轴和y轴动画)
  11. 限制线(用于显示添加限制信息或者最大值)
  12. 自定义(绘制、类型面板、图例、颜色、背景、手势、虚线)
  13. 绘制来自Realm.io移动数据库的数据

能看到这说明你也是一个痴情郎啊,既然选择就一往情深。下面看看如何带回家享受服务吧。

###缴费办理

####一、 手动配置

  1. Charts.xcodeproj拖拽到你的工程
  2. 打开target's settings,点击 Embedded Binaries下方的加号,选择Charts.framework
  3. Xcode 6.3.1 有一个bug,你必须先编译然后引入头文件
  4. @import Charts
  5. 在Objc项目中需要添加桥接文件

####一、 使用Pods
1.在Podfile文件中添加

1
pod 'Charts/Realm'

执行 pod install命令

售后服务

iOS-Charts已经能够实现大部分功能,当然由于业务需求,她不能完全满足你的需求,就需要你改源码了。比如我司业务还需要她满足一下功能:

  1. 数据点只支持圆点不支持正方形。
  2. 多条折线时无法同时高亮相同X轴的点
  3. 柱状图动画不支持数值变换

下一篇文章我会讲解如何在GitHub上Fork iOS-Charts的代码、修改源码满足自己的业务需求。

看到这,你才是“本店”的忠实粉丝啊,看在我们“优质的服务和合理的价格”,欢迎分享到朋友圈,未关注用户点击右上角关注哟。


本博客也会在 lecoding 微信公众号中同步更新,欢迎大家订阅,有什么问题可以在此一起交流。公众号搜索: 乐Coding 或者 lecoding 或者微信扫描下方二维码:

/img/icon.jpg

About Me

欢迎来到 LvesLi's Blogging 。我是李兴乐 ,从事互联网移动开发,乐于分享。欢迎订阅我的微信公众账号:”乐Coding”,里边有更多iOSSwift开发相关精彩文章。

联系方式如下:

  1. 微博@Lves李兴乐
  2. Github:https://github.com/Lves

欢迎关注微信公众账号:乐Coding 或者 lecoding,你也可以扫描下方二维码:

icon

苹果开放了CloudKit对服务器到服务器端的请求

苹果最近宣布可以连接苹果云平台的OS XiOSCloudKit框架,现在已经对服务器到服务器的网络请求进行了开放。它消除了以前只有iOS和MAC应用才能连接到CloudKit公共数据库的限制,使服务器直达苹果web站点。

CloudKit服务器到服务器的请求在原来已有特性的基础上新添加了允许开发者提供网络接口,使用户能访问自己的iCloud数据。服务器到服务器的请求根本目的是提供访问iCloud公共数据的权限,也为Parse关闭DBaaS在一定程度上提供了另外一种选择。

为了从服务器端程序或者脚本读取或写入数据到CloudKit数据库中,程序员首先需要使用OpenSLL生成钥匙串:

openssl ecparam -name prime256v1 -genkey -noout -out eckey.pem

然后,开发者应该到CloudKit故事版拿着公钥换取访问服务器的私钥。一旦输入公钥,作为网络服务请求子路径的KeyID就会立刻生成。苹果提供了一些开发者如何使用新的方式认证CloudKitJavaScript简单代码,如下:

[Current date]:[Request body]:[Web Service URL]

苹果还提供了使用curl来请求的简单代码,如下:

curl -X POST -H "content-type: text/plain" -H "X-Apple-CloudKit-Request-KeyID: [keyID]” -H "X-Apple-CloudKit-Request-ISO8601Date: [date]" -H "X-Apple-CloudKit-Request-SignatureV1: [signature]" -d '{"users":[{"emailAddress":"[user email]"}]}' https://api.apple-cloudkit.com/database/1/[container ID]/development/public/users/lookup/email

Stack Overflow上的一些用户也提供了JavaScript,PHP和Python语言的替代实现。

CloudKit给开发者提供了包括身份认证,私有和公共数据库,结构化的一些服务,例如基于plist,资产存储。

原文翻译自InfoQ

更多iOSAndroid精彩文章请关注微信公众账号:lecoding,你也可以扫描下方二维码关注我们。

qrcode_for_gh_af22362bf4bb_258.jpg

iOS二维码扫描和创建(下)

在上一篇文章《二维码扫描和创建(上)》中我们已经介绍了三种扫描二维码的方式和如何扫描相册中的二维码图片,想查看的可以关注我们的微信公众号:lecoding ,里边有更多 iOS开发精彩文章。今天我们谈谈我了解到关于创建二维码的几种方式。

我在iPhone APP 扫码神奇中使用的就是下面第二种方法,大家可以到APPStore搜索扫码神奇,下载体验一下(记得给个好评呦)。扫码神奇下载链接:
https://itunes.apple.com/cn/app/id1074173840

icon108.png

libqrencode

源文件我已经上传到百度网盘 下载链接:http://pan.baidu.com/s/1qXrFOq4github链接:https://github.com/fukuchi/libqrencode ,

  • 下载解压后,把文件夹拖入项目中
  • 文件中加入以下框架:AVFoundation.framework、CoreMedia.framework、CoreVideo.framework、QuartzCore.framework、libiconv.dylib
  • 需要使用的页面.m文件中引用头文件#import "QRCodeGenerator.h"
    生成二维码只需要一行代码:
UIImage *image = [QRCodeGenerator qrImageForString:self.codeString imageSize:self.imageView_Code.bounds.size.width];  

使用libqrencode 生成二维码无法生成彩色二维码。下面可以看看原生的可以实现生成彩色二维码。

###原生

我在网上找到了一种不使用第三方库创建彩色二维码的方式,分享给大家:

//

//  LLQRGenerator.m

//  QRenManager

//

//  Created by LiXingLe on 16/1/12.

//  Copyright © 2016年 com.wildcat. All rights reserved.

//



#import "LLQRGenerator.h"





@implementation LLQRGenerator



+ (UIImage *) getQRImageWithContent:(NSString *)content red:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue{



    // 1.创建滤镜

    CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];



    // 2.还原滤镜默认属性

    [filter setDefaults];



    // 3.设置需要生成二维码的数据到滤镜中

    // OC中要求设置的是一个二进制数据

    NSData *data = [content dataUsingEncoding:NSUTF8StringEncoding];

    [filter setValue:data forKeyPath:@"InputMessage"];



    // 4.从滤镜从取出生成好的二维码图片

    CIImage *ciImage = [filter outputImage];



   return  [self createNonInterpolatedUIImageFormCIImage:ciImage size:500 withRed:red green:green blue:blue];



}









//生成高清二维码方法

+ (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)ciImage size:(CGFloat)widthAndHeight withRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue

{

    CGRect extentRect = CGRectIntegral(ciImage.extent);

    CGFloat scale = MIN(widthAndHeight / CGRectGetWidth(extentRect), widthAndHeight / CGRectGetHeight(extentRect));



    // 1.创建bitmap;

    size_t width = CGRectGetWidth(extentRect) * scale;

    size_t height = CGRectGetHeight(extentRect) * scale;

    CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();

    CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, (CGBitmapInfo)kCGImageAlphaNone);



    CIContext *context = [CIContext contextWithOptions:nil];



    CGImageRef bitmapImage = [context createCGImage:ciImage fromRect:extentRect];

    CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);

    CGContextScaleCTM(bitmapRef, scale, scale);

    CGContextDrawImage(bitmapRef, extentRect, bitmapImage);



    // 保存bitmap到图片

    CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);

    CGContextRelease(bitmapRef);

    CGImageRelease(bitmapImage);



    //return [UIImage imageWithCGImage:scaledImage]; // 黑白图片

    UIImage *newImage = [UIImage imageWithCGImage:scaledImage];

    return [self imageBlackToTransparent:newImage withRed:red andGreen:green andBlue:blue];

}



void ProviderReleaseData (void *info, const void *data, size_t size){

    free((void*)data);

}

//设置图片透明度

+ (UIImage*)imageBlackToTransparent:(UIImage*)image withRed:(CGFloat)red andGreen:(CGFloat)green andBlue:(CGFloat)blue{

    const int imageWidth = image.size.width;

    const int imageHeight = image.size.height;

    size_t      bytesPerRow = imageWidth * 4;

    uint32_t* rgbImageBuf = (uint32_t*)malloc(bytesPerRow * imageHeight);

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    CGContextRef context = CGBitmapContextCreate(rgbImageBuf, imageWidth, imageHeight, 8, bytesPerRow, colorSpace,

                                                 kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);

    CGContextDrawImage(context, CGRectMake(0, 0, imageWidth, imageHeight), image.CGImage);

    // 遍历像素

    int pixelNum = imageWidth * imageHeight;

    uint32_t* pCurPtr = rgbImageBuf;

    for (int i = 0; i < pixelNum; i++, pCurPtr++){

        if ((*pCurPtr & 0xFFFFFF00) < 0x99999900)

        {

            uint8_t* ptr = (uint8_t*)pCurPtr;

            ptr[3] = red; //0~255

            ptr[2] = green;

            ptr[1] = blue;

        }

        else

        {

            uint8_t* ptr = (uint8_t*)pCurPtr;

            ptr[0] = 0;

        }

    }

    // 输出图片

    CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, rgbImageBuf, bytesPerRow * imageHeight, ProviderReleaseData);

    CGImageRef imageRef = CGImageCreate(imageWidth, imageHeight, 8, 32, bytesPerRow, colorSpace,

                                        kCGImageAlphaLast | kCGBitmapByteOrder32Little, dataProvider,

                                        NULL, true, kCGRenderingIntentDefault);

    CGDataProviderRelease(dataProvider);

    UIImage* resultUIImage = [UIImage imageWithCGImage:imageRef];

    // 清理空间

    CGImageRelease(imageRef);

    CGContextRelease(context);

    CGColorSpaceRelease(colorSpace);

    return resultUIImage;

}



@end

扫描二维码和创建二维码项目展示:APPStore搜索扫码神奇(记得给个好评呦)。


转载请注明,版权归http://lvesli.com所有。

更多iOSAndroid精彩文章请关注微信公众账号:lecoding,你也可以扫描下方二维码关注我们。

icon

二维码扫描和创建(上)

saomashengqi.png

##扫描二维码(包括读取和解码)

扫描二维码OC的开源库有ZBar和ZXingiOS7以后iOS拥有原生的扫码功能。
我在iPhone项目扫码神奇中使用的就是下面第三种方法,大家可以到APPStore搜索扫码神奇,下载体验一下(记得给个好评呦)。扫码神奇下载链接:
https://itunes.apple.com/cn/app/id1074173840

icon108.png

好了下面是具体实现介绍:

ZXing

现在OC版本已经停止维护,Java版本还在维护,github链接:https://github.com/zxing/zxing,现在也很少有人使用,在唐巧的一篇12年http://blog.devtang.com/blog/2012/12/23/use-zxing-library/文章中有关于ZXing的配置过程,不过好像他好久没有更新了。ZXing相对于ZBar的好处是读取和扫码速度快,但是整合到Xcode项目中比较痛苦。

ZBar

ZBargithub地址:https://github.com/bmorton/ZBarSDK ,在github上下载的.a文件不支持64位,好像也有好今年没有更新了,不过我在网上找到了支持64位的.a文件,下载链接:https://markobl.com/2015/03/27/zbar-sdk-64-bit-for-iphone-6-and-ios-8-download/ ,下面说一下ZBar的集成步骤:

  • github上下载源文件,解压后如下图,把Headers文件夹拖入到项目中。
  • 64位.a文件下载支持64位的.a文件,添加到项目中
  • 在新工程中导入以下框架:AVFoundation.framework、CoreMedia.framework、CoreVideo.framework、QuartzCore.framework、libiconv.dylib
  • 在需要使用的页面.h文件中引用头文件#import "ZBarSDK.h"

.m文件中在点击开始扫描的按钮中实现:

ZBarReaderViewController *reader = [ZBarReaderViewController new];  
  reader.readerDelegate = self;  
reader.supportedOrientationsMask = ZBarOrientationMaskAll;  

  ZBarImageScanner *scanner = reader.scanner;  
  [scanner setSymbology: ZBAR_I25  
                 config: ZBAR_CFG_ENABLE  
                     to: 0];  
  [self presentViewController:reader  
                     animated:YES  
                   completion:^{  
  }];

还要实现代理

- (void) imagePickerController: (UIImagePickerController*) reader didFinishPickingMediaWithInfo: (NSDictionary*) info{
      id<NSFastEnumeration> results = [info objectForKey: ZBarReaderControllerResults];  
      ZBarSymbol *symbol = nil;  
      for(symbol in results)  
          break;      
      [self dismissViewControllerAnimated:YES  
                           completion:^{  
                           }];  
    NSString *code = [NSString stringWithString:symbol.data];  

}

ZBar有一个弊端,因为他是静态文件,所以自定义相机比较困难,只能进行简单的修改,我尝试实现微信扫码效果没有实现。

###iOS原生扫码

iOS7以后APPle有了自己原生的扫码接口,我当然要义无反顾地选择使用原生的了,下面是我在项目中的部分代码:
在.m文件中:

#import <AVFoundation/AVFoundation.h>
@interface SysScannerController ()<AVCaptureMetadataOutputObjectsDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate>
@property (nonatomic, strong) AVCaptureSession *session;//输入输出的中间桥梁
@property (strong,nonatomic)AVCaptureDevice *device;
@property (strong,nonatomic)AVCaptureDeviceInput *input;
@property (strong,nonatomic)AVCaptureMetadataOutput *output;
@property (strong,nonatomic)AVCaptureVideoPreviewLayer *preview;
@end

懒加载:

#pragma mark - Setter & Getter
-(UIView *)line{
    if (_line == nil) {
        _line = [[UIView alloc] initWithFrame:CGRectMake((ScreenFrameWith-180)/2, ScreenFrameHeight/3.f, 180, 4)];
        _line.backgroundColor=[UIColor whiteColor];
        [self.view addSubview:_line];
    }
    return _line;
}

-(AVCaptureDevice *)device{
    if (_device == nil) {
        _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    }
    return _device;
}
-(AVCaptureDeviceInput *)input{
    if (_input == nil) {
        _input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
    }
    return _input;
}
-(AVCaptureMetadataOutput *)output{
    if (_output == nil) {
        _output = [[AVCaptureMetadataOutput alloc]init];
        [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
        //限制扫描区域(上左下右)
        [ _output setRectOfInterest : CGRectMake (1/6.f,1/6.f,4/6.f,4/6.f)];
    }
    return _output;
}

- (AVCaptureSession *)session{
    if (_session == nil) {
        // Session
        _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];
        }
    }
    return _session;
}

-(AVCaptureVideoPreviewLayer *)preview{
    if (_preview == nil) {
        _preview =[AVCaptureVideoPreviewLayer layerWithSession:self.session];

    }
    return _preview;
}

-viewDidLoad中调用下面函数:

- (void)setupCamera
{
    //1.
    if(self.device == nil){
        [self showAlertTipWithTitle:@"未检测到相机" andMessage:@"请检查相机设备是否正常"];
        return ;
    }
    // 2.添加预览图层
    [self.view.layer insertSublayer:self.preview atIndex:0];
    self.preview.frame = self.view.bounds;
    // 3.设置输出能够解析的数据类型
    // 注意点: 设置数据类型一定要在输出对象添加到会话之后才能设置
    self.output.metadataObjectTypes = self.output.availableMetadataObjectTypes;
    // 4.设置监听监听输出解析到的数据
    [self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    // 5.开始扫描
    [self.session startRunning];

}

实现AVCaptureMetadataOutputObjectsDelegate 代理:

#pragma mark AVCaptureMetadataOutputObjectsDelegate

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{

    if ([metadataObjects count] >0)
    {
        AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex:0];

        if ([metadataObject isKindOfClass:[AVMetadataMachineReadableCodeObject class]]) {
            NSString *stringValue = [metadataObject stringValue];
            if (stringValue != nil) {
                [self.session stopRunning];
                //扫描结果
                self.scannedResult=stringValue;
            }

        }
    }
}

iOS原生的扫码界面你可以随意的自定义了,和自定义相机一样,这里就不做介绍了。

###扫描相册中的二维码

扫描相册中的二维码,首先打开相册然后先在UIImagePickerControllerDelegate代理方法中:

 #pragma mark - imagePickerController delegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    //1.获取选择的图片
    UIImage *image = info[UIImagePickerControllerOriginalImage];
    //2.初始化一个监测器
    CIDetector*detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{ CIDetectorAccuracy : CIDetectorAccuracyHigh }];

    [picker dismissViewControllerAnimated:YES completion:^{
        //监测到的结果数组
        NSArray *features = [detector featuresInImage:[CIImage imageWithCGImage:image.CGImage]];
        if (features.count >=1) {
            /**结果对象 */
            CIQRCodeFeature *feature = [features objectAtIndex:0];
            NSString *scannedResult = feature.messageString;
            self.scannedResult=scannedResult;
            [self performSegueWithIdentifier:@"ToResult" sender:self];
        }
        else{
            [self showAlertTipWithTitle:@"提示" andMessage:@"该图片没有包含一个二维码!"];
        }
    }];
}

好了,关于扫描二维码今天就说到这,下一篇我会分享创建二维码功能。扫描二维码和创建二维码项目展示:APPStore搜索扫码神奇(记得给个好评呦)。


更多精彩文章请关注微信公众账号:lecoding,你也可以扫描下方二维码关注我们。

icon

微信朋友圈红包照片绕过方法

微信朋友圈红包照片绕过方法:

微信朋友圈刚出的新功能只有发红包才能看到对方的照片,想必大家已经被刷屏了吧。其实这张照片只是在客户端加了一个毛玻璃效果,原始图片是没有的,只要抓包就可以看到不用给他红包哈哈哈,下面介绍一下iPhone如何查看对方的照片。
下载一个抓包工具,Mac电脑我使用的是Charles,打开Charles,MAC要和iPhone在同一个Wifi下,然后进入朋友圈点击你想看的图片,就会发送网络请求,在Charles中复制下面请求的URL,把链接粘贴到浏览器就可以看到了。哈哈你们的图片我都看到了……愚蠢的人类。

屏幕快照 2016-01-26 下午5.55.54.png

微信公众账号:lecoding同步更新,你也可以扫描下方二维码关注我们。

qrcode_for_gh_af22362bf4bb_258.jpg

扫码神奇-二维码、条形码扫描,二维码创建

xuanchuan1.png

###iOS版扫码神奇上线了,二维码条形码扫描和创建神器。二维码扫描,神奇啊!

APPStore下载链接:https://itunes.apple.com/cn/app/id1074173840 欢迎下载评论。

###一、应用介绍:

  • 支持二维码和条形码的扫描,可以从相册中选择二维码图片进行扫描;
  • 支持二维码创建包括:文字、URL、地址、电话;
  • 可以把扫描或者创建的二维码分享到微信、微博、QQ等平台;
  • 扫描历史记录自动保存;

###二、效果展示

640_1096a.jpg

640_1096b.jpg

640_1096c.jpg

最近闲来无事写个小应用扫码器,关于二维码扫描和创建的代码稍后会分享个给大家,你也可以关注微信公众号:lecoding 实时关注文章更新。你也可以扫描下方二维码关注我们:

wechat

iOS 实现ScrollView 上滑隐藏Navigationbar,下滑显示

我司产品🐶突然喜欢上了知乎简书的的那种上滑加载更多时隐藏NavigationBar,下拉时显示的那种效果。那些阅读类APP需要沉浸式体验隐藏导航栏无可厚非,我就纳闷一个P2P类软件你隐藏个毛线!废话少说,技术很好实现几行代码的事。

在包含TableView或者ScrollView的.m文件中加入以下代码:

在页面即将消失时显示NavigationBar,让下一个页面显示时NavigationBar显示状态:

//滑动隐藏导航栏 LiXingLe
-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];

    self.navigationController.navigationBarHidden = NO;

}

实现ScrollView的代理:

#pragma mark 滑动隐藏导航栏
//滑动隐藏导航栏 LiXingLe

-(void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{

    if(velocity.y>0)

    {

        [self.navigationController setNavigationBarHidden:YES animated:YES];

    }

    else

    {

        [self.navigationController setNavigationBarHidden:NO animated:YES];

    }

}

现在运行一下如果上滑的时候顶部没有变黑就OK了,如果NavigationBar 隐藏后顶部变黑,加上下面的代码,
viewDidLoad中添加:

//滑动隐藏导航栏 LiXingLe

if ([self respondsToSelector:@selector(edgesForExtendedLayout)])

      self.edgesForExtendedLayout = UIRectEdgeNone;

更多iOS、Swift开发精彩内容请移步http://lvesli.com或者关注我们的微信公众账号

微信公众账号:lecoding同步更新,你也可以扫描下方二维码关注我们。

icon

Swift基础之闭包

##闭包

Swift对闭包进行了简化:

  • 利用上下文推断参数和返回值类型
  • 隐式返回单表达式闭包,即单表达式闭包可以省略return关键字
  • 参数名称缩写
  • 尾随(Trailing)闭包语法

先来看一个排序的例子,数组的降序排列

1
2
3
4
5
6
7
8
9
var usernames = ["Lves", "Wildcat", "Cc", "Lecoding"]
func backWards(s1: String, s2: String) -> Bool
{
return s1 > s2
}

var resultName1 = usernames.sort(backWards)

//resultName1: ["Wildcat", "Lves", "Lecoding", "Cc"]

###1. 闭包表达式语法

swift中闭包的一版形式如下:

1
2
3
{ (parameters) -> returnType in
statements
}

下面我们用内联闭包实现数组的升序排列,

函数的最后一个参数是闭包时 () 可以省略;

注意:此时闭包的参数和返回值类型要和函数声明相同,(Self.Generator.Element, Self.Generator.Element) -> Bool

1
2
3
4
var resultName2 = usernames.sort { (s1: String, s2: String) -> Bool in
return s1 < s2
}
//resultName2 : ["Cc", "Lecoding", "Lves", "Wildcat"]

###1.2 根据上下文推断类型(Inferring Type From Context)

上面的内联闭包书写还可以更加精简,因为sort(_:)函数需要的函数参数类型已知即:(String, String) -> Bool

因为所有的类型都可以被正确推断,返回箭头(->)和围绕在参数周围的括号也可以被省略:

1
2
3
4
5
var resultName3 = usernames.sort { s1, s2 in
return s1 > s2
}

//["Wildcat", "Lves", "Lecoding", "Cc"]

###1.3 单表达式闭包隐式返回

单行表达式闭包可以通过省略return关键字来隐式返回单行表达式的结果

var resultName4 = usernames.sort { s1, s2 in s1 > s2 }

###1.4 参数名称缩写

如果你觉得还不够精简,当然还有更加精简的:

内联闭包可以省略参数名直接用参数顺序$0,$1,$2调用.

1
var resultName5 = usernames.sort ({ $0 > $1 })

###1.5 运算符函数(Operator Functions)

对于上边的排序函数,你觉得内联闭包书写是最精简了,那你就错了。

SwiftString类型定义了关于大于号(>)的字符串实现,其作为一个函数接受两个String类型的参数并返回Bool类型的值。而这正好与sort(_:)方法的第二个参数需要的函数类型相符合。

1
var resultName6 = usernames.sort(>)

###2. 尾随闭包(Trailing Closures))

尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用:

下面先定义一个计算函数,参数为:两个整数和一个函数类型参数

1
2
3
4
5
6
7
8
9
10
11
12
func caculateTwoNumbers(num1: Int, num2: Int, CaluFunction: (Int, Int) -> Int) -> Int{
return CaluFunction(num1, num2)
}

//内联闭包形式,不使用尾随闭包,求和
var numReult1 = caculateTwoNumbers(2, num2: 3,CaluFunction: {(num1: Int, num2: Int) -> Int in
return num1 + num2
})
//5
//使用尾随闭包,求乘机
var numReult2 = caculateTwoNumbers(3, num2: 4) { $0 * $1 }
numReult2 //7

###3. 捕获值(Capturing Values)

闭包可以在其被定义的上下文中捕获常量或变量。即使定义这些常量和变量的原作用域已经不存在,闭包仍然可以在闭包函数体内引用和修改这些值。

###4.闭包是引用类型(Closures Are Reference Types)

和类一样,必要也是引用类型

###5. 非逃逸闭包(Nonescaping Closures)

一个闭包作为参数传到一个函数中,但是这个闭包在函数返回之后才被执行,我们称该闭包从函数中逃逸。可以在参数名之前标注@noescape,用来指明这个闭包是不允许“逃逸”出这个函数的。将闭包标注@noescape能使编译器知道这个闭包的生命周期.

像刚才的数组的sort(_:)函数中的参数就定义成了非逃逸闭包,

public func sort(@noescape isOrderedBefore: (Self.Generator.Element, Self.Generator.Element) -> Bool) -> [Self.Generator.Element]

你可能会问什么时候会出现逃逸闭包呢?举个例子:很多启动异步操作的函数接受一个闭包参数作为 completion handler。这类函数会在异步操作开始之后立刻返回,但是闭包直到异步操作结束后才会被调用。在这种情况下,闭包需要“逃逸”出函数,因为闭包需要在函数返回之后被调用。

非逃逸闭包和逃逸闭包讲的不是执行先后顺序吧,非逃逸是指你的闭包不能在函数外单独调用,只能在函数内部调用,函数调用完成后,那个闭包也就结束了。

下面举个逃逸闭包的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//声明一个存放函数的数组
var functionArray: [() -> Void] = []
//定义一个接收闭包参数的函数,如果定义非逃逸函数 func doSomething(@noescape paramClosure:() -> Void) 就会编译错误
func doSomething(paramClosure:() -> Void){
//把参数放入数组中,用于逃逸调用
functionArray.append(paramClosure)

}
//调用函数

doSomething({print("Hello world")})

doSomething({print("Hello LvesLi")})

//逃逸调用闭包
for closurePrama in functionArray {

print("\(closurePrama)")

}

更多iOS、Swift开发精彩文章请访问http://lvesli.com

微信公众账号:lecoding同步更新,你也可以扫描下方二维码关注我们。

icon