【转发】一步一步搭建自个儿的iOS互联网请求库

进展简短的卷入

我们接下去将在出席动态的动态的HTTP参数(parameters)的功效,之后封装出大家团结的接口。

先是呢,我们先来对上二次的代码举行二次轻巧的包裹,建立三个新的类LyNetWork,承袭于NSObject类
。新建三个静态的request方法。将请求情势和U逍客L传入

代码如下:

+(void)request :(NSString *)method URL:(NSString *)URL{
    NSURL *url = [NSURL URLWithString:URL];
    NSURLSession *session = [NSURLSession sharedSession];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = method;
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * data,NSURLResponse *reponse,NSError *error){

        //NSdata转String
        NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"%@",string);
    }];
    [task resume];

}

OK

让大家在ViewController中打开一下测试,代码如下:

@IBAction func mainButtonBeTapped(sender: AnyObject) {
    [LyNetWork request:@"GET" URL:@"http://cityuit.sinaapp.com/1.php"];
}

接下去运转一下:OK 依然突显我们科学的测试结果:succeed

看了1篇国外的篇章,关于iOS9的Core Data教学,在此处做了弹指间总计

接下去举办我们最难处理的地点,增加parameters处理技能

开始

开拓你的Xcode新建2个中兴工程,选择Single View Application
template起名叫HitList并且采取Use Core Data。

起名 1

选中Use Core Data复选框后将会在AppDelegate.swift生成Core Data
stack样本代码

Core Data stack由一组对象组成,方便于检索和封存Core
Data的数量。有二个对象极其2个总体来治本Care Data的情形和数据模型等等。

那一个示例程序的想法很粗大略。有二个被叫”hit
list”的表视图。你能够在那么些列表中加多名字,并且最终你将选择Core
Data确定保证数量在各样环节之间。

点击Main.storyboard在Interface Builder.接下来点击艾德itor,采用Navigation
Controller。具体操作如图所示: 起名 2

回去Interface Builder,拖拽1个Table view。

接下去拖拽贰个Bar Button Item将它放置到navigation
bar。最后,起名称叫Add。就像这么

起名 3

当你每一次点击Add的时候,2个涵盖文本音讯字段的弹框将会面世在显示屏上展现。在那边您可见输入暗许的名字到进入文本域。

1旦您想掌握原委,你能够不安装表示图的信托,那样就不会触发任何表现。

开采Assistant 艾德itor拖拽table view到
ViewController.swift,在类中插入二个outlet:

起名 4

起名为 tableview

@IBOutlet weak var tableView: UITableView!

一致将Add拖拽到ViewController.swift,创建1个action 命名叫addName:

@IBAction func addName(sender: AnyObject) {

}

那正是说以后你可援引表示图和开关了。接下来正是树立代表图模型。在ViewContrroller.swift中增多一下代码:

//Insert below the tableView IBOutlet
var names = [String]()

names是二个可变的shtring类型的数组,在tableview中显示。

在viewDidLoad()中落到实处一下代码:

override func viewDidLoad() {
  super.viewDidLoad()
  title = "\"The List\""
  tableView.registerClass(UITableViewCell.self,
    forCellReuseIdentifier: "Cell")
}

在那边将确立1个标题,注册UITableViewCell在table view类中。table
view将赶回正确类型的cell

仍然在ViewController.swift,添加UITableViewDataSource,UITableViewDelegate

//Add UITableViewDataSource to class declaration
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate{
  //这里添加
    tableView.dataSource = self
    tableView.delegate = self


}

其一时半刻候Xcode会提示ViewCotroller不符合协议.达成data
source方法修改这么些荒唐。

// MARK: UITableViewDataSource
func tableView(tableView: UITableView,
  numberOfRowsInSection section: Int) -> Int {
  return names.count
}

func tableView(tableView: UITableView,
  cellForRowAtIndexPath
  indexPath: NSIndexPath) -> UITableViewCell {

  let cell =
  tableView.dequeueReusableCellWithIdentifier("Cell")

  cell!.textLabel!.text = names[indexPath.row]

  return cell!
}

比方你用过UITableView,那段代码看起来会很相似。第二个点子正是names数量。

其次个措施tableView(_:cellForRowAtIndexPath:)返回对cell对象。

不要现在就运转。首先你供给多个输入names的法门然后在table
view中开始展览体现他们。

实现addName IBAction

//Implement the addName IBAction
@IBAction func addName(sender: AnyObject) {

  let alert = UIAlertController(title: "New Name",
    message: "Add a new name",
    preferredStyle: .Alert)

  let saveAction = UIAlertAction(title: "Save",
    style: .Default,
    handler: { (action:UIAlertAction) -> Void in

      let textField = alert.textFields!.first
      self.names.append(textField!.text!)
      self.viewWillAppear(true)
      self.tableView.reloadData()
  })

  let cancelAction = UIAlertAction(title: "Cancel",
    style: .Default) { (action: UIAlertAction) -> Void in
  }

  alert.addTextFieldWithConfigurationHandler {
    (textField: UITextField) -> Void in
  }

  alert.addAction(saveAction)
  alert.addAction(cancelAction)

  presentViewController(alert,
    animated: true,
    completion: nil)
}

