照片牆增加功能-1

修改儲存方式,修改照片牆顯示方式,並將返回方式更改為單指往下拖曳圖片,最後增加自訂的過場動畫

--

上一篇

這次修改一些 photo wall 的缺點,讓照片牆看起來更順眼,以下為修改的東西:

  1. 將儲存的方式由原本的 userDefault 修改成存在外部的 plist 檔案
  2. 將 collection view 中的圖片顯示成與手機同寬且有自訂的高,讓照片的邊緣不會被裁切,並在圖片左下角增加拍照者的名字
  3. 調整 segue kind 種類
  4. 新增可以用手勢操作,並且將左上角的按扭重新作調整
  5. 修改觸發 segue 的方式,改成 perform Segue 以及 unwind segue
  6. 增加自訂的過場動畫

將儲存的方式由原本的 userDefault 修改成存在外部的 plist 檔案

userDefault 適用於儲存少量資料,一但資料量多起來,是有可能會造成閃退的,因此這裡我將儲存資料調整為存在檔案中,需要使用時再從檔案拿取。

首先使用 FileManager.default.urls 取得用戶檔案的路徑, .urls 是來找指定的陣列目錄,指定的方式是在 in 後面宣告。因為是回傳陣列, 所以要指定拿陣列中的哪一個位置, user domain 是在陣列第一欄, system domain 則是在最後一欄, 我們是要取 userDomain 因此使用 first 選第一欄位。( 也可以使用常見的 [0] 代表)

接著在目錄下使用 appendingPathComponent 新增檔案,命名為 PhotoDatas,且使用 appendingPathExtension 加入副檔名。(副檔名可以不用加入)

最後使用 write(to: path) 將檔案寫入指定的位置,記得在寫入之前要先將資料編譯成 Data 的型別。

存檔的function

取資料時到先前所存放之料的位置取就能拿到資料

讀檔的function

將 collection view 中的圖片顯示成與手機同寬且有自訂的高,讓照片的邊緣不會被裁切,並在圖片左下角增加拍照者的名字

這裡每張圖有自己的長與寬,因此我先從網路上取得高度與長度,算出來比例後套入手機的寬,就能取得照片的長度,最後在套入 collectionView(_: layout:sizeForItemAt) 就能將每個cell調整成與照片一樣的大小。

計算出照片的長寬

調整 segue kind 種類

Segue 總共有五種 Action 的方式: Show, Show Detail,Present Modally,Present as Popover 與 Custom。

> Show( push ):在非自訂的類型中唯一會堆疊 view 的總類, 意思是新的畫面會疊在舊的畫面之上。在用 navigation controller時,進入畫面由右向左,退出則是由左向右,並且會預設返回鈕在左上角。

> Show Detail:只是用在 UISplitViewController 內的 view controller 。不管有沒有 Navigation controller,只取代目前的 view,且不會提供返回鈕。

> Present Modally:有許多種呈現的方式,預定為由下往上彈出,同時沒有返回鈕。

>Present as Popver:目標 view 會以浮動窗呈現,點擊浮動窗以外的畫面目標 view 會消失,iphone 上則會佔滿整個螢幕。

> Custom:可以自訂並且按照自己想要的方式使用 segue 。

在上一篇的設計的 segue kind 欄位是使用 show 的方法,因此會自動出現返回的 navigation item,但是進入與返回的動畫是由右至左跟左至右,我想將它修改成上下的動畫,因此我在 storyboard 中調整為 Present Modally,並且在 Presentation 選擇 Full Screen 插入整個畫面。

從上圖可以看到最右邊的 controller 的 Navigation bar 在改成 present modally 後會消失(因為顯示的方式為變成卡片出現),而且又使用 Full Screen,會將整個畫面蓋住,就會把 navigation bar 一起蓋掉。

因為使用 Full Screen,所以要調整 Story board 拉畫面的順序,調整為下圖

用此方法就能看到 Navigation bar, 但是這樣在傳資料時就要先經過 Navigation Controller,再傳送到右邊的 controller。顯示畫面時也會先顯示 Navigation 才能顯示右邊的 controller。

這裡不直接用預設的 Present Modally,因為會出現空白,如下圖所示

很明顯地看到有黑色畫面出現,因此我使用自訂動畫

修改觸發 segue 的方式,改成 performSegue 以及 unwind Segue

上版本因為沒有使用到 performSegue,因此不用設定segue id ,只需要從 collection view cell 拉線到想要顯示的 controller 並選擇 show,就能夠使用 segue,若想要傳遞資料可以使用 prepare(for:segue) 。

這次為了嘗試其他 segue 的種類,這裡我選擇使用 perform segue 傳遞資料的方式,以下為程式碼。

performSegue 的使用時機是在需要從程式判斷去哪個畫面(或是否該去哪個畫面)時使用的所以 segue 需要加上 id 才能夠分辨出 segue,因此performSegue 的第一欄是 segue id,第二欄則是可以寫入要傳送的東西,我將選擇到的第幾個 cell 傳送出去,這樣其他 controller 才能知道選擇到了哪張照片。

在 prepare 的部分我先將 segue 的目的地設定為 navigation controller ( SelectedNavigationController),為了使用 navigation controller 裡面的 view controller 傳遞資料,所以宣告 .viewControllers ( first 代表 root view controller),最後將 navigation controller 中的 root view controller 轉換成SelectedPhotoViewController,代表傳遞資料給 SelectedPhotoViewControlle -r ,最後因為傳送出的資料格式為 int 所以將 sender 型態轉換成 int。

新增可以使用手勢操控,並且將左上角的按扭重新作調整

這裡我增加了兩種手勢,一種是使用一根手指對螢幕點一下,另一種是使用一根手指頭由上往下滑。在 swift 中使用 UIGestureRecognizer 可以監聽手勢,目前總共有六種手勢,這邊我使用 UITapGestureRecognizer 監聽點螢幕的動作以及用 UISwipeGestureRecognizer 監聽滑動的動作。

使用 #selector 代表使用 Objectc 的 selector,當使用了 object c 的 selector ,那麼後面的 function 也要是 object c,否則會出現 Argument of ‘#selector’ refers to instance method ‘swipe’ that is not exposed to Objective-C 的錯誤,這裡我將函示前面加上@objc,代表著可以直接讓 object c 使用。

增加自訂的過場動畫

在點選照片時的動畫是讓畫面往上,返回時則是往下。

網上時想呈現另一個畫面的關鍵是將想呈現的畫面先放在原本的畫面下方的位置,這樣一來同時將畫面往上移就能看到想要的畫面,往下的動畫也是同一個道理,最後把動畫設定在 segue 的 class 就能呈現出自己寫的動畫了。

往上的動畫
往下的動畫

成果:

Github

參考文件

取得文件路徑

取得檔案日期與時間

如何設定navigation bar 返回按鈕的標題

MVC架構

collection View cell大小調整

如何在collection view cell中使用perform Segue

如何重新設定 info.plist 位置

過場動畫

Segue 介紹

segue 使用 present modally 且 full screen 時 navigation controller 會消失的問題

傳遞資料

view controller

selector

--

--