1. 程式人生 > >善假於物,利用工具2天開發一款完整新聞類iOS app

善假於物,利用工具2天開發一款完整新聞類iOS app

題外話:
此篇文章以一個iOS新手的角度解釋一款新聞類iOS APP誕生的過程,詳細介紹在這過程中碰到的問題和我的解決思路。歡迎大家指正。

選單介面:

主介面:

詳細頁面:

關於我們頁面:

初期的想法

具體專案背景跳過,我們著重看如何實現一款新聞類APP。

在開始專案計劃前,我下載了大量的新聞類APP進行研究,不論是android還是iOS,充斥著大量的此類APP,比如網易新聞,一點諮詢,新浪微博(暫歸位新聞類),知乎,知乎日報等,然後我從零開始點開每個應用,思考它的流程以及佈局和要點。發現核心不外乎以下兩點:

  • 一個可以下拉重新整理的tableview(即一欄一欄的檢視)
  • 點選每一欄可以進入一個詳細的頁面

可是我們的應用不可能就這個樣子,需要有不同的新聞模組,所以又有以下幾點:

  • 兩種選單佈局:底部或頂部導航欄和側邊欄(抽屜導航)
  • 除了新聞模組還要新增豐富類模組,比如我這的地圖顯示和校車查詢(隨意拓展)。

當然,有了APP後我們的客戶端從哪請求資料呢?於是有了以下問題:

  • 如何一個人快速開發移動端的後臺,而且安全可靠

OK,暫先我們只想到這,至於優化本地儲存和使用者友好展示等,我們後面會涉及到。

開始實現

(一)繪畫草圖

一開始我們只是個想法,即便想了很多,依然還是覺的不踏實,沒有清晰的專案概念,所以我把專案的草圖畫了下來,如下:

這下心裡踏實多了,起碼知道自己想讓它長個什麼樣子了。

(二)開始佈局

ok,草圖已經有了,那想必大家已經知道我選用了流行的側邊欄(抽屜導航)佈局。大家都知道蓋一棟大樓最重要的是先把整棟大樓的骨架先搭起來,同樣一個APP首先要做的是把自己的架構搭起來,而這就是我們的佈局。

iOS有著眾多開源的專案,這是我以前就知道的(PS:這些都是經驗才能得到的,你可以通過看書,看部落格,瀏覽官網,與大牛交流等各種渠道獲取這些資訊),而對於類似我們這種側邊欄的佈局,開源界有著眾多的解決方案,我選用了SWRevealViewController **這套開源庫,地址是:
https://github.com/John-Lluch/SWRevealViewController

 (fork: **440 star: 1660)

案例效果:

(三)構建核心頁面

核心頁面是一個主頁面和一個詳細頁面:

  • 主頁面當然是新聞資訊的介面,因為我們的目標是一款新聞資訊類的框架,所以頁面就是一個新聞的列表。自然而然我們用了一個UItableView作為主頁面的控制元件。
  • 詳細頁面是展示詳細新聞內容的頁面,暫時我們不考慮複雜的涉及,只需要在裡面放置一textview
  • 通過segue將主頁面和詳細頁面聯絡起來,實現跳轉和訊息傳遞(基礎)

OK,核心介面有了(PS:我這裡使用的是Xcode的storboard構建頁面,不使用舊式的xib)

效果如下:

(四)構建伺服器

終於到了這個移動開發人員頭疼的問題了,由於專案需要,我們必須有可以提供資料的介面,對於前端移動開發人員來說如果可以自己構建後臺無疑減少了大量的溝通問題,然而人的精力有限,無法同時兼顧,咋麼辦?

OK,現在這個問題得到了不錯的解決,越來越多的雲服務開始出現,小編今天給大家推薦一款移動端後臺開發平臺Bomb(當然同類型的不少,不如facebook的Parse,不過國內大家都懂的),它提供了一套後臺開發所使用的SDK,方便的為你的前端產品搭建後臺,適合中小企業或者獨立開發者使用。