老是点击Add开关的时候,那个艺术该方法弹出文本域和多个开关,保存和撤回。

点击保存,将其名目插入到数组中,table view将重新加载数据并出示。

在那边,塑造并且第三次运转大家的应用程序。点击顶部的Add按键,将会插入三个弹框。

起名 5

加多多少个或许陆个左右的数据,正是上边的典范

起名 6

你的table
view将展现数据,可是并不能够兑现持久化,什么意思吧?正是说大家未来的数组数据是存放在在内部存款和储蓄器中的,但是只要大家假如强制退出应用程序或然重新起动你的设备,你的数组数据就会被灭绝。

Core
Data提供持久化,意思便是她可让数据保持为持久状态,尽管采纳重新启航也许是重新运行。

您现在还一直不增进别的Core
Data。让咱们来测试下,切换成Simulator,点击Shift+⌘+H,将会回来home分界面。

起名 7

见到HitListLogo,点击它切换来利用,那几个名字同样存在着。那跟大家刚刚描述的不均等,为何呢?

当你点击Home按键的时候。那年操作系统会瞬间冻结全数当前在内部存款和储蓄器中的1切音讯。包涵我们的名号数组字符串。同样,当我们的选取切换回去的时候,操作系统会苏醒过去的记得,就如您根本不曾偏离过一样,意思正是大家的names被还原了。

多职分形式早在iOS
肆中出产。他们创设了iOS用户无缝体验,同时也增多了持续性的概念,那心真的存在吗?

不,那不是真的。如果您一点一滴杀死应用程序大概关闭你的One plus,你的names数组就会收敛。你能够体会下,快捷的双击Home。

起名 8

在那里,向上拉动你的应程序,在那边就会将先后杀死了。今年反回Home,再一回点击你的应用程序,names就会未有。

上述展现的三种办法书有反差的,所以这里看来精晓熟悉多职务情势是明摆着的。不过那些在用户的头脑中是未有怎么差别的。用户不会在乎通过哪一类办法切回到Home,可能切回到应用。

前几天的标题正是哪些让动用无论通过哪类方法赶回都可以存在。

于今就到了大家要讲诉的事物了,完成真正的持久性,数据在1个施用中无论如何都会存在着。

一步一步搭建自身的iOS网络请求库(3)

大家好,笔者是LastDay,上一回分享了简便的包装,和GET请求。本次带给大家POST方法

自身的博客地址:http://lastday.github.io

封存数据到Core Data

在ViewCortroller.swift中 Import Core Data

//Add below "import UIKit"
import CoreData

在Objective-C你恐怕不得不手动链接框架,可是在斯威夫特中,3个简便的Import语句就就足以让你在你的代码中应用API。

接下去,更动模型。

//将names变味people,并且将people类型改为NSManagedObject类型
var people = [NSManagedObject]()

接下去你存款和储蓄的是Person实体而不是names,所以将数据模型更名称叫people,并且它今后是NSManagedObject类型而不是简单的String类型。

NSManagedObject被叫做在Core
Data中的单1对象。你必须运用它成立,修改,保存和删除操作你的持久数据。

就在刚刚您早就改成了视图的模子,你必须也要动用上面包车型客车代码替换原来的数据源。

//Replace both UITableViewDataSource methods
func tableView(tableView: UITableView,
  numberOfRowsInSection section: Int) -> Int {
    return people.count
}

func tableView(tableView: UITableView,
  cellForRowAtIndexPath
  indexPath: NSIndexPath) -> UITableViewCell {

    let cell =
    tableView.dequeueReusableCellWithIdentifier("Cell")

    let person = people[indexPath.row]

    cell!.textLabel!.text =
      person.valueForKey("name") as? String

    return cell!
}

事实上通过相比来看其实最分明的更动在cellForRowAtIndexPath,仔细看看就可见察觉里面包车型地铁变迁。

自然,你必要小心的地点还有就是你是如何从NSManagedObject抓去name属性。

cell!.textLabel!.text = person.valueForKey("name") as? String

干什么用上述的主意呢?因为NSManagedObject并不知道在你的数据模型中name是哪些被定义在您的数据模型中的,由此并未艺术直接待上访问你的name属性。唯1的格局正是用过Core
Data提供的key-value来读取,那种艺术1般被称呼KVC。

