軟件介紹
AVHider (oh NO) FileHider是一款將你的文件夾或文件隱藏起來的效率軟件,適用于macOS X 10.10及以后的macOS版本迁匠。百度網(wǎng)盤下載地址,歡迎大家試用剩瓶,并提出改進(jìn)建議驹溃!有開發(fā)能力的朋友也可以去Github將項(xiàng)目fork后contribute您的code。
Specially thanks to
unfamous Designer Joseph, who designed the exquisite logo for this Application!
軟件的使用也非常簡單延曙,基本可以實(shí)現(xiàn)文件/文件夾的可見/不可見一鍵切換豌鹤,錄了一個(gè)gif動(dòng)畫。
開發(fā)初衷
開發(fā)這款軟件的初衷是將xxx.mp4/xxx.avi/xxx.mkv在白天藏起來枝缔,免得被其他人發(fā)現(xiàn)布疙。 在Apple store上發(fā)現(xiàn)了一款類似的軟件,售價(jià)163元愿卸,而且賣的不錯(cuò)灵临。作為一個(gè)工程師,我是不愿意掏這份冤枉錢的趴荸,因?yàn)槲矣X得這東西一天內(nèi)可以搞出來儒溉,于是就花了一晚上做出了功能類似的軟件FileHider(認(rèn)真臉)。
與Secret Folder不同的地方在于它的TableView中有兩列发钝,而我認(rèn)為顯示當(dāng)前文件可見/不可見的列跟右邊的NSSegmentedControl信息重復(fù)了睁搭,因此我就除去了該列。
還有一點(diǎn)不同是Secret Folder設(shè)置了Require Password這個(gè)選項(xiàng)笼平,這個(gè)我覺得可以不加园骆,因?yàn)槿绻粋€(gè)人在用戶不在的時(shí)候能夠進(jìn)入到系統(tǒng)中,那么user的密碼也是多余的寓调,F(xiàn)ileHider的目的是對(duì)有機(jī)會(huì)看到你電腦屏幕卻沒有機(jī)會(huì)操作你電腦的人隱藏文件锌唾。
起初我還想在用戶切換文件可見性的時(shí)候發(fā)送一個(gè)Notification,但是覺得過度設(shè)計(jì)了夺英,因?yàn)檫@些通知如果不手動(dòng)刪除晌涕,將會(huì)在通知中心保留下來,這顯然會(huì)增加別人知道有文件隱藏起來的可能性余黎。
開發(fā)過程
界面部分
界面部分完全模仿了Secret Folder的布局,是一個(gè)single-Page的應(yīng)用惧财,依然采用了StoryBoard構(gòu)造界面扭仁。
左右分為垂直的兩欄垮衷,使用了NSSplitView,并調(diào)整左右兩欄的大小比例乖坠,左邊顯示文件列表和對(duì)列表的增加/刪除按鈕;右邊是文件的詳細(xì)信息與文件隱藏/可見之間切換的NSSegmentedControl仰迁。對(duì)各個(gè)組件定好布局甸昏,確保在窗口resize后依然保持著相對(duì)較好的樣式。
TableView部分
文件列表是放到TableView中進(jìn)行顯示的徐许,它也是本應(yīng)用的核心部分筒扒。默認(rèn)的TableView Cell高度只有17px绊寻,每個(gè)Cell要塞進(jìn)去一個(gè)文件縮略圖icon和文件名悬秉,顯然過于小了,因此需要定制Cell村缸。在本項(xiàng)目中武氓,我將Cell設(shè)置為了30px梯皿,其中文件縮略圖為24 X 24 px,我覺得大小是比較合適的县恕。
一個(gè)TableView要想成功顯示需要知道兩件事:1.顯示幾行忠烛、2.每行顯示什么。和其他應(yīng)用一樣冤议,驅(qū)動(dòng)這個(gè)TableView的是一個(gè)數(shù)組师坎,filesList : [URL]。請(qǐng)注意這里是一個(gè)URL的數(shù)組胯陋,文件路徑的URL都是定義為file://+文件路徑這種格式的。URL在Swift中有相當(dāng)多的方法寿弱,方便拿到文件名按灶、路徑名、根據(jù)完整路徑拿到對(duì)應(yīng)文件的縮略圖鸯旁、文件的detail信息等等。具體的使用可以參考官方API文檔艇挨。
數(shù)據(jù)持久化
對(duì)于本應(yīng)用,用戶對(duì)某個(gè)文件的操作并不是一次性隱藏就完事了的势就,它需要保留恢復(fù)為可見的權(quán)力脉漏,顯然讓用戶記住哪些文件被隱藏、甚至隱藏在哪個(gè)路徑下是很不現(xiàn)實(shí)的舅锄,因此需要數(shù)據(jù)持久化司忱,保證用戶下次打開應(yīng)用的時(shí)候可以知道哪些文件是有過隱藏歷史的。因?yàn)橛羞^前科的文件很可能需要二次隱藏坦仍。
數(shù)據(jù)持久化的選擇很多繁扎,最典型的有比較重的core data和比較輕量級(jí)的userDefaults。由于文件列表的路徑通常不會(huì)很長锻离,因此我選用了相對(duì)輕量級(jí)的userDefaults汽纠。
在使用userDefaults存儲(chǔ)前面提到的URL類型的filesList數(shù)組的時(shí)候,我發(fā)現(xiàn)會(huì)報(bào)一個(gè)錯(cuò)誤虱朵,Attempt to set a non-property-list object as an NSUserDefaults。 后面在網(wǎng)上發(fā)現(xiàn)了一些solution絮宁,主要的原因是NSUserDefaults只支持NSArray, NSDictionary, NSString, NSData, NSNumber, 和 NSDate的數(shù)據(jù)類型服协,對(duì)于URL這種類型,網(wǎng)上大多數(shù)的solution都是建議將數(shù)組編碼為NSData窘游,然后進(jìn)行存儲(chǔ)。我考慮到URL和String之間的互轉(zhuǎn)比較方便贪嫂,因此我將其轉(zhuǎn)換為了string類型的數(shù)組進(jìn)行存儲(chǔ)艾蓝。
// String -> URL
override func viewDidLoad() {
let defaults = UserDefaults.standard
if let filesListFromUserDefaults = defaults.array(forKey: "filesPath"){
var tmpFilePath : [String] = filesListFromUserDefaults as! [String]
for str in tmpFilePath{
self.filesList.append(URL(string: str)!)
}
}
}
// URL -> String
override func viewWillDisappear() {
let defaults = UserDefaults.standard
var array : [String] = []
for url in filesList{
array.append(url.absoluteString)
}
defaults.set(array, forKey: "filesPath")
}
URL與String數(shù)組之間的互轉(zhuǎn)
轉(zhuǎn)換的時(shí)機(jī)很重要,這會(huì)提高應(yīng)用的性能亮靴。String->URL這個(gè)方向僅在應(yīng)用打開時(shí)敌厘,view加載完畢后進(jìn)行朽合;而URL->String這個(gè)方向是在應(yīng)用關(guān)閉后,view消失的時(shí)候觸發(fā)一次宪彩。
文件列表的增加
文件的增加目前是靠比較簡單的NSOpenPanel來實(shí)現(xiàn)的讲婚,顯然這很不Mac,后面需要做的是drag-and-drop活合,一種更為優(yōu)雅的solution物赶。
@IBAction func selectFile(_ sender: Any) {
let openPanel = NSOpenPanel()
openPanel.message = "Please select file to Hide"
openPanel.canChooseDirectories = true
// openPanel.allowsMultipleSelection = true
openPanel.beginSheetModal(for: view.window!, completionHandler: {(result) in
if result == NSModalResponseOK{
self.selectedFolder = openPanel.url!
}
})
}
文件列表的刪除
文件列表的刪除依然是對(duì)上文提到的filesList進(jìn)行操作,通過tableviewDelegate中的tableViewSelectionDidChange方法得到需要?jiǎng)h除的元素index告嘲。需要注意的是奖地,需要增加判斷,確保當(dāng)前有元素被選中仰楚。(如果沒有元素被選中,index值會(huì)是-1缸血,這很可能引起應(yīng)用的崩潰)
無論是文件列表的增加還是刪除捎泻,都需要調(diào)用tableview.reloadData()方法對(duì)視圖進(jìn)行更新。
隱藏和非隱藏的實(shí)現(xiàn)
Unix系統(tǒng)中實(shí)現(xiàn)一個(gè)文件隱藏的方法很多笆豁,甚至可以給該文件進(jìn)行加密。我能想到的最簡單的方法是在原文件前面加一個(gè).煞赢,并用mv xxx.mp4 .xxx.mp4將該文件就地在原路徑下進(jìn)行隱藏哄孤。這也符合了本軟件的設(shè)計(jì)初衷,將文件從有機(jī)會(huì)從你電腦邊路過凝危,但卻沒有機(jī)會(huì)真正操作你電腦的人隱藏晨逝。
模擬console執(zhí)行命令,是通過Process()來完成的支鸡。這里有一些坑趁窃,不幸的被我全踩了。
第一個(gè)坑是普通文件和文件夾的URL是不同的醒陆,文件夾是以/結(jié)尾的,而普通文件則不是检碗,為了得到path和文件名码邻,我調(diào)用了String.components(separatedBy: “/“)方法,那么文件夾的文件名就存在了方法得到數(shù)組的倒數(shù)第二項(xiàng)中怕犁;而其他普通文件的文件名存在了數(shù)組的倒數(shù)第一項(xiàng)中。
第二個(gè)是當(dāng)用戶不是第一次打開應(yīng)用時(shí)戈轿,執(zhí)行mv的參數(shù)設(shè)置方式需要分四種情況討論阵子,這也是前面為了應(yīng)用的效率,不及時(shí)update fileList挖下的坑挠进。果然凡事都是有兩面性的~
致謝领突、結(jié)束語
首先感謝非著名設(shè)計(jì)師Joseph給我提供的精美logo,感謝Secret Folder君旦,讓我有了靈感和動(dòng)力去做一個(gè)類似的軟件金砍。
周五有幸聆聽了公司CTO的演講,一個(gè)工程師的日常捞魁。我不禁聯(lián)想到了我自己离咐,我因?yàn)樵浖▋r(jià)過高,做過Syngery的替代品mouseSync昆著、Manico的替代品Manico-substitution术陶、Re Desktop的替代品HideDesktop,這也許就是我作為一個(gè)工程師的日常吧接谨。
Drag-and-drop是更為優(yōu)雅的文件與應(yīng)用的交互方式塘匣,我將于近期抽空集成進(jìn)應(yīng)用中,屆時(shí)再見扫夜!