給出我的平臺數據庫圖片:

如圖所示我的雲端資料庫有7個表,User是使用者的登錄檔,由Bomb自動幫我們建立,因為我們是簡單的新聞資訊類APP,所以未使用。接下來有四個module表,分別對應我新聞內容的四個模組(我添加了title,publishTime,content三個欄位)。GameScore暫時未用。Question用於使用者提交問題反饋的表(我添加了Question 和 Reply兩個欄位)。

OK,對於一個簡單的新聞諮詢類APP這個後臺我想已經足夠了。

(五)連線後臺與前端

雖然這裡用不著,但我說些題外話,在iOS開發中,對於web service的訪問是重中之重,主要涉及以下三個方面:

  • Json資料格式的解析:iOS SDK自帶了最快的解析方式
  • 訪問web Service:推介使用第三方的開源庫(ASIHTTPRequest,AFNetworking,MKNetworkKit)
  • 定位服務與地圖應用

上面的看起來對於初學者有些恐怖,不過好訊息是Bomb提供了封裝好的SDK,使用自帶的BombQuery去查詢資料庫。現面給出我的一個例子:
(PS:在使用之前記得將應用祕鑰加入專案,方法見Bomb官網)

<code style="font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; font-size: 1em; padding: 0px; color: inherit; background-color: transparent;"> <span class="hljs-comment" style="color: rgb(136, 136, 136);">//請求資料</span>
    BmobQuery   *bquery = [BmobQuery queryWithClassName:module];
    [bquery selectKeys:@[<span class="hljs-string" style="color: rgb(136, 0, 0);">@"title"</span>,<span class="hljs-string" style="color: rgb(136, 0, 0);">@"publishTime"</span>]];
    [bquery setLimit:<span class="hljs-number" style="color: rgb(0, 136, 0);">15</span>];
    [bquery orderByDescending:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"createdAt"</span>];
    [bquery findObjectsInBackgroundWithBlock:^(<span class="hljs-built_in" style="font-weight: bold;">NSArray</span> *array, <span class="hljs-built_in" style="font-weight: bold;">NSError</span> *error) {
        <span class="hljs-keyword" style="font-weight: bold;">if</span>(!error){
            local = <span class="hljs-literal" style="color: rgb(0, 136, 0);">false</span>;(步驟<span class="hljs-number" style="color: rgb(0, 136, 0);">1</span>)
            myarray = array;(步驟<span class="hljs-number" style="color: rgb(0, 136, 0);">2</span>)
            [<span class="hljs-built_in" style="font-weight: bold;">NSThread</span> detachNewThreadSelector:<span class="hljs-keyword" style="font-weight: bold;">@selector</span>(saveContent:) toTarget:<span class="hljs-keyword" style="font-weight: bold;">self</span> withObject:array];(步驟<span class="hljs-number" style="color: rgb(0, 136, 0);">3</span>)
            [<span class="hljs-keyword" style="font-weight: bold;">self</span> performSelector:<span class="hljs-keyword" style="font-weight: bold;">@selector</span>(reloadData) withObject:<span class="hljs-literal" style="color: rgb(0, 136, 0);">nil</span> afterDelay:<span class="hljs-number" style="color: rgb(0, 136, 0);">0</span>];(步驟<span class="hljs-number" style="color: rgb(0, 136, 0);">4</span>)
        }<span class="hljs-keyword" style="font-weight: bold;">else</span>{
            [<span class="hljs-keyword" style="font-weight: bold;">self</span><span class="hljs-variable">.refreshControl</span> endRefreshing];
            UIAlertView *alertView = [[UIAlertView alloc]
                                      initWithTitle:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"友情提示"</span>
                                      message:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"無法獲取資料,請檢查網路(☆_☆)"</span>
                                      delegate:<span class="hljs-keyword" style="font-weight: bold;">self</span> cancelButtonTitle:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"關閉"</span>
                                      otherButtonTitles:<span class="hljs-literal" style="color: rgb(0, 136, 0);">nil</span>, <span class="hljs-literal" style="color: rgb(0, 136, 0);">nil</span>];
            [alertView show];
        }
    }];