自个儿在此地相同也简要的介绍一下KVC吧。正是说假使你是多少个新的iOS开辟者可能不打听怎么是KVC也许是key-vale编码。KVC正是Cocoa和Cocoa
Touch的编写制定来拜会一个目的的而属性直接的选取字符串来鉴定分别。在以上的动静下,KVC就像是1本字典。

接下去就是退换我们@IBAction addName方法:

let saveAction = UIAlertAction(title: "Save",
  style: .Default,
  handler: { (action:UIAlertAction) -> Void in

    let textField = alert.textFields!.first
    self.saveName(textField!.text!)
    self.tableView.reloadData()
})

旁观地点大家有新扩大加了二个saveName方法

func saveName(name: String) {
  //1
  let appDelegate =
  UIApplication.sharedApplication().delegate as! AppDelegate

  let managedContext = appDelegate.managedObjectContext

  //2
  let entity =  NSEntityDescription.entityForName("Person",
    inManagedObjectContext:managedContext)

  let person = NSManagedObject(entity: entity!,
    insertIntoManagedObjectContext: managedContext)

  //3
  person.setValue(name, forKey: "name")

  //4
  do {
    try managedContext.save()
  //5
    people.append(person)
  } catch let error as NSError  {
      print("Could not save \(error), \(error.userInfo)")
  }
}

那其间都以如何呢?大家来分析下

  • 在您做svae操作从前,你要求先获得NSManagedObjectContext。你能够感到那是用来managed
    object context的。想拓展封存对象到Core
    Data中需求两步,首先,你供给插入3个目的到managed object
    context中。然后提交,将该对象存款和储蓄到磁盘中。Xcode其实已经产生三个通用的沙盘,当你挑选Use
    Core Data的时候。这些暗许的managed object context存在于application
    delegate中。要想引用它,你要求获得2个app delegate引用。
  • 开创managed object
    context并且达成NSManagedObject的起首化,init(entity:insertIntoManagedObjectContext:).你也许会想到NSEntityDescription的具备有关东西
  • 运用NSManagedObject,必须采纳你建立的name,必须运用KVC,不然会产出崩溃现象。
  • 您的交给的person被保留在磁盘中,注意save会抛出10分,那正是怎么大家供给动用try
    do。
  • 接下去就要恭喜你已经成功还要安全的的兑现了数量的持久化。依然是当大家插入后将会再也加载视图

那比使用二个字符串或者复杂的大多,然而并不是很复杂。那里的代码正是收获managed
object context和entity,

营造并且运营,增多一些近乎上面包车型地铁名字。

起名 9

若是您的多寡现已在Core
Data中储存,并且实现了数据的持久化,那年我们杀死大家的app,然后重现加载大家先后,等一下,爆发了何等?table
view是空的

起名 10

您继续到Core
Data中的数据只是再一次加载后并不曾,依旧是空的,其实数据实际上在这里的等候着,你并未出示它、

从Core Data中获取

要收获持久化的数量,你无法不收取它。在ViewController.swift中天增多三个主意

override func viewWillAppear(animated: Bool) {
  super.viewWillAppear(animated)

  //1
  let appDelegate =
  UIApplication.sharedApplication().delegate as! AppDelegate

  let managedContext = appDelegate.managedObjectContext

  //2
  let fetchRequest = NSFetchRequest(entityName: "Person")

  //3
  do {
    let results =
      try managedContext.executeFetchRequest(fetchRequest)
    people = results as! [NSManagedObject]
  } catch let error as NSError {
    print("Could not fetch \(error), \(error.userInfo)")
  }
}

如上代码中做了如何?

  • 仿佛刚刚说的,在做壹些操作前你需求获得二个managed object
    context。从delegate中引用managed object context.
  • 基于名字就能看出来,NSFetchRequest便是回到的多少。
  • executefetchrequest()再次来到满足managed
    objects读取请求中钦点的正式数组。

构建并且重新运转,就能窥见你想要的机能了

起名 11

目前您就可以轻便的测试了。

轻松的介绍

介绍一下,NSUXC60LSession是iOS七中新的网络接口,它与NSUCR-VLConnection是不分厚薄的。在先后在前台时,NSUTiggoLSession与NSUWranglerLConnection可以互为代表工作。两者在前台的时候实在没有怎么差异,最重点的是先后在进入后台的时候,Background
Session会愈发灵活

多少建立模型

前几日您精通怎么着检查实验持久性了,让我们开始Core
Data的求学。你的对象很轻易,便是持久化你输入的名字,重新起动后依然存在那么些应用程序中。

那那里,你早已领会了何等在内部存款和储蓄器中蕴藏names名称。在此间你将采用Core
Data代替那种形式。

率先步正是创制一个managed object model,正是意味着通过Core
Data数据将要磁盘上。暗中认可意况下,Core
Data使用SQlite数据库作为持久化的仓库储存,所以您能够想像数据模型看成数据库架构。

