// // ViewController.h // 賣票 // // Created by apple on 13-7-29. // Copyright (c) 2013年 itcast. All rights reserved. // #import <UIKit/UIKit.h> @interface ViewController : UIViewController // 多行文本提示框 @property (weak, nonatomic) IBOutlet UITextView *infoTextView; // NSThread售票 - (IBAction)threadSales:(id)sender; // NSInvocationOperation售票 - (IBAction)invocationSales:(id)sender; // NSBlockOperation售票 - (IBAction)blockSales:(id)sender; // GCD售票 - (IBAction)gcdSales:(id)sender; @end
<pre name="code" class="objc">
// ViewController.m // 賣票 // Created by apple on 13-7-29. #import "ViewController.h" @interface ViewController () { NSInteger _tickets; // 線程鎖NSLock,必須是成員變量,不能是局部變量 NSLock *_lock; } // 如下的atomic成員,結合同步代碼塊使用,@synchronized (self) {} @property (assign, atomic) NSInteger tickets; /* 1. 在作多線程NSOperation和GCD技術的時候,搶奪的內存資源必須是「原子屬性」——atomic 2. 搶奪的資源在使用的時候, //必定要用屬性的self.xxx或者object.xxx,這樣才getter,才atomic發揮做用 3. 要在Operation和GCD中搶奪資源。需要使用到「同步鎖」,@synchronized(self){...} //目的是,鎖住與搶奪資源相關的代碼,包含讀和寫 4. 平時,儘可能不要用搶奪資源去作推斷條件,並且同步鎖的範圍越小越好!*/ @end @implementation ViewController /* // 同步鎖是要手敲出來的 @synchronized (self) { } */ // 爲了在TextView裏面添加文本,更新界面,需要先寫一個方法處理。 // 1. 讀出當前文本框的內容 // 2. 把要追加的文本附加在當前文本框內容的後面 // 3. 又一次爲文本框賦值 // 這是負責更新界面的UI - (void)appendTextView:(NSString *)text { NSMutableString *str = [NSMutableString stringWithString:_infoTextView.text]; [str appendFormat:@"\n%@", text]; [_infoTextView setText:str]; // 定義一個NSRange,表明文本框需要滾動到的位置 NSRange range = NSMakeRange(str.length, 1); // 咱們現在想要滾動到最後,這種方法的參數是一個NSRange [_infoTextView scrollRangeToVisible:range]; } // 多線程一:響應button點擊,啓動NSThread售票 - (IBAction)threadSales:(id)sender { _tickets = 100; // 建立線程 NSThread1 NSThread *thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(threadSaleMethod) object:nil]; // 設置線程1的名字 [thread1 setName:@"售票線程-1"]; // 啓動線程 NSThread1 僅僅有NSThread需要手動start [thread1 start]; // 建立線程 NSThread2 NSThread *thread2 = [[NSThread alloc]initWithTarget:self selector:@selector(threadSaleMethod) object:nil]; // 設置線程2的名字 [thread2 setName:@"售票線程-2"]; // 啓動線程 NSThread2 僅僅有NSThread需要手動start [thread2 start]; } // 多線程一:實際NSThread售票運行的代碼,線程跑的方法 #pragma mark - 本身定義方法,NSThread售票核心代碼 - (void)threadSaleMethod { // 1. 推斷是否還有票 // 2. 更新界面,提示當前票數 // 3. 總票數-1 // 4. 模擬延時 // 要解決一個問題:在threadSaleMethod這一個方法裏面,咱們就把所有的票賣光。!html
!web
// 線程鎖:所謂線程鎖。就是:在改動或者推斷共享資源的時候, //需要把共享資源加鎖,防止別的線程對 // 共享資源進行改動。 // 使用線程鎖的方式: // 1. 定義鎖,懶載入,且鎖必須是成員變量 if (_lock == nil) { _lock = [[NSLock alloc]init]; } while (YES) { // 2. 使用共享資源以前。加鎖 [_lock lock]; if (_tickets > 0) { // 作了一個字符串,顯示提示信息 NSString *str = [NSString stringWithFormat:@"當前票數是%d,售票線程是%@", _tickets, [[NSThread currentThread]name]]; // 主線程,UI界面中顯示一下票數 // 在多線程方法裏面不能這樣使用的 // [self appendTextView:@"12"]; // waitUntilDone 的意思是:是否等待主線程更新完成 [self performSelectorOnMainThread:@selector(appendTextView:) withObject:str waitUntilDone:YES]; // 售完一張,票數減1 _tickets--; // 3. 使用共享資源完成,立刻解鎖 [_lock unlock]; // 模擬不一樣售票效率 if ([[[NSThread currentThread]name] isEqualToString:@"售票線程-1"]) { [NSThread sleepForTimeInterval:0.2]; } else { [NSThread sleepForTimeInterval:0.3]; } } else { // 3. 使用共享資源完成,立刻解鎖 [_lock unlock]; // 結束時,打印下線程名 NSString *str = [NSString stringWithFormat:@"票已售完%@", [[NSThread currentThread]name]]; // 主線程,UI界面中顯示一下哪一個線程結束了 [self performSelectorOnMainThread:@selector(appendTextView:) withObject:str waitUntilDone:YES]; NSLog(@"%@", str); // 退出循環 break; } } } // 多線程二:響應button點擊,經過NSInvocationOperation加入到NSOperationQueue售票 - (IBAction)invocationSales:(id)sender { _tickets = 20; // 1. 定義2個NSInvocationOperation操做 // 1.1. 操做需要調用一個target對象的selector方法。類似NSThread // 1.2. 第3個參數object表明:方法是可以接收參數的,且僅僅能接收一個。 NSInvocationOperation *operation1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(operationSaleMethod:) object:@"Operation - 1"]; NSInvocationOperation *operation2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(operationSaleMethod:) object:@"Operation - 2"]; // 2. 定義1個操做隊列NSOperationQueue NSOperationQueue *queue = [[NSOperationQueue alloc]init]; // 3. 將2個操做逐一加入到操做隊列,本身主動啓動 [queue addOperation:operation1]; [queue addOperation:operation2]; } // 多線程二:經過NSInvocationOperation加入到NSOperationQueue售票運行的代碼,線程跑的方法 // 相同也是多線程三:經過NSOperationQueue的block售票的核心代碼,線程跑的方法 #pragma mark - NSOperation售票,使用@synchronized(self){} // NSOperation售票方法,參數是上面方法定義的操做名稱 - (void)operationSaleMethod:(NSString *)operationName { // 賣票流程——在這一個方法裏面,咱們需要把所有的票賣光。!!瀏覽器
// 1. 是否有票 // 2. 顯示當前票數 // 3. 票數-1 // 4. 經過延時,模擬效率 while (YES) { // !緩存
。。同步鎖要鎖住所有搶奪資源的代碼 // 平時,儘可能不要用搶奪的資源作推斷條件。會添加同步鎖的範圍,減小效率! @synchronized(self) { if (self.tickets > 0) { NSString *str = [NSString stringWithFormat:@"當前票數:%d。線程名稱:%@", self.tickets, operationName]; // 主線程隊列「僅僅」負責更新UI // 把所有的成員變量調用的位置都改爲了getter方式調用,發揮atomickeyword // 屬性調用是經過getter,這樣調用才幹發揮atomic的做用 [[NSOperationQueue mainQueue]addOperationWithBlock:^{ // 在NSOperationQueue的主隊列中,僅僅負責更新界面UI [self appendTextView:str]; }]; self.tickets--; // 經過延時,模擬不一樣售票效率 if ([operationName isEqualToString:@"Operation - 1"] || [operationName isEqualToString:@"Block - 1"]) { [NSThread sleepForTimeInterval:0.2]; } else { [NSThread sleepForTimeInterval:1.0]; } } else { NSString *str = [NSString stringWithFormat:@"票已售完,線程名稱:%@", operationName]; // 在NSOperationQueue的主隊列中,僅僅負責更新界面UI [[NSOperationQueue mainQueue]addOperationWithBlock:^{ [self appendTextView:str]; }]; break; } }//同步代碼塊@synchronized,到這兒才結束 } } // 多線程三:響應button點擊,經過NSOperationQueue的block售票 - (IBAction)blockSales:(id)sender { _tickets = 20; // 1,定義NSOperationQueue操做隊列 NSOperationQueue *queue = [[NSOperationQueue alloc]init]; // 2,經過block給操做隊列加入本身定義方法,並運行 [queue addOperationWithBlock:^{ [self operationSaleMethod:@"Block - 1"]; }]; // 2,經過block給操做隊列加入本身定義方法,並運行 [queue addOperationWithBlock:^{ [self operationSaleMethod:@"Block - 2"]; }]; // 2,經過block給操做隊列加入本身定義方法,並運行 [queue addOperationWithBlock:^{ [self operationSaleMethod:@"Block - 3"]; }]; // 3,設置NSOperationQueue操做隊列,最大併發運行任務個數 [queue setMaxConcurrentOperationCount:2]; } // 多線程四:響應button點擊,經過GCD grand central dispatch售票 - (IBAction)gcdSales:(id)sender { _tickets = 20; // 1. 獲取全局隊列 dispatch_get_global_queue,參數1爲默認優先級, // 參數2標記永遠是0 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 2. 建立小組 dispatch_group_create dispatch_group_t group = dispatch_group_create(); // 3. 向小組加入異步任務一,dispatch_group_async // 參數1,小組名 // 參數2,全局隊列名 // 參數3,block,即指定詳細要運行的方法,可帶參數:名字 dispatch_group_async(group, queue, ^{ [self gcdSaleMethod:@"GCD-1"]; }); // 3. 向小組加入異步任務二。dispatch_group_async // 參數1,小組名 // 參數2,全局隊列名 // 參數3,block,即指定詳細要運行的方法,可帶參數,名字 dispatch_group_async(group, queue, ^{ [self gcdSaleMethod:@"GCD-2"]; }); // 4. 監聽小組通知 // 參數1,小組名 // 參數2,得到主隊列 dispatch_get_main_queue() // 參數3,block代碼塊:所有異步任務都完成時,要作的事情!!! dispatch_group_notify(group, dispatch_get_main_queue(), ^{ // 提示用戶沒有票了。更新到界面UI [self appendTextView:@"票已售完!"]; }); } // 多線程四:經過GCD向小組加入的異步任務。即線程跑的方法 #pragma mark - GCD售票 詳細賣票流程 - (void)gcdSaleMethod:(NSString *)gcdName { // 1. 確認票數 // 2. 更新界面 // 3. 票數-1 // 4. 模擬延時 while (YES) { if (_tickets > 0) { // 1. 肯定要更新的內容 NSString *str = [NSString stringWithFormat:@"當前票數:%d, 售票線程:%@", _tickets, gcdName]; // 2. dispatch_async(),開啓異步任務, // 參數1,要在哪一個地方運行該異步任務:dispatch_get_main_queue() // 參數2,block指明要運行的詳細異步任務:更新UI界面,並且票數-1 dispatch_async(dispatch_get_main_queue(), ^{ [self appendTextView:str]; // GCD中 對共用資源的改動也要放到得到的主隊列裏 _tickets--; }); // 經過延時,模擬不一樣售票效率 if ([gcdName isEqualToString:@"GCD-1"]) { [NSThread sleepForTimeInterval:0.2]; } else { [NSThread sleepForTimeInterval:1.0]; } } else { break; } } } @end 網絡
// ViewController.h // ASI演練 // Created by apple on 13-7-30. // Copyright (c) 2013年 itcast. All rights reserved. #import <UIKit/UIKit.h> #import "ASIHTTPRequest.h" @interface ViewController : UIViewController <ASIHTTPRequestDelegate, ASIProgressDelegate> // 響應button點擊,下載文件 - (IBAction)downloadFile:(id)sender; @end
<pre name="code" class="objc">// ViewController.m // ASI演練 /* ASIproject注意事項: 1,不能選ARC 2,更改IOS 部署 目標爲 IOS5.0 3,將ASI壓縮包,解壓,拖動Classes文件夾和External文件夾拖進project 4,嘗試編譯,出現錯誤:沒法找到libxml/HTMLparser.h 解決方法: 進入build settings,找到_head search paths頭文件搜索文件夾_加入: ${SDK_DIR}/usr/include/libxml2,並回車 5,再次嘗試編譯,出現錯誤:ASITestCase.h:12:9: 'GHUnitIOS/GHUnit.h' file not found 錯誤緣由:沒有GHUnit框架 解決的方法: 進入build phases 展開compile sources 將tests結尾的文件全部移除,按減號,即測試文件,不參與編譯 即刪除單元測試部分的代碼引用 6,再次command B 編譯,85個錯誤 解決方法: 很是easy,進入summary,找到連接的框架和引用,+號,加入下列iOS框架引用就能夠 CFNetwork.framework SystemConfiguration.framework MobileCoreServices.framework libz.dylib libxml2.dylib 7,上述框架,在ASI提供的project樣本中可以看到,再次編譯OK 8,爲了解壓縮,還要加入SSZipArchive框架 將下面文件加入project: SSZipArchive.h SSZipArchive.m minizip文件夾 9,編譯OK */ // Created by apple on 13-7-30. // Copyright (c) 2013年 itcast. All rights reserved. #import "ViewController.h" #import "SSZipArchive.h" // 遵照兩個ASI協議 <ASIHTTPRequestDelegate, ASIProgressDelegate> @interface ViewController () { // 下載文件的大小,頭信息字典中的文件長度,在後面進度中要用到 CGFloat _fileLength; } @end @implementation ViewController #pragma mark - 響應button點擊,開始啓動ASI框架斷點續傳下載文件 - (IBAction)downloadFile:(id)sender { // 1. 指定下載文件地址 NSString *urlString = @"http://teacher.local/~apple/itcast/download/iTunesConnect_DeveloperGuide_CN.zip"; NSURL *url = [NSURL URLWithString:urlString]; // 2. 設定文件保存路徑及暫時緩存路徑 NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //保存路徑 NSString *downloadPath = [documents[0]stringByAppendingPathComponent:@"book.zip"]; //緩存路徑 NSString *tempPath = [documents[0]stringByAppendingPathComponent:@"book.tmp"]; // 3. 經過URL,初始化ASIHTTPRequest實例對象,不支持ARC ASIHTTPRequest *request = [[[ASIHTTPRequest alloc]initWithURL:url]autorelease]; // 4. 設置代理爲當前控制器——ASI是經過代理回調的方式處理網絡請求的 [request setDelegate:self]; // 5. 設置下載完畢的保存路徑 [request setDownloadDestinationPath:downloadPath]; // 6. 設置暫時緩存路徑 [request setTemporaryFileDownloadPath:tempPath]; // 7. 設置贊成斷點續傳 [request setAllowResumeForFileDownloads:YES]; // 8. 設置下載進程代理——用戶想知道下載的實際進展狀況 [request setDownloadProgressDelegate:self]; // 9. 啓動異步請求 [request start]; } #pragma mark - ASI代理方法 // 2. 接收到響應頭 didReceiveResponseHeaders 目的得到文件長度 - (void)request:(ASIHTTPRequest *)request didReceiveResponseHeaders:(NSDictionary *)responseHeaders { // 經過Log,咱們看到了"Content-Length" = 6105204; // 貌似可以用來監控下載進度 // 暫時不去管它 NSLog(@"請求頭%@", responseHeaders); // 在這裏。咱們可以知道文件長度。若是咱們在這裏記錄下來文件的長度,若是100M // 需要得到的是文件的兆數會更加人性化 字節->K->M(1024) NSInteger length = [responseHeaders[@"Content-Length"]integerValue]; // 文件長度計算以後。是一個小數,需要改變一下成員變量的類型 _fileLength = (CGFloat)length / 1024 / 1024; } #pragma mark - 下載進度的代理方法 - (void)setProgress:(float)newProgress { // 傳回來的參數是一個下載進度的百分比 // 那麼,咱們告訴用戶還差多少M下載完畢? NSLog(@"%.2f", newProgress * _fileLength); // 100M * 0.2 = 20M } #pragma mark - ASI代理方法 // 3. 請求完畢 requestFinished - (void)requestFinished:(ASIHTTPRequest *)request { NSLog(@"請求完畢"); // 咱們可以去作解壓縮的工做了。因爲下載工做已經完畢了!// 需求: // 1. 知道文件保存路徑 // 2. 解壓縮文件 // 2.1 定義一個壓縮文件 NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *downloadPath = [documents[0]stringByAppendingPathComponent:@"book.zip"]; // 2.3 調用SSZipArchive的類方法解壓縮,參數2是一個文件夾 [SSZipArchive unzipFileAtPath:downloadPath toDestination:documents[0]]; // 3. 經過文件管理者(單例),刪除壓縮文件 [[NSFileManager defaultManager]removeItemAtPath:downloadPath error:nil]; } #pragma mark - ASI代理方法 // 代理方法之1. 請求開始 - (void)requestStarted:(ASIHTTPRequest *)request { NSLog(@"請求開始"); } #pragma mark - ASI代理方法 // 代理方法之4. 請求失敗 - (void)requestFailed:(ASIHTTPRequest *)request { NSLog(@"請求失敗"); } @end 多線程
// // ViewController.h // AFN斷點續傳演練 // // Created by apple on 13-7-30. // Copyright (c) 2013年 itcast. All rights reserved. // #import <UIKit/UIKit.h> @interface ViewController : UIViewController // 下載文件 - (IBAction)downloadFiles:(id)sender; @end
<pre name="code" class="objc">// ViewController.m // AFN斷點續傳演練 // Created by apple on 13-7-30. // Copyright (c) 2013年 itcast. All rights reserved. /* AFN使用步驟: 1,新建project的時候,勾選ARC(畢竟AFN有是人在維護的) 2,拖動目錄AFNetworking到project中 3,將解壓要用到的目錄SSZipArchive拖到project中 同一時候導入它依賴的libz.dylib框架 4,編譯,彈出2個warning,缺乏框架 SystemConfiguration.framework MobileCoreServices.framework 5,展開supporting files目錄,找到--> project名-Prefix.pch文件,在#endif的前面加入 #import<SystemConfiguration/SystemConfiguration.h> #import<MobileCoreServices/MobileCoreServices.h> 6,再次編譯ok */ #import "ViewController.h" #import "AFNetworking.h" #import "SSZipArchive.h" @interface ViewController () @end @implementation ViewController #pragma mark - 下載文件 - (IBAction)downloadFiles:(id)sender { // 1. 指定下載文件地址 NSURL *url = [NSURL URLWithString:@"http://169.254.98.245/~apple/itcast/download/iTunesConnect_DeveloperGuide_CN.zip"]; // 2. 指定文件保存路徑 NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *downloadPath = [documents[0]stringByAppendingPathComponent:@"book.zip"]; // 3. 建立NSURLRequest NSURLRequest *request = [NSURLRequest requestWithURL:url]; // 4. 經過固定請求,建立AFURLConnectionOperation,多態 AFURLConnectionOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; // 5. 設置操做的輸出流(在網絡中的數據是以流的方式傳輸的, //告訴操做把文件保存在第2步設置的路徑中) [operation setOutputStream:[NSOutputStream outputStreamToFileAtPath:downloadPath append:NO]]; // 6. 設置下載進程處理塊代碼 // 6.1 bytesRead 讀取的字節——這一次下載的字節數 // 6.2 totalBytesRead 讀取的總字節——已經下載完的 // 6.3 totalBytesExpectedToRead 但願讀取的總字節——就是文件的總大小 [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { // 作下載進度百分比的工做 NSLog(@"下載百分比:%f", (float)totalBytesRead / totalBytesExpectedToRead); }]; // 7. 操做完畢塊代碼 [operation setCompletionBlock:^{ // 解壓縮的順序 // 1. 定義要解壓縮的文件 —— downloadPath // 2. 要解壓縮的目標目錄,必須是目錄 // 3. 調用類方法解壓縮 [SSZipArchive unzipFileAtPath:downloadPath toDestination:documents[0]]; // 使用文件管理者,刪除壓縮包 [[NSFileManager defaultManager]removeItemAtPath:downloadPath error:nil]; }]; // 8 啓動操做 [operation start]; } @end
// // ViewController.h // UIWebView演練 // // Created by apple on 13-7-30. // Copyright (c) 2013年 itcast. All rights reserved. // #import <UIKit/UIKit.h> @interface ViewController : UIViewController // 成員屬性:UIWebView控件 @property (weak, nonatomic) IBOutlet UIWebView *localWebView; // 點擊,載入PDF文件button - (IBAction)clickPDFButton:(id)sender; // 點擊,載入HTMLString - (IBAction)loadHTMLString:(id)sender; // 點擊,使用loadData載入數據 - (IBAction)loadData:(id)sender; @end
<pre name="code" class="objc">// ViewController.m // UIWebView演練 // Created by apple on 13-7-30. // Copyright (c) 2013年 itcast. All rights reserved. #import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // 經過本身定義方法得到MIMETYPE [self mimeType]; } // 本身定義方法,獲取MIMEType // 因爲咱們不能記住所有類型文檔的MIMEType,因此咱們本身動手。寫一個方法 - (NSString *)mimeType { // 一。本地文件URL生成的過程 // 1. 絕對路徑 NSString *path = [[NSBundle mainBundle]pathForResource:@"關於.docx" ofType:nil]; // 2 絕對路徑轉FILEURL NSURL *fileURL = [NSURL fileURLWithPath:path]; // 二。網絡文件URL生成的過程 // 1. 網絡地址字符串 NSString *urlString = @"http://www.baidu.com"; // 2. 生成URL NSURL *webURL = [NSURL URLWithString:urlString]; // 1. 定義固定請求 NSURLRequest *request = [NSURLRequest requestWithURL:fileURL]; // 2. 定義響應,到時候,傳入地址,到時候方便接收返回的response NSURLResponse *response = nil; // 3. NSConnection靜態方法,發送同步請求,傳入接收響應的地址 [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil]; NSLog(@"MIMEType %@", response.MIMEType); return response.MIMEType; } // 響應button點擊事件, - (IBAction)clickPDFButton:(id)sender { [self viewLocalPDFFile]; } // 1. 咱們現在準備了一個素材是PDF // 2. 咱們要把這個PDF顯示在webView裏面 // 顯示本地PDF文件在WebView - (void)viewLocalPDFFile { // 1. 定義URL // 1. 全路徑 NSString *path = [[NSBundle mainBundle]pathForResource:@"iTunesConnect_DeveloperGuide_CN.pdf" ofType:nil]; // 2 全路徑獲得fileURL NSURL *fileURL = [NSURL fileURLWithPath:path]; // 2. 經過fileURL構建請求 NSURLRequest *request = [NSURLRequest requestWithURL:fileURL]; // 4. 重要!!!!!!設置WebView的數據偵測類型:爲偵測所有類型 [_localWebView setDataDetectorTypes:UIDataDetectorTypeAll]; // 5. 使用WebView載入這個請求就能夠 [_localWebView loadRequest:request]; } // 響應button點擊,載入HTMLString - (IBAction)loadHTMLString:(id)sender { // 臨時不考慮baseURL。集中在String上面 // 用「iOS 正則表達式」去搜索相關知識點,可以作新聞類的應用!併發
NSString *fullHTML = @"<html><head><title>hello</title></head><body><p1>我愛你</p1></body></html>"; NSString *partHTML = @"<p1>我愛你!!!app
</p1>"; // webview是可以顯示部分html代碼的 [_localWebView loadHTMLString:partHTML baseURL:nil]; } // 響應button點擊,載入「data數據」——NSData - (IBAction)loadData:(id)sender { // 1. pdf文件絕對路徑 NSString *path = [[NSBundle mainBundle]pathForResource:@"iTunesConnect_DeveloperGuide_CN.pdf" ofType:nil]; // 2 經過 絕對路徑 生成fileURL NSURL *fileURL = [NSURL fileURLWithPath:path]; // 2. 用NSData類方法載入數據,參數爲fileURL NSData *data = [NSData dataWithContentsOfURL:fileURL]; // 3. 使用webView載入data類型數據 [_localWebView loadData:data MIMEType:@"application/pdf" textEncodingName:@"UTF-8" baseURL:nil]; } @end 框架
// // ViewController.h // UIWebView Demo // // Created by apple on 13-7-21. // Copyright (c) 2013年 itcast. All rights reserved. // #import <UIKit/UIKit.h> @interface ViewController : UIViewController <UITextFieldDelegate, UIWebViewDelegate> // URL文本 @property (weak, nonatomic) IBOutlet UITextField *urlText; // 回退button @property (weak, nonatomic) IBOutlet UIBarButtonItem *goBackButton; // 前進button @property (weak, nonatomic) IBOutlet UIBarButtonItem *goForwardButton; // 重載button @property (weak, nonatomic) IBOutlet UIBarButtonItem *reloadButton; // 中止button @property (weak, nonatomic) IBOutlet UIBarButtonItem *stopButton; // Web視圖 @property (weak, nonatomic) IBOutlet UIWebView *webView; // 回退 - (IBAction)goBack:(id)sender; // 前進 - (IBAction)goForward:(id)sender; // 刷新 - (IBAction)reloadURL:(id)sender; // 提交表單 - (IBAction)submit:(id)sender; @end
// ViewController.m // UIWebView 瀏覽器綜合演示 // Created by apple on 13-7-21. // Copyright (c) 2013年 itcast. All rights reserved. #import "ViewController.h" @interface ViewController () // 訪問指定URL字符串的內容,僅由文本框回車事件調用 - (void)gotoURLString:(NSString *)urlString; // 訪問指定的URL內容 - (void)gotoURL:(NSURL *)url; // 得到本地文件的MIMEType - (NSString *)MIMEType:(NSString *)fileName; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [self MIMEType:@"001.網絡基礎.pdf"]; // 調用本身定義測試方法 [self testLoadHTMLFile]; } // 測試載入本地HTML文件 - (void)testLoadHTMLFile { // 測試載入本地HTML文件,需要指定MIMETYPE NSString *dataPath = [[NSBundle mainBundle]pathForResource:@"demo.html" ofType:nil]; // baseURL基址,以便查找CSS JS jpg等 NSURL *baseURL = [NSURL fileURLWithPath:[[NSBundle mainBundle]resourcePath] isDirectory:YES]; // 僅僅有載入的html文件才需要指定baseURL路徑,告訴瀏覽器去哪裏找圖片、樣式表等文件 [_webView loadData:[NSData dataWithContentsOfFile:dataPath] MIMEType:@"text/html" textEncodingName:@"UTF-8" baseURL:baseURL]; } // 本身定義方法,得到本地文件的MIMEType - (NSString *)MIMEType:(NSString *)fileName { // 依據文件名稱,獲得絕對路徑 NSString *path = [[NSBundle mainBundle]pathForResource:fileName ofType:nil]; // 依據絕對路徑,獲得fileURL NSURL *url = [NSURL fileURLWithPath:path]; // 依據url 建立固定請求 NSURLRequest *request = [NSURLRequest requestWithURL: url]; // 定義響應,以便接收響應內容 NSURLResponse *response = nil; // 發送同步請求,並傳入響應的地址,以便接收響應 [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil]; NSLog(@"MIMEType is %@", [response MIMEType]); return [response MIMEType]; } #pragma mark - UIWebView載入內容的測試方法 // 載入HTML字符串 - (void)testLoadHTMLString { // 測試載入HTML字符串 NSString *html = @"<html><head><title>紅樓夢</title></head><body><h1>世外仙姝</h1></body></html>"; [_webView loadHTMLString:html baseURL:nil]; } // 載入部分HTML字符串測試 - (void)testLoadPartHTMLString { // 測試載入部分HTML字符串。不需要顯示整個網頁內容時。一般使用此方法 NSString *partHtml = @"<h1>寂寞林</h1>"; [_webView loadHTMLString:partHtml baseURL:nil]; } // 載入本地PDF文件 - (void)testLoadPDFFile { // 測試載入本地PDF,需要指定MIMETYPE NSString *dataPath = [[NSBundle mainBundle]pathForResource:@"001.網絡基礎.pdf" ofType:nil]; [_webView loadData:[NSData dataWithContentsOfFile:dataPath] MIMEType:@"application/pdf" textEncodingName:@"UTF-8" baseURL:nil]; } // 載入本地文本文件 - (void)testLoadTextFile { // 測試載入本地文本文件,需要指定MIMETYPE NSString *dataPath = [[NSBundle mainBundle]pathForResource:@"關於.txt" ofType:nil]; [_webView loadData:[NSData dataWithContentsOfFile:dataPath] MIMEType:@"text/plain" textEncodingName:@"UTF-8" baseURL:nil]; } #pragma mark - UITextField代理方法 // 文本框回車事件 - (BOOL)textFieldShouldReturn:(UITextField *)textField { // 假設被回車的是地址欄,且不爲空 if (textField == _urlText && textField.text.length > 0) { // 退出鍵盤 [textField resignFirstResponder]; // 調用本身定義方法,轉到URLstring方法 [self gotoURLString:textField.text]; } return YES; } #pragma mark - 本身定義方法,回車後,調用訪問指定URL內容 // 訪問指定URL字符串的內容,僅由文本框事件調用,文本框回車時候調用的 - (void)gotoURLString:(NSString *)urlString { NSURL *url = nil; // 推斷是不是httpURL if ([urlString hasPrefix:@"http://"]) { // URL中有中文的。是需要加百分號的。 url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; } else if ([urlString hasPrefix:@"file://"]) { // 推斷給定參數是否已是完整的url路徑,避免出現前進後退後, //URL變成完整URL沒法訪問的狀況 if ([urlString hasPrefix:@"file://localhost/"]) { // 注意此處不能使用fileURLWithPath方法??????????異步
?
// 因爲fileURLWithPath是將絕對路徑,轉成fileURL // 而此時,已是fileURL了 url = [NSURL URLWithString:urlString]; } else { // 假設沒有localhost前綴的,說明是新輸入的本地文件。需要轉換url。
// 檢測字串範圍 NSRange range = [urlString rangeOfString:@"file://"]; // 截取剩餘部分做爲文件名稱 NSString *fileName = [urlString substringFromIndex:range.length]; // 依據文件名稱,生成文件絕對路徑 NSString *path = [[NSBundle mainBundle]pathForResource:fileName ofType:nil]; // 推斷絕對路徑是否存在 if ([[NSFileManager defaultManager]fileExistsAtPath:path]) { // 若存在,將絕對路徑轉成fileURL url = [NSURL fileURLWithPath:path]; } else { url = nil; } } } // 假設到這兒url仍爲空,說明,轉換失敗,輸入地址欄內容有誤 if (url == nil) { UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"輸入地址不對。請又一次輸入!
" delegate:nil cancelButtonTitle:@"肯定" otherButtonTitles:nil, nil]; [alert show]; // 設置文本框輸入焦點 [_urlText becomeFirstResponder]; } else { // 地址正確,下一步,調用本身定義方法,訪問指定的URL內容 [self gotoURL:url]; } } // 地址正確,下一步,調用本身定義方法,訪問指定的URL內容 - (void)gotoURL:(NSURL *)url { // 使用轉換後的URL字符串替代用戶輸入的URL文本框內容 // absoluteString??? [_urlText setText:[url absoluteString]]; // 1, 依據url 建立固定請求 NSURLRequest *request = [NSURLRequest requestWithURL:url]; // 2, 設置瀏覽器,本身主動偵測所有數據類型 [_webView setDataDetectorTypes:UIDataDetectorTypeAll]; // 3, webView 載入請求 [_webView loadRequest:request]; } // 響應button點擊,JS 提交表單 - (IBAction)submit:(id)sender { // 獲取當前頁面的url NSString *url = [_webView stringByEvaluatingJavaScriptFromString:@"document.location.href"]; NSLog(@"url %@", url); // 獲取當前頁面的標題 NSString *title = [_webView stringByEvaluatingJavaScriptFromString:@"document.title"]; NSLog(@"title %@", title); // 提交表單 [_webView stringByEvaluatingJavaScriptFromString:@"document.forms[0].submit(); "]; } #pragma mark - UIWebViewDelegate 代理方法 // 網頁中的每一個請求都會被觸發這種方法,返回NO表明不運行這個請求(常用於JS與iOS之間通信) - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSLog(@"將要載入請求"); return YES; } #pragma mark - IBActions // 調用瀏覽器webView默認的,回退操做 - (IBAction)goBack:(id)sender { [_webView goBack]; } // 調用瀏覽器webView默認的,前進操做 - (IBAction)goForward:(id)sender { [_webView goForward]; } // 調用瀏覽器webView默認的,刷新操做 - (IBAction)reloadURL:(id)sender { [_webView reload]; } #pragma mark - UIWebViewDelegate 代理方法 // 網頁開始載入的時候調用 - (void)webViewDidStartLoad:(UIWebView *)webView { NSLog(@"開始載入"); } #pragma mark - UIWebViewDelegate 代理方法 // 網頁載入完畢的時候調用 - (void)webViewDidFinishLoad:(UIWebView *)webView { NSLog(@"載入完畢"); } #pragma mark - UIWebViewDelegate 代理方法 // 網頁載入出錯的時候調用 - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { NSLog(@"載入出錯%@", [error localizedDescription]); } @end