</code>

上述例子查詢了資料庫的15條例子,採用非同步訪問的方式返回資料。發生錯誤時給出提示,如果成功,會有四步操作:

  • 步驟一我指定一個bool值,表示資料非本地儲存
  • 步驟二我將新載入的資料賦值給tableview繫結的資料
  • 步驟三開啟一個執行緒,將新載入的資料本地化
  • 步驟四跳轉到執行更新列表的方法

後面會詳細涉及到資料持久話操作,在這裡我們不必細究。
OK,我們使用Bomb自己提供的查詢方法訪問Bomb服務,成功的將應用與伺服器連線起來。

這是我訪問資料後展示新聞列表的頁面:

(六)基本的業務邏輯

OK,其實我們幾乎不涉及業務邏輯,因為我們只是把最新的新聞資料展示給使用者看,不過仍然有一些邏輯需要我們注意:

  • 使用者如何獲取最新的訊息: 下拉重新整理
  • 使用者想儲存一條新聞訊息到本地: 我的收藏
  • 使用者發現問題咋麼辦: 訊息反饋

解決方案:

  • iOS sdk自帶了下拉重新整理的解決方案refreshControl

示例程式碼:

<code style="font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; font-size: 1em; padding: 0px; color: inherit; background-color: transparent;"><span class="hljs-keyword" style="font-weight: bold;">self</span><span class="hljs-variable">.refreshControl</span> = [[UIRefreshControl alloc] init];
<span class="hljs-keyword" style="font-weight: bold;">self</span><span class="hljs-variable">.refreshControl</span><span class="hljs-variable">.backgroundColor</span> = [<span class="hljs-built_in" style="font-weight: bold;">UIColor</span> lightGrayColor];
<span class="hljs-keyword" style="font-weight: bold;">self</span><span class="hljs-variable">.refreshControl</span><span class="hljs-variable">.tintColor</span> = [<span class="hljs-built_in" style="font-weight: bold;">UIColor</span> whiteColor];
[<span class="hljs-keyword" style="font-weight: bold;">self</span><span class="hljs-variable">.refreshControl</span> addTarget:<span class="hljs-keyword" style="font-weight: bold;">self</span>
                        action:<span class="hljs-keyword" style="font-weight: bold;">@selector</span>(getLatestLoans)
              forControlEvents:UIControlEventValueChanged];
</code>

效果圖案:


(PS:以上程式碼和示例只是用於展示,不推薦直接使用,建議先找幾篇文章系統學習以下)

  • 使用CoreData儲存使用者想要儲存的資訊

在這裡我推薦兩篇教程,很簡明的講述了Core Data的基本使用,附連結:

再給出我處理儲存動作時執行的程式碼:

<code style="font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; font-size: 1em; padding: 0px; color: inherit; background-color: transparent;">- (<span class="hljs-keyword" style="font-weight: bold;">IBAction</span>)saveNews:(<span class="hljs-keyword" style="font-weight: bold;">id</span>)sender {
NSManagedObjectContext *managedObjectContext = [<span class="hljs-keyword" style="font-weight: bold;">self</span> managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"CollectionNews"</span>];
NSPredicate *predicate = [NSPredicate predicateWithFormat: <span class="hljs-string" style="color: rgb(136, 0, 0);">@"newsTitle == %@"</span>,titleName];
[fetchRequest setPredicate:predicate];
<span class="hljs-built_in" style="font-weight: bold;">NSArray</span> *news = [[managedObjectContext executeFetchRequest:fetchRequest error:<span class="hljs-literal" style="color: rgb(0, 136, 0);">nil</span>] mutableCopy];

    <span class="hljs-keyword" style="font-weight: bold;">if</span> (news<span class="hljs-variable">.count</span> == <span class="hljs-number" style="color: rgb(0, 136, 0);">0</span>) {
        NSManagedObject *newRecentlyNews = [NSEntityDescription insertNewObjectForEntityForName:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"CollectionNews"</span> inManagedObjectContext:managedObjectContext];
        [newRecentlyNews setValue:titleName forKey:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"newsTitle"</span>];
        [newRecentlyNews setValue:publishTime forKey:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"newsPublishTime"</span>];
        [newRecentlyNews setValue:newsContent<span class="hljs-variable">.text</span> forKey:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"newsContent"</span>];
        <span class="hljs-comment" style="color: rgb(136, 136, 136);">//[newRecentlyNews setValue:[obj objectForKey:@"playerName"] forKey:@"newsContent"];</span>
        <span class="hljs-built_in" style="font-weight: bold;">NSError</span> *error = <span class="hljs-literal" style="color: rgb(0, 136, 0);">nil</span>;
        <span class="hljs-keyword" style="font-weight: bold;">if</span> (![managedObjectContext save:&error]) {
            UIAlertView *alertView = [[UIAlertView alloc]
                                      initWithTitle:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"友情提示"</span>
                                      message:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"發生意外(☆_☆)"</span>
                                      delegate:<span class="hljs-keyword" style="font-weight: bold;">self</span> cancelButtonTitle:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"關閉"</span>
                                      otherButtonTitles:<span class="hljs-literal" style="color: rgb(0, 136, 0);">nil</span>, <span class="hljs-literal" style="color: rgb(0, 136, 0);">nil</span>];
            [alertView show];
        }<span class="hljs-keyword" style="font-weight: bold;">else</span>{
            UIAlertView *alertView = [[UIAlertView alloc]
                                      initWithTitle:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"友情提示"</span>
                                      message:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"儲存成功Y(^_^)Y"</span>
                                      delegate:<span class="hljs-keyword" style="font-weight: bold;">self</span> cancelButtonTitle:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"關閉"</span>
                                      otherButtonTitles:<span class="hljs-literal" style="color: rgb(0, 136, 0);">nil</span>, <span class="hljs-literal" style="color: rgb(0, 136, 0);">nil</span>];
            [alertView show];

        }
    }<span class="hljs-keyword" style="font-weight: bold;">else</span>{
        UIAlertView *alertView = [[UIAlertView alloc]
                                  initWithTitle:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"友情提示"</span>
                                  message:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"重複儲存哦,親(☆_☆)"</span>
                                  delegate:<span class="hljs-keyword" style="font-weight: bold;">self</span> cancelButtonTitle:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"關閉"</span>
                                  otherButtonTitles:<span class="hljs-literal" style="color: rgb(0, 136, 0);">nil</span>, <span class="hljs-literal" style="color: rgb(0, 136, 0);">nil</span>];
        [alertView show];
    }
}
</code>

首先查詢表中有無重複的資訊,如果有提示重複儲存,如果沒有則新建一個NSManageObject儲存資訊。

效果圖:



- 使用Bomb提供的服務提交問題到Question表

Bomb不僅給我提供了查詢的API,同樣提供了增刪改查一整套API,所以我們能使用Bomb提供的服務將使用者的問題進行提交,給出我的程式碼和執行效果:

<code style="font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; font-size: 1em; padding: 0px; color: inherit; background-color: transparent;">- (<span class="hljs-keyword" style="font-weight: bold;">IBAction</span>)submitQuestion:(<span class="hljs-keyword" style="font-weight: bold;">id</span>)sender {
    <span class="hljs-keyword" style="font-weight: bold;">if</span>(![_myQuestion<span class="hljs-variable">.text</span> isEqualToString:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"在此輸入:"</span>]){
        BmobObject *gameScore = [BmobObject objectWithClassName:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"Questions"</span>];
        [gameScore setObject:_myQuestion<span class="hljs-variable">.text</span> forKey:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"question"</span>];
        [gameScore saveInBackgroundWithResultBlock:^(<span class="hljs-built_in" style="font-weight: bold;">BOOL</span> isSuccessful, <span class="hljs-built_in" style="font-weight: bold;">NSError</span> *error) {
            <span class="hljs-comment" style="color: rgb(136, 136, 136);">//進行操作</span>
            <span class="hljs-keyword" style="font-weight: bold;">if</span>(error ==<span class="hljs-literal" style="color: rgb(0, 136, 0);">nil</span>){
                UIAlertView *alertView = [[UIAlertView alloc]
                                          initWithTitle:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"友情提示"</span>
                                          message:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"提交成功Y(^_^)Y"</span>
                                          delegate:<span class="hljs-keyword" style="font-weight: bold;">self</span> cancelButtonTitle:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"關閉"</span>
                                          otherButtonTitles:<span class="hljs-literal" style="color: rgb(0, 136, 0);">nil</span>, <span class="hljs-literal" style="color: rgb(0, 136, 0);">nil</span>];
                [alertView show];

            }<span class="hljs-keyword" style="font-weight: bold;">else</span>{
                UIAlertView *alertView = [[UIAlertView alloc]
                                          initWithTitle:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"友情提示"</span>
                                          message:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"提交失敗,請檢查網路(☆_☆)"</span>
                                          delegate:<span class="hljs-keyword" style="font-weight: bold;">self</span> cancelButtonTitle:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"關閉"</span>
                                          otherButtonTitles:<span class="hljs-literal" style="color: rgb(0, 136, 0);">nil</span>, <span class="hljs-literal" style="color: rgb(0, 136, 0);">nil</span>];
                [alertView show];

            }
        }];
    }<span class="hljs-keyword" style="font-weight: bold;">else</span>{

        UIAlertView *alertView = [[UIAlertView alloc]
                                  initWithTitle:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"友情提示"</span>
                                  message:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"請輸入有效文字(☆_☆)"</span>
                                  delegate:<span class="hljs-keyword" style="font-weight: bold;">self</span> cancelButtonTitle:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"關閉"</span>
                                  otherButtonTitles:<span class="hljs-literal" style="color: rgb(0, 136, 0);">nil</span>, <span class="hljs-literal" style="color: rgb(0, 136, 0);">nil</span>];
        [alertView show];

    }
}
</code>


(七)優化使用者體驗

我們本著主要功能去優化使用者的體驗,我想到以下兩點,其實也是最基本的兩點:

  • 當用戶進入詳細頁面後加載資料期間,如何顯示才能不讓使用者覺得突兀?
  • 使用者訪問過一次資料之後,再進入到此詳細頁面時難道要再訪問一次後臺嗎?

好伐,以上兩點應該是我們應用中使用者體驗感最強的兩點,下面給出我的解決思路:

  • 對於需要使用者等待的時間段內我會展示一個旋轉的進度條,告訴使用者我在載入資料,這個進度條可以使用iOS 提供的UIActivityIndicatorView類,只需要通過以下三行程式碼即可改善使用者體驗:

    <code style="font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; font-size: 1em; padding: 0px; color: inherit; background-color: transparent;"><span class="hljs-title" style="color: rgb(136, 0, 0); font-weight: bold;">[myprogress setHidesWhenStopped:YES]</span><span class="hljs-comment" style="color: rgb(136, 136, 136);">;//設定進度條停止時隱藏</span>
    <span class="hljs-title" style="color: rgb(136, 0, 0); font-weight: bold;">[myprogress startAnimating]</span><span class="hljs-comment" style="color: rgb(136, 136, 136);">;//設定進度條開始旋轉</span>
    <span class="hljs-title" style="color: rgb(136, 0, 0); font-weight: bold;">[myprogress stopAnimating]</span><span class="hljs-comment" style="color: rgb(136, 136, 136);">;//設定進度條停止旋轉</span>
    </code>