当你创立了工程的时候大家选用了Use Core
Data,Xcode会自动创制3个数据模型文件叫做HitList.xcdatamodeld

起名 12

点击HitList.xcdatamodeld打开它,正如你所见到的,Xcode有和好的数据模型编辑器,就像是如图所示那样

起名 13

这一个数据模型有广大效应,让我们创设2个简便的数目实体。

在左下方点击 Add
Entity创立2个新的实体,双击大家新创立的实业,并且改名称叫Person,就像是这么:

起名 14

你可能很想精晓干什么数据模型编辑器使用”实体”,而不是归纳的定义2个新类。你赶紧就会看到,Core
Data的数量出自自己的词汇表。以下有一对大规模的书语你大概会遇上:

  • 在Core
    Data中叁个entity是一个类的定义。举一个独立的例子就是职员和工人和供销合作社的例子。在关系型数据库中,一个实体对应1个表。
  • 三个attribute是连接受特定实体音讯的一有的。例如,2个职员和工人能够具有姓名,职位,薪金等attribute。在数据库中attribute(属性)对应表中一定的字段。
  • relationship是多少个实体之间的一个接连。

今昔您知道了怎么样是attribute,重返模型编辑并且增进一个attribute到Person中,选取Person,点击+。

制造一个name并且选取种类为String。

起名 15

在Core Data包涵很两种数据类型,String是里面的一种。

行使Block处理请求重回值

简单来说的介绍下闭包(block),对于OC而言是1个新词,但不是新的定义,不是新的事物。学过Javascript的同伙对闭包应该不生分吧~学过PHP的应该也不不熟悉,在PHP伍.3版本之后也支撑闭包,
也正是OC中所提到的Block。

最近对大家的request函数实行改动,LyNetWork.m代码如下:

起名 16

+(void)requestMethod:(NSString *)method
                 URL:(NSString *)URL
             success:(void (^)(NSData *__nullable data,NSURLResponse * __nullable response))success
             failure:(void (^)(NSError *__nullable error))failure
{
    NSURL *url = [NSURL URLWithString:URL];
    NSURLSession *session = [NSURLSession sharedSession];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = method;
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * data,NSURLResponse *response,NSError *error){
        if (error) {
            failure(error);
        }else{
            if (success) {
                success(data,response);
            }
        }

    }];

    [task resume];
}

接下去修改ViewController中的函数调用,代码修改后如下:

起名 17

- (IBAction)test:(id)sender {
    [LyNetWork requestMethod:@"GET"
                         URL:@"http://cityuit.sinaapp.com/1.php"
                     success:^(NSData *data,NSURLResponse *response){
                         NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                         NSLog(@"%@",string);
                     }
                     failure:^(NSError *error){
                         NSLog(@"%@",error);
                     }];
}

起名 18

测试结果依然重回succeed,测试结果正确

Core Data 教学

示范开源地址:LastDayCoreData

在这篇小说中大家将学习Core Data的多级教程,你将使用斯维夫特二.0写你的Core
Data。你将发未来Xcode中它是很轻便上手的,从运行代码导师数据模型编辑器。在学科停止后,你会精晓到:

  • 行使Xcode的model editor将你想囤积在Core Data。
  • 增加新的记录到 Core Data
  • 从Core Data中读取壹组数据
  • 在表视图中突显所获取的结果

您也将会询问Core
Data背后的多寡是什么样,以及哪些进行相互。OK,未来让大家来营造笔者的app吧。

运用适配器方式封装LyHttp

简短的来介绍一下适配器的定义:

适配器格局,能够如此说,用于连接二种分歧类型的对象,使其不用难题地协同职业。观念实际十一分的简便。适配器达成客户端须求的某种接口的一言一动。同时它又接2连三到另一个存有不相同行为的靶子。一边是客户端通晓如何选择的目的接口,另一面还客户端一窍不通的适配者,适配器站在两者中间。适配器主要的效率是把适配者的一言一行传递给管道另一端的客户端,其实那种所谓的极高大赏的适配器模型很两人实在早已应用过了

接下去正是来修改大家的LyNetWork

开始搞

新建3个LYHTTPRequestOperationManager类,然后伊始化一些参数

#import "LYHTTPRequestOperationManager.h"
#import "LYURLRequestSerialization.h"

@interface LYHTTPRequestOperationManager()

@property(nonatomic,strong) NSString *URL;
@property(nonatomic,strong) NSString *method;
@property(nonatomic,strong) NSDictionary *parameters;
@property(nonatomic,strong) NSMutableURLRequest *request;
@property(nonatomic,strong) NSURLSession *session;
@property(nonatomic,strong) NSURLSessionDataTask *task;

@end

@implementation LYHTTPRequestOperationManager


