標籤:ios 網路請求 block傳值 封裝
1.block在倆個UIViewController間傳值
最近剛學了幾招block 的進階用法,其實就是利用block文法在倆個UIViewController之間傳值,在這裡分享給初學者,同時也方便我自己理解。我們知道UINavigationController類管理UIViewController的時候,利用的是“棧”的思想,在這裡不做過多解釋,切入正題,假設我們現在有倆個UIViewController,viewC1和viewC2,viewC1比viewC2先進入到UINavigationController裡,即viewC2是由viewC1push出來的,這裡的傳值是指將viewC2的值傳到viewC1裡面。例如通訊錄的修改,裡修改資訊等。
不多說,直接上例子:
一.首先在viewC2的標頭檔中的代碼:
//1 。重定義一個block類型typedef void(^BL)(UIColor *color);typedef void(^stringBL)(NSString *string);@interface SecondViewController : UIViewController//定義一個block屬性 一定要使用copy特性 原因:@property (nonatomic, copy) BL block;@property (nonatomic, copy) stringBL string;- (void)valueBlock:(BL)block;- (void)valueStringBlock:(stringBL)block;
提示:
重定義block在Xcode中有快捷實現方式,直接在@interfacexxx 上面一行打typedef會有提示: 直接斷行符號,第一個參數是返回值類型,第二個為重定義的block名稱,第三個為要傳參數類型和參數名;然後需要定義重定義block類型的屬性,並且實現參數為該重定義類型block的方法。
二.viewC2的.m檔案中代碼:
- (void)viewDidLoad{ [super viewDidLoad]; // Do any additional setup after loading the view. UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; button.frame = CGRectMake(0, 70, 320, 40); [self.view addSubview:button]; [button setTitle:@"return 1 page" forState:UIControlStateNormal]; [button addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];}- (void)buttonAction:(UIButton *)button{// 2.在合適的地方執行block代碼 self.block([UIColor redColor]); self.string(@"asdasdasd"); [self.navigationController popToRootViewControllerAnimated:YES];}- (void)valueBlock:(BL)block{ self.block = block;}- (void)valueStringBlock:(stringBL)block{ self.string = block;}解釋:實現標頭檔中定義的方法,方法內部寫將參數賦值給重定義block的屬性,然後在合適的地方執行block代碼,block裡面的參數即你要傳的值。
三.在viewC1中push第二個頁面的時候調用 viewC2的方法,直接斷行符號,block重定義中的參數名裡存的即是要在viewC1中修改的值。
2.利用block封裝網路請求類。1.建立網路請求類NetRequest,標頭檔如下
typedef void(^BLOCK)(id result);@interface NetRequest : NSObject@property (nonatomic, copy) BLOCK bl;- (void)requestNetWithUrl:(NSString *)urlStr BodyOfRequestForString:(NSString *)bodyStr block:(BLOCK)bl;+ (void)PostWithUrl:(NSString *)urlStr BodyOfRequestForString:(NSString *)bodyStr block:(BLOCK)bl;@end
解釋:該處利用的是非同步post傳值,標頭檔寫法基本上跟block傳值一樣,我這裡寫了一個+號方法,為的是能在使用NetRequest類的時候更加方便。可以看到這裡的方法有三個參數,分別是url的地址,以及設定request的HttpBody屬性的,這裡屬於網路請求,不做過多解釋。2.下面看.m檔案:實現倆個方法
- (void)requestNetWithUrl:(NSString *)urlStr BodyOfRequestForString:(NSString *)bodyStr block:(BLOCK)bl{ self.bl = bl; NSURL *url = [NSURL URLWithString:urlStr]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30]; request.HTTPMethod = @"post"; NSData *bodyData = [bodyStr dataUsingEncoding:NSUTF8StringEncoding]; request.HTTPBody = bodyData; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options :NSJSONReadingMutableContainers error:nil]; NSLog(@"%d", [[dic objectForKey:@"news"] count]); self.bl(dic); }]; }+ (void)PostWithUrl:(NSString *)urlStr BodyOfRequestForString:(NSString *)bodyStr block:(BLOCK)bl{ NetRequest *netRequest = [[NetRequest alloc] init]; [netRequest requestNetWithUrl:urlStr BodyOfRequestForString:bodyStr block:bl];}解釋:-方法中首先要設定屬性block=參數block,再將要傳的值添加到block方法的參數中。+號方法是利用-號方法將參數block傳給屬性block。因為在+號方法中不能直接給屬性賦值。
3.如何使用:將資料轉送到ViewController上
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{ self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization self.array = [NSMutableArray array]; self.title = @"新聞"; NSString *urlStr = @"http://ipad-bjwb.bjd.com.cn/DigitalPublication/publish/Handler/APINewsList.ashx"; NSString *bodyStr = @"date=20131129&startRecord=1&len=30&udid=1234567890&terminalType=Iphone&cid=213"; [NetRequest PostWithUrl:urlStr BodyOfRequestForString:bodyStr block:^(id result) { self.array = [result objectForKey:@"news"]; [self.tableView reloadData]; }]; } return self;}- (void)viewDidLoad{ [super viewDidLoad]; // Do any additional setup after loading the view. self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 480) style:UITableViewStylePlain]; [self.view addSubview:self.tableView]; self.tableView.dataSource = self; self.tableView.delegate = self; [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"reuse"]; }- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ NSString *str = @"reuse"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:str]; cell.textLabel.numberOfLines = 2; cell.textLabel.text = [[self.array objectAtIndex:indexPath.row] objectForKey:@"title"]; return cell;}-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ WebViewController *webVC = [[WebViewController alloc] init]; webVC.webUrl = [[self.array objectAtIndex:indexPath.row] objectForKey:@"newsUrl"]; [self.navigationController pushViewController:webVC animated:YES]; [webVC release];}-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return [self.array count];}
下面來看看為什麼我們要用這種傳值方式:因為我要把當前獲得的資料轉送給一個UIViewController,而這個UIViewController上面有UITableView,需要重新整理,而我們擷取網路資料的時候使用的是利用block封裝的一個擷取NSData的方法,該方法會在資料載入完後才會執行塊語句,而且網路會有延遲,我們的UI介面會優先於資料顯示在手機上,所以當資料請求成功後,我們需要重新整理頁面,即調用UITableView的reloadData方法,所以才使用這種策略。
這是今天新get的技能,在這裡分享給大家,我是個新手,有上面問題還望能得到大家的指導。謝謝!