只需要在載入前設定進度條開始旋轉,非同步載入完資料後設置進度條停止旋轉即可。

  • 對於第二點,很自然就想到了資料持久化。當用戶訪問完某條新聞內容時,將資料內容本地化,下一次訪問時直接從本地獲取,無需延遲。同樣,我使用core data進行資料儲存。

程式碼如下:

<code style="font-family: Consolas, Menlo, Monaco, 'Courier New', monospace; font-size: 1em; padding: 0px; color: inherit; background-color: transparent;">-(<span class="hljs-built_in" style="font-weight: bold;">BOOL</span>)isLocalData{
    <span class="hljs-comment" style="color: rgb(136, 136, 136);">//NSLog(@"titlename%@",titleName);</span>
    NSManagedObjectContext *managedObjectContext = [<span class="hljs-keyword" style="font-weight: bold;">self</span> managedObjectContext];
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:myEntimty];
    NSPredicate *predicate = [NSPredicate predicateWithFormat: <span class="hljs-string" style="color: rgb(136, 0, 0);">@"newsTitle == %@"</span>,titleName];
    [fetchRequest setPredicate:predicate];

    <span class="hljs-built_in" style="font-weight: bold;">NSArray</span> *news = [[managedObjectContext executeFetchRequest:fetchRequest error:<span class="hljs-literal" style="color: rgb(0, 136, 0);">nil</span>] mutableCopy];
    <span class="hljs-keyword" style="font-weight: bold;">if</span>(news<span class="hljs-variable">.count</span> > <span class="hljs-number" style="color: rgb(0, 136, 0);">0</span>)
    {
        NSManagedObject *entiy = [news objectAtIndex:<span class="hljs-number" style="color: rgb(0, 136, 0);">0</span>];
        <span class="hljs-keyword" style="font-weight: bold;">if</span>(![entiy valueForKey:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"newsContent"</span>]){
            <span class="hljs-keyword" style="font-weight: bold;">return</span> <span class="hljs-literal" style="color: rgb(0, 136, 0);">false</span>;
        }<span class="hljs-keyword" style="font-weight: bold;">else</span>{
            [newsContent setText:[entiy valueForKey:<span class="hljs-string" style="color: rgb(136, 0, 0);">@"newsContent"</span>]];
            [<span class="hljs-keyword" style="font-weight: bold;">self</span> changeFrameSizeOfTextView];
            <span class="hljs-keyword" style="font-weight: bold;">return</span> <span class="hljs-literal" style="color: rgb(0, 136, 0);">true</span>;
        }
    }
    <span class="hljs-keyword" style="font-weight: bold;">return</span> <span class="hljs-literal" style="color: rgb(0, 136, 0);">false</span>;
}
</code>

上述程式碼在使用者進入詳細頁面後執行,檢測本地是否已經擁有此條新聞內容,如果已經存在,則從本地獲取,若不存在,則遠端獲取資料。(PS:由於我本地最多存取15條新聞,每次重新整理時會清空原先的資料,所以直接通過新聞標題查取,不推薦)

(八)豐富功能模組

OK,經過以上七步,基本已經搭建起一個簡單的新聞類APP了,但是我們的應用會不會太單調了呢?我們可以給自己的應用增加一些額外的模組,具體選擇什麼要視自己的情況。這裡因為是給學校做了一個就業資訊釋出的APP,所以添加了校車查詢,地圖顯示的富類模組。

(九)開源

歡迎各位大牛們指點一二 Y(^_^)Y

相關推薦

利用工具2開發完整新聞iOS app