- (instancetype)initWithMethod:(NSString *)method URL:(NSString *)URL parameters:(id)parameters
{
    self = [super init];
    if (!self) {
        return nil;
    }
    self.URL = URL;
    self.method = method;
    self.parameters = parameters;
    self.request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:URL]];
    self.session = [NSURLSession sharedSession];
    return self;
}

@end

探望大家刚刚分析事物:

1.构造 NSURLRequest

1.确定 URL

2.确定 HTTP 方法(GET、POST 等)

3.添加特定的 HTTP 头

4.填充 HTTP Body

旧事地点的解析,我们创设3个setRequest函数:

-(void)setRequest{
    if ([self.method isEqual:@"GET"]&&self.parameters.count>0) {

        self.request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[[self.URL stringByAppendingString:@"?"] stringByAppendingString: [LYURLRequestSerialization LYQueryStringFromParameters:self.parameters]]]];
    }
    self.request.HTTPMethod = self.method;

    if (self.parameters.count>0) {
        [self.request addValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    }
}

setRequest达成了大家早已分析的前四个步骤

接下去创立setBody函数:

-(void)setBody{
    if (self.parameters.count>0&&![self.method isEqual:@"GET"]) {

        self.request.HTTPBody = [[LYURLRequestSerialization LYQueryStringFromParameters:self.parameters] dataUsingEncoding:NSUTF8StringEncoding];
    }
}

setBody正是成功了笔者们最后1个步骤

一步一步搭建自身的iOS互联网请求库(1)

世家好,笔者是LastDay,很久未有写博客了,上周会分享叁个的HTTP请求库的编辑撰写经验。

我们该进行驱动 [SESSION DATATASKWITHREQUEST] 方法,开首请求

-(void)driveTask:(void(^)(NSData *__nullable data,NSURLResponse * __nullable response))success
         failure:(void (^)(NSError *__nullable error))failure
{
    [self setRequest];
    [self setBody];
    [self setTaskWithSuccess:success failure:failure];
}

上述处理实现了协会 NSU景逸SUVLREQUEST

一步一步搭建本身的iOS网络请求库(贰)

大家好,小编是LastDay,上一回分享了大概体验并且测试下一下NSU福睿斯LSession。

本人的博客地址:http://lastday.github.io

咱俩先来处理GET方法呢

GET 方法下,params 在通过 url encode 之后一贯附在 U凯雷德L 末尾发送给服务器

好像于那些样子 GET
/foo.php?first_name=John&last_name=Doe&action=Submit HTTP/1.1

修改大家的requestMethod方法,将其进展一下退换,引进parameters参数

起名 19

+(void)requestMethod:(nullable NSString *)method
                 URL:(nullable NSString *)URL
            parameters:(nullable id) parameters
             success:(nullable void (^)(NSData *__nullable data,NSURLResponse * __nullable response))success
             failure:(nullable void (^)(NSError *__nullable error))failure;

分析NSURLSESSION

1.构造 NSURLRequest

1.确定 URL

2.确定 HTTP 方法(GET、POST 等)

3.添加特定的 HTTP 头

4.填充 HTTP Body

2.驱动 [session dataTaskWithRequest] 方法,开端请求

一步一步搭建本身的iOS网络请求库(四)–解耦处理

LastDays HTTP Library

04 Dec 2015 in Lyhttplibrary  2.335 minutes read

测试完了

接下去大家来探望大家的NSU福睿斯LSession是还是不是为异步?OK,大家来总结的改造一下大家的次第吗。讲五个闭塞,来探视大家的主线程变化。

- (IBAction)test:(id)sender {
  NSURL *url = [NSURL URLWithString:@"http://cityuit.sinaapp.com/1.php"];
  NSURLSession *session = [NSURLSession sharedSession];
  NSURLRequest *request = [NSURLRequest requestWithURL:url];
  NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * data,NSURLResponse *reponse,NSError *error){
    //阻塞3秒
    [NSThread sleepForTimeInterval:3];
    NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"%@",string);
  }];
  [task resume];
}

能够望见作用便是接二连三点击三遍,每隔三秒进行一回输出,直到一遍施行到位,那就证实大家的主线程未有被封堵,验证表明NSU大切诺基LSession为异步。

曾将看过1篇作品中,介绍过,那篇文章里介绍NSU奥德赛LSession 接纳的是
“异步阻塞” 模型,即具备请求在发出后都跻身 2# 线程实施,在 2#
线程内部根据阻塞队列方式施行。初叶推断,此阻塞脾性为 [NSURLSession
sharedSession] 单例形式的结果。

 

POST方法

POST
下很许多商谈可提供大家挑选,因为大家未有写文件的上传,所以大家就应用
application/x-www-form-urlencoded
那种归纳的秘技发送请求吧。requestMethod 中举办部分更换,增添POST方法。

代码如下:

+(void)requestMethod:(NSString *)method
                 URL:(NSString *)URL
          parameters:(id) parameters
             success:(void (^)(NSData *__nullable data,NSURLResponse * __nullable response))success
             failure:(void (^)(NSError *__nullable error))failure
{
    NSString *newURL;
    if ([method isEqual:@"GET"]) {
        newURL = [[URL stringByAppendingString:@"?"] stringByAppendingString: [LYURLRequestSerialization LYQueryStringFromParameters:parameters]];
        NSLog(@"%@",newURL);
    }else{
        newURL = URL;
    }

    NSURL *url = [NSURL URLWithString:newURL];
    NSURLSession *session = [NSURLSession sharedSession];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = method;

    if([method isEqual:@"POST"]){
        [request addValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
        request.HTTPBody =[[LYURLRequestSerialization LYQueryStringFromParameters:parameters] dataUsingEncoding:NSUTF8StringEncoding];
    }
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * data,NSURLResponse *response,NSError *error){
        if (error) {
            failure(error);
        }else{
            if (success) {
                success(data,response);
            }
        }
    }];
    [task resume];
}

接下去我们开始展览测试,原来的不行接口不扶助POST请求,为了测试本人就新写了三个假说,有八个参数为username和password,唯有当八个参数都为一的时候回来ok,别的再次回到no

大家提交POST请求测试代码:

- (IBAction)test:(id)sender {

    NSString *URL = @"http://cityuit.sinaapp.com/p.php";
    id parmenters = @{
                      @"username":@"1",
                      @"password":@"1"
                      };


    [LyNetWork requestMethod:@"POST"
                         URL:URL
                  parameters:parmenters
                     success:^(NSData *data,NSURLResponse *response){
                         NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                         NSLog(@"%@",string);
                     }
                     failure:^(NSError *error){
                         NSLog(@"%@",error);
                     }];
}

翻开结果为:

起名 20

若parmenters为1,222

id parmenters = @{
                      @"username":@"1",
                      @"password":@"222"
                      };

结果为:

起名 21

 

对LyHttp进行降耦处理

世家好,作者是LastDays,本次分享解耦处理,升高代码的可扩展性,和重用性。

本人的博客地址:http://lastday.github.io

LyHttp项目地址

原先的那么些代码就算,看起来比较轻易掌握,但是最大的问题要么功能太单纯,代码太混乱了。接下来我们将是用适配器模型来促成独立于底层结构的网络API,构造我们本身确实的”库”

封装多级API

不带parameters:

+(void)requestWithMethod:(NSString *)method
                 URL:(NSString *)URL
             success:(void (^)(NSData *__nullable data,NSURLResponse * __nullable response))success
             failure:(void (^)(NSError *__nullable error))failure
{

    LYHTTPRequestOperationManager *manange = [[LYHTTPRequestOperationManager alloc] initWithMethod:method URL:URL parameters:nil];
    [manange driveTask:success failure:failure];
}

不带parameters的GET方法:

+(void)requestGetWithURL:(NSString *)URL
             success:(void (^)(NSData *__nullable data,NSURLResponse * __nullable response))success
             failure:(void (^)(NSError *__nullable error))failure
{

    LYHTTPRequestOperationManager *manange = [[LYHTTPRequestOperationManager alloc] initWithMethod:@"GET" URL:URL parameters:nil];
    [manange driveTask:success failure:failure];
}

带parameters的GET方法:

//GET带parameters
+(void)requestGetWithURL:(NSString *)URL
          parameters:(id) parameters
             success:(void (^)(NSData *__nullable data,NSURLResponse * __nullable response))success
             failure:(void (^)(NSError *__nullable error))failure
{

    LYHTTPRequestOperationManager *manange = [[LYHTTPRequestOperationManager alloc] initWithMethod:@"GET" URL:URL parameters:parameters];
    [manange driveTask:success failure:failure];
}

POST不带parameters

+(void)requestPostWithURL:(NSString *)URL
                 success:(void (^)(NSData *__nullable data,NSURLResponse * __nullable response))success
                 failure:(void (^)(NSError *__nullable error))failure
{

    LYHTTPRequestOperationManager *manange = [[LYHTTPRequestOperationManager alloc] initWithMethod:@"POST" URL:URL parameters:nil];
    [manange driveTask:success failure:failure];
}

POST带parameters

+(void)requestPostWithURL:(NSString *)URL
              parameters:(id) parameters
                 success:(void (^)(NSData *__nullable data,NSURLResponse * __nullable response))success
                 failure:(void (^)(NSError *__nullable error))failure
{

    LYHTTPRequestOperationManager *manange = [[LYHTTPRequestOperationManager alloc] initWithMethod:@"POST" URL:URL parameters:parameters];
    [manange driveTask:success failure:failure];
}

接下去正是进入我们的改动ViewController代码实行测试:

- (IBAction)test:(id)sender {
    NSString *postURL = @"http://cityuit.sinaapp.com/p.php";
    NSString *getURL= @"http://cityuit.sinaapp.com/1.php";

    id parmentersPost = @{
                      @"username":@"1",
                      @"password":@"1"
                      };
    id parmentersGet = @{
                      @"value":@"Lastday",
                          };



    [LyNetWork requestWithMethod:@"POST"
                             URL:@"http://cityuit.sinaapp.com/1.php?value=Lastday"
                         success:^(NSData *data,NSURLResponse *response){
                             NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                             NSLog(@"requestWithMethod = %@",string);
                         }
                         failure:^(NSError *error){
                             NSLog(@"====%@",error);
                         }];


    [LyNetWork requestPostWithURL:postURL
                       parameters:parmentersPost
                          success:^(NSData *data,NSURLResponse *response){
                              NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                              NSLog(@"requestPostWithURL(带参数) = %@",string);
                          }
                          failure:^(NSError *error){

                          }];
    [LyNetWork requestPostWithURL:postURL
                          success:^(NSData *data,NSURLResponse *response){
                              NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                              NSLog(@"requestPostWithURL(不带参数) = %@",string);
                          }
                          failure:^(NSError *error){

                          }];

    [LyNetWork requestGetWithURL:getURL
                       parameters:parmentersGet
                          success:^(NSData *data,NSURLResponse *response){
                              NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                              NSLog(@"requestGetWithURL(带参数) = %@",string);
                          }
                          failure:^(NSError *error){

                          }];

    [LyNetWork requestGetWithURL:getURL
                          success:^(NSData *data,NSURLResponse *response){
                              NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                              NSLog(@"requestGetWithURL(不带参数) = %@",string);
                          }
                          failure:^(NSError *error){

                          }];



}

看一下实践结果

起名 22

起名, 

测试NSURLSession

首先大家来新建2个工程,起名叫LyHttp,在页面上放置2个开关,起名称叫”测试”。

起名 23

将按键关联到大家的ViewController.m,起名称叫test。

起名 24

增添以下代码

- (IBAction)test:(id)sender {
    NSURL *url = [NSURL URLWithString:@"http://cityuit.sinaapp.com/1.php"];
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * data,NSURLResponse *reponse,NSError *error){
  NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  NSLog(@"%@",string);
    }];
    [task resume];
}

http://cityuit.sinaapp.com/1.php是我自己写的一个接口用来测试的,会返回succeed。 

大家来看一下触及效果:

起名 25

接下去就该处理我们的parameters参数了

作者们从AFNetworking中借鉴一下他的处理方案(其实那里自个儿便是仿照编写罢了)

咱俩新建七个类起名称叫LYU库罗德LRequestSerialization,在LYU逍客LRequestSerialization.h添加一下艺术

+(NSString *)LYQueryStringFromParameters:(NSDictionary *)parameters;

进入大家的LYU卡宴LRequestSerialization.m文件中,加多以下代码:

起名 26

#import "LYURLRequestSerialization.h"

@interface LYURLRequestSerialization()

@property (readwrite, nonatomic, strong) id  value;
@property (readwrite, nonatomic, strong) id  field;


@end

@implementation LYURLRequestSerialization



- (id)initWithField:(id)field value:(id)value {
    self = [super init];
    if (!self) {
        return nil;
    }

    self.field = field;
    self.value = value;

    return self;
}

#pragma mark -

FOUNDATION_EXPORT NSArray * LYQueryStringPairsFromDictionary(NSDictionary *dictionary);
FOUNDATION_EXPORT NSArray * LYQueryStringPairsFromKeyAndValue(NSString *key, id value);

+(NSString *)LYQueryStringFromParameters:(NSDictionary *)parameters {
    NSMutableArray *mutablePairs = [NSMutableArray array];
    for (LYURLRequestSerialization *pair in LYQueryStringPairsFromDictionary(parameters)) {

        [mutablePairs addObject:[pair URLEncodedStringValue]];
    }

    return [mutablePairs componentsJoinedByString:@"&"];
}



NSArray * LYQueryStringPairsFromDictionary(NSDictionary *dictionary) {
    return LYQueryStringPairsFromKeyAndValue(nil, dictionary);
}