題外話: 此篇文章以一個iOS新手的角度解釋一款新聞類iOS APP誕生的過程,詳細介紹在這過程中碰到的問題和我的解決思路。歡迎大家指正。 選單介面: 主介面: 詳細頁面: 關於我們頁面: 初期的想法 具體專案背景跳過,我們著重看如何實現一款新

君子性非異也 也(三) selenium+phantomjs java將淘寶網頁轉換成圖片支援下拉重新整理

1.本地安裝phantomjs,並且將bin加入環境變數path中2.新建java專案,selenium和phantomjs的maven如下,driver有很多種,比如chromedriver等等,phtomjs作為無頭瀏覽器做動態爬蟲專案挺爽的<dependency&

君子性非異也

一、Kafka簡介 Kafka是一個分散式的訊息佇列系統(Message Queue)。 kafka叢集有多個Broker伺服器組成,每個型別的訊息被定義為topic。 同一topic內部的訊息按照一定的key和演算法被分割槽(partition)儲存在不同的Broke

優秀程式設計師無他-

 運用一門程式設計語言對大多數程式設計師來說是小菜一碟,但是更上一層樓成為一名專家級的軟體開發者,恐怕目前還是大多數人的夢想。《程式設計師的思維修煉》一書中將程式設計師分為5個層級:新手,高階新手,勝任者,精通者,專家。根據作者的調查研究結果,在這5個層級中,大多數的程

君子性非異也 也() antlr4 處理json 詞法和文法 簡易版

學習了一下antlr4,之前都是自己寫token parser lexer,用工具真的方便,自己擼了個json文法 作為學習環境IDEA+antlr4外掛,JB是真的業界福音,好尷尬,到現在還沒買過正版。。。。程式設計師約架還用手寫parser,多撈哦。grammar JSO