NSArray * LYQueryStringPairsFromKeyAndValue(NSString *key, id value) {
    NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];

    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(compare:)];

    if ([value isKindOfClass:[NSDictionary class]]) {
        NSDictionary *dictionary = value;
        for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
            id nestedValue = dictionary[nestedKey];
            if (nestedValue) {
                [mutableQueryStringComponents addObjectsFromArray:LYQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
            }
        }
    } else if ([value isKindOfClass:[NSArray class]]) {
        NSArray *array = value;
        for (id nestedValue in array) {
            [mutableQueryStringComponents addObjectsFromArray:LYQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
        }
    } else if ([value isKindOfClass:[NSSet class]]) {
        NSSet *set = value;
        for (id obj in [set sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
            [mutableQueryStringComponents addObjectsFromArray:LYQueryStringPairsFromKeyAndValue(key, obj)];
        }
    } else {
        [mutableQueryStringComponents addObject:[[LYURLRequestSerialization alloc] initWithField:key value:value]];
    }

    return mutableQueryStringComponents;
}


static NSString * LYPercentEscapedStringFromString(NSString *string) {
    static NSString * const kLYCharactersGeneralDelimitersToEncode = @":#[]@"; // does not include "?" or "/" due to RFC 3986 - Section 3.4
    static NSString * const kLYCharactersSubDelimitersToEncode = @"!$&'()*+,;=";

    NSMutableCharacterSet * allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];
    [allowedCharacterSet removeCharactersInString:[kLYCharactersGeneralDelimitersToEncode stringByAppendingString:kLYCharactersSubDelimitersToEncode]];


    static NSUInteger const batchSize = 50;

    NSUInteger index = 0;
    NSMutableString *escaped = @"".mutableCopy;

    while (index < string.length) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wgnu"
        NSUInteger length = MIN(string.length - index, batchSize);
#pragma GCC diagnostic pop
        NSRange range = NSMakeRange(index, length);

        range = [string rangeOfComposedCharacterSequencesForRange:range];

        NSString *substring = [string substringWithRange:range];
        NSString *encoded = [substring stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet];
        [escaped appendString:encoded];

        index += range.length;
    }

    return escaped;
}

- (NSString *)URLEncodedStringValue {
    if (!self.value || [self.value isEqual:[NSNull null]]) {
        return LYPercentEscapedStringFromString([self.field description]);
    } else {
        return [NSString stringWithFormat:@"%@=%@", LYPercentEscapedStringFromString([self.field description]), LYPercentEscapedStringFromString([self.value description])];
    }
}

@end

简言之的说一下啊,以上的点子皆感觉着处理传入的NSDictonary参数,因为大家在行使的时候为了方便大家传入动态的parameters,所以她的的格式是那般的:

id parmenters = @{
                  @"value":@"LastDays",
                 };

将它处理后大家希望获得的样式应该是那般,对吧?

http:URL.php?value=LastDays

本条参数是三个动态的,咱们不可能鲜明里头毕竟有几组参数,而且还索要记挂的三个标题不怕NSDictonary中嵌套NSDictonary的情景,我们处理这种难点的一个构思正是递归。从最中间初步拍卖。

OK,那样我们就完结了parameters处理能力

接下来大家须要测试一下

为了拓展测试自身又重新改换了接口,提供了参数处理的力量,以下是新的接口:

http://cityuit.sinaapp.com/1.php  value=将要返回的值

更改下requestMethod方法

+(void)requestMethod:(NSString *)method
                 URL:(NSString *)URL
          parameters:(id) parameters
             success:(void (^)(NSData *__nullable data,NSURLResponse * __nullable response))success
             failure:(void (^)(NSError *__nullable error))failure
{
    NSString *newURL;
    if ([method isEqual:@"GET"]) {
        newURL = [[URL stringByAppendingString:@"?"] stringByAppendingString: [LYURLRequestSerialization LYQueryStringFromParameters:parameters]];

        NSLog(@"%@",newURL);
    }

    NSURL *url = [NSURL URLWithString:newURL];
    NSURLSession *session = [NSURLSession sharedSession];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = method;
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * data,NSURLResponse *response,NSError *error){
        if (error) {
            failure(error);
        }else{
            if (success) {
                success(data,response);
            }
        }
    }];
    [task resume];
}

其间变化的地方:

if ([method isEqual:@"GET"]) {
        newURL = [[URL stringByAppendingString:@"?"] stringByAppendingString: [LYURLRequestSerialization LYQueryStringFromParameters:parameters]];
        NSLog(@"%@",newURL);
    }

上述代码的意趣便是判断一下是不是未GET请求,如若是的话将拍卖后的parameters加到尾部,以刚才的参数为例子,处理后的newU汉兰达L为:http://cityuit.sinaapp.com/1.php?value=LastDays

也正是说重返值为LastDays

到ViewController.m中开始展览测试,测试代码如下:

起名 27

- (IBAction)test:(id)sender {

    id parmenters = @{
                      @"value":@"LastDays",
                      };
    [LyNetWork requestMethod:@"GET"
                         URL:@"http://cityuit.sinaapp.com/1.php"
                  parameters:parmenters
                     success:^(NSData *data,NSURLResponse *response){
                         NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                         NSLog(@"%@",string);
                     }
                     failure:^(NSError *error){
                         NSLog(@"%@",error);
                     }];
}

起名 28

ok重返结果为LastDays,成功添出席动态的动态的HTTP参数(parameters)的效劳。

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图