Java學習----Jenkins(工具

  最近開始開發java專案,對於java這一套程式的釋出流程進行了梳理,主要用到工具就是Jenkins,那麼什麼是Jenkins呢?問題就出來了。   提到Jenkins,就不得不提到其所屬的範圍或

利用Python3開發工具 (介面背後的程式碼)

介面設計參照上一篇部落格(https://blog.csdn.net/hitguolu/article/details/82620681), 1、介面中的控制元件 2、如何給一個控制元件新增事件響應 3、介面的約束 4、訊號

win10裝Ubuntu18遇到的grub安裝失敗的問題(血淚史折磨了2

由於剛開始對知識的欠缺,我第一次在win10環境下安裝Ubuntu很easy的成功了,但是某一次不小小刪除了Ubuntu的桌面檔案後變成了伺服器端的Linux,我決定刪除整個Ubuntu重灌。結果第二次,卡了我2天的時間。我查了各種資料,網路上的解決辦法感覺很雜,在此特意總結

疑似伊朗黑客組織APT33再出手利用Shamoon V3發起新波攻擊

在上週,McAfee高階威脅研究小組釋出了一篇分析文章。在這篇文章中,該研究小組分析了針對中東和歐洲企業的新一波Shamoon“wiper(磁碟擦除惡意軟體)”攻擊活動,並討論了最新Shamoon攻擊活動與此前Shamoon攻擊活動的區別。其中最值得關注的是,最新版本的Shamoon(Shamoon

利用Python3開發工具(引言)

該部落格會詳細講解利用Python製作一款小工具的過程,後續文件將圍繞以下兩個方面: 環境安裝 分解開發 本文只是一個引言,將小工具的需求進行描述: ##背景 目前筆者所在專案的程式碼編譯及測試用例檢查,都是執行在兩個Linux伺服器中,而程式碼工程一般是

Android中帶你開發自動爆破簽名校驗工具kstools

系統服務 代理類 water 利用 技術分享 roo 解決 問題 dia 一、技術回顧 為了安全起見,一些應用會利用自身的簽名信息對應用做一層防護,為了防止應用被二次打包操作,在之前已經介紹了很多關於應用簽名校驗爆破的方法,一條基本原則不能忘:全局搜索"signature"

帶你開發給Apk中自己主動註入代碼工具icodetools(開鑿篇)

wid 事件 signed 類對象 soft .keystore ade ref 轉化 一、前言從這篇開始咋們開始一個全新的靜態方式逆向工具icodetools的實現過程。這個也是我自己第一次寫的個人認為比較實用的小工具,特別是在靜態方式逆向apk找關鍵點的時候。興許會

我想開發小程序怎樣才能快速上手並上線?

reac 原生 數據 web前端開發 業務開發 2017年 簡單 技術分享 lan 歡迎大家前往騰訊雲+社區,獲取更多騰訊海量技術實踐幹貨哦~ 2017 年 1 月 9 日,微信正式發布了小程序應用。之後,我們陸續收到了一些開發者留言和反饋。這裏面,問最多的就是: 我是做

進階學習如何無代碼設計美觀且實用的網站?

可用性測試 很好 product 收獲 遷移 落地 流行 最好的 人員 作為一門新興的邊緣性職業,網站設計既要從外觀上創意,又要適當結合圖形、版面及交互設計等相關原理,使得它成為一門獨特且令人神往的藝術。毫無疑問,好的設計能讓網站在諸多站點中脫穎而出,優秀的創意和表現方式能

開發一對一視頻社交APP成品源碼*付費社交平臺搭建為你定制

正在 社交 span normal 不同步 最新 cdd 基於 多個 開發一款一對一視頻社交APP,成品源碼*付費社交平臺搭建,為你定制互聯網時代,風雲變化,你永遠不知道下一秒將會有什麽事情發生日前,布谷鳥科技宣布現已推出多種直播系統,針對直播場景做了諸多優化,徹底解決了直

利用Python給自己寫不一樣的吃雞“外掛”!把把吃雞絕不封號

atp 有時 成功 alt 基礎入門 最大的 比較 比賽 我們 那麽我們就用python和R做數據分析來回答以下的靈魂發問? 首先來看下數據: 進群:125240963 即可獲取數十套PDF或者零基礎入門資料一套哦!

Vue+koa2開發全棧小程序(1.課程介紹+2.ES6入門)

... index 定義變量 打包 npm tps 管理系統 中心 概述 1.課程介紹 1.課程概述 1.做什麽? Vue+koa2開發一款全棧小程序 2.哪些功能? 個人中心、圖書列表、圖書詳情、圖書評論、個人評論列表 3.技術棧 小程序、Vue.js、koa2、koa-

從零到使用實時音視頻 SDK 一起開發 Zoom 吧

暴露 返回 詳細 ack 滿足 html 說了 scribe Once zoom(zoom.us) 是一款受到廣泛使用的在線會議軟件。相信各位一定在辦公、會議、聊天等各種場景下體驗或者使用過,作為一款成熟的商業軟件,zoom 提供了穩定的實時音視頻通話質量,以及白板、聊

開發即時通訊App從這幾步開始

聯系 多功能 數據監控 live 裁剪 ren vertica super 聯系人 歡迎大家前往騰訊雲+社區,獲取更多騰訊海量技術實踐幹貨哦~ 本文由騰訊雲視頻發表於雲+社區專欄 關註公眾號“騰訊雲視頻”,一鍵獲取 技術幹貨 | 優惠活動 | 視頻方案 “晚上去哪吃

zanePerfor 完整高效能高可用的前端效能監控系統不要錯過

HI!,你好,我是zane,zanePerfor是一款最近我開發的一個前端效能監控平臺,現在支援web瀏覽器端和微信小程式段。 我定義為一款完整,高效能,高可用的前端效能監控系統,這是未來會達到的目的,現今的架構也基本支援了高可用,高效能的部署。實際上還不夠,在很多地方還有優化的空間,我會持續的優化和升級。