2015年4月29日 星期三

Youtube API 資料收集簡易教學

Youtube API 資料收集簡易教學


取得某影片的詳細資訊
https://gdata.youtube.com/feeds/api/videos/videoid
videoid改成目標影片的id


取得播放清單的詳細資訊
https://gdata.youtube.com/feeds/api/playlists/playlistid
playlistid改成目標播放清單的id


取得某帳號的所有播放清單
https://gdata.youtube.com/feeds/api/users/userId/playlists
userId改成目標帳號的帳號名稱

取得某帳號所上傳的影片
https://gdata.youtube.com/feeds/api/users/userId/uploads
userId改成目標帳號的帳號名稱


網址後可加參數
https://developers.google.com/youtube/2.0/developers_guide_protocol_api_query_parameters
以下挑幾簡單說明及中文化

alt:輸出資料格式有atom, rss, json, json-in-script, jsonc可選,預設atom

fields:選擇要輸出的資料項目,預設全部輸出,用逗號分隔可複選,小括號選擇子項目
範例  fields=entry(title),entry(media:group(yt:videoid))

max-results:輸出清單項目最多幾項,預設25,最大50

start-index:從清單中哪一項開始,最小1,預設也是1

v:api版本,目前還在2版,不加也可以


總範例

https://gdata.youtube.com/feeds/api/users/nctuocw/playlists?v=2&max-results=50&start-index=1&fields=entry(title),entry(yt:playlistId),entry(yt:countHint)&alt=json

輸出nctuocw這個帳號的播放清單,使用第二版api,最多50項,從第一項開始,輸出entry(title),entry(yt:playlistId),entry(yt:countHint)這三項就好,格式json

資料來源: http://ldkrsi.blogspot.tw/2013/04/youtube-api.html

2015年4月27日 星期一

面試 iOS 工程師的一些題目

前言

自己參加過不少 iOS 的工作面試機會,前一陣子敝公司在徵 iOS 工程師,也讓我有這個機會去面試求職者。這段期間下來,也累積了不少面試題目,趁這個機會列出其中幾個題目跟各位交流。
我在面試求職者的時候,不會去問這份工作用不到的問題。例如演算法,我知道它很重要,但這份工作如果不太有機會要工程師寫演算法的東西,那就沒必要問。所以我在面試 iOS 工程師的時候,幾乎不會要求對方當場寫程式,我問的問題都比較偏向基礎知識與觀念,有些有正確答案,有些則是申論題。
以下題目不一定適用於你的公司現況或工作內容,使用前請自行斟酌
以下題目不一定適用於你的公司現況或工作內容,使用前請自行斟酌
以下題目不一定適用於你的公司現況或工作內容,使用前請自行斟酌
廢話不多說,以下就列出一些我曾經問過的幾個問題。

一般閒聊

這些問題真的就只是閒聊,一來放鬆彼此的心情,二來也可以了解一下求職者的相關背景與個性。
  • 怎麼學 iOS 開發的,有在關注哪些網站嗎?最近有看到什麼感興趣的技術或討論嗎?
  • 有在使用第三方套件嗎?如何管理第三方套件?
  • 開發 iOS 過程,有遇過什麼技術上的難題嗎?
  • 如何收集用戶 crash 紀錄,如何 debug
  • 如何追蹤使用者行為
  • 有在使用版本控制系統嗎?請說明你們的版本控制流程
  • 有在看 WWDC 嗎?對哪些 session 比較有印象,有什麼感想?
  • 有在寫測試嗎?有的話,請說明一下用哪套工具測試,還有測試什麼東西
  • 是否有特別喜歡某個 app,你認為這個 app 的架構大概是怎樣,你會如何設計這個 app?

基礎問題

個人覺得這些都是非常基礎的問題,任何一個有一年以上經驗的 iOS 開發者應該都要能回答這些問題。但讓我訝異的是,一些號稱有多年經驗的面試者,還是會答錯某些有正確答案的問題。
  • 會使用 XIB 跟 Storyboard 嗎?有辦法用程式碼刻畫面嗎?能否比較 XIB, Storyboard, Code 刻畫面的優劣?
  • 我們可以使用 [anObject doSomething] 讓某物件去做某件事?那如果 anObject = nil 會發生什麼事?
  • 假設 array 是一個 mutable array,那 [array addObject:nil] 會發生什麼事?
  • 假設 dic 是一個 mutable dictionary,那 dic[@"key"] = nil 會發生什麼事?dic[nil] = @"value" 會發生什麼事?
  • 什麼是 ARC,什麼是 MRC
  • ARC 是如何判斷何時要回收記憶體的?它跟 GC 有不一樣嗎?
  • new 跟 alloc init 有不一樣嗎?何時該用哪一種

進階問題

這裡的問題大多偏向觀念性,有少數是比較實作細節的東西。會問這些問題,是想知道面試者平時是否會思考該怎麼設計程式、是否有想過什麼時候用哪種解決方案比較適合,以及是否會去碰一些比較細節的東西。
  • 物件之間可以透過哪些方式溝通,什麼情況下該用哪一種
  • 如果要擴充一個 Class 的功能,又不能修改該 Class 的原始碼,有哪些方法可以辦到,其優缺點為何
  • 有用過 Category 嗎?請舉出一些用它的實際情況。可能會遇到哪些問題,要如何解決
  • 什麼是 Singleton,有什麼優缺點,請舉出使用它的時機
  • 什麼是 retain cycle,為何會發生,該怎麼解決
  • 直接呼叫 method 跟使用 performSelector: 有何不同,何時會使用後者
  • 有實作過 isEqual 嗎?要注意哪些地方
  • 什麼情況下無法使用 ARC
  • 知道什麼是 toll free bridging 嗎
  • 知道什麼是 shallow copy 跟 deep copy 嗎?如何 deep copy 一個 array
  • 說說對 MVC 的看法

2015年4月24日 星期五

『為什麼遊戲公司開發一個遊戲需要上億的資金?』錢都燒去哪了?

『為什麼遊戲公司開發一個遊戲需要上億的資金?』錢都燒去哪了?



 

在中國大陸的知識袋類型網站上,有個網友問了這麼問個問題。


『為什麼遊戲公司開發一個遊戲需要上億的資金?』

「剛剛看到一篇新聞最貴的遊戲,拿剛出不久的 GTA 相比遊戲開發成本就差不多用了 2.75 億美金,遊戲公司開發一個遊戲資金都是花在哪裡? 我只知道一個人力成本的費用」



看到這個問題,心中格外有感觸,近年來有些人來問我,說想做遊戲,準備了一百萬,想做一款 APP ,想做一款大作,想做一款心目中的有趣遊戲。

十萬夠不夠?一百萬夠不夠?一千萬夠不夠?在遊戲公司上班到底賺不賺錢?

玩家付了錢,買了遊戲,又從 DLC 掏空一次玩家的荷包,這些錢到底去哪了?

剛好有位在「育碧軟體(UBI SOFT)」工作的華人網友回覆了這個問題。

當然,UBI 搞的不是手遊,是電腦與家用主機的 AAA 級大作,底下資訊與手機遊戲市場生態自然大不相同,但舉一反三,仍是有參考價值的。

(至於他是不是真是 UBI 的員工,我也不清楚,如果以下資訊有誤,歡迎指正)
網友 Jiayang Yang 回覆如下,他現任 Warner Bros Games Montreal 的 Lead Level Designer,部份用字我修改為台灣用詞。

原回覆連結:為什麼遊戲公司開發一個遊戲需要上億的資金(知乎)


本人在遊戲行業幹了十幾年了,在國外一直做AAA遊戲,所以對這個話題還是有些瞭解的,其他答案都提及到了大概的成本問題,本人已這些年瞭解到的情況給大家聊一聊。

從給大家清理幾個誤解開始,逐步展開吧:


1. 開發一個遊戲需要上億的資金嗎?


一般情況不需要。注意,題主問的是開發,純開發的
話,絕大多數遊戲不可能有這麼高的成本。

2. 那GTA呢?


特例!而且之所以是特例,是因為是人就知道,這個遊戲穩賺,所以才可以砸這麼多錢。

3. 那為什麼GTA能花這麼多錢?


時間+人力。僅此而已。GTAV一共花了5年時間,團隊全部加一起上千人。這麼大的規模,只有搖滾之星搞得出來。用了這麼多人,用了這麼長時間,而且開發工具極其穩定,人們就是在不停的加內容,所以才可以有無數種細節。這些細節都是靠人+時間=錢,來堆出來的。

4. 那一般一個AAA遊戲的開發成本到底多少是正常的?


一般的情況,成本必須控制在 50M 以下,也就是五千萬。超過這個數,想要盈利就很困難了。那麼五千萬是什麼概念?就是一年半的小團隊 pre production,加上一年半的大團隊 production。整個 production 超過兩年,就風險很大了,因為花銷巨大。

5. 那麼為什麼超過五千萬就快跪了?


這裡要討論一下遊戲的盈利。(傳統遊戲啊,跟國內的網遊手游不搭邊。)一款遊戲售價 60 美金,這裡面真正到開發商手裡的錢,也就 20 美金(其餘全被零售商,發行,物流等等剝削去了),如果是發行商自己的工作室,可能會達到 25 美金。

那麼保守計算,一個五千萬成本的遊戲需要賣多少套可以打平?

答案:兩百五十萬套。

賣到這個數很難嗎?只能說不容易。現在的遊戲市場都在拼產品價值,只有做的好的前十名才有錢賺,其他的遊戲要麼將將打平,要麼虧到死。那為什麼大家都還在做AAA?因為前十名把整個市場的錢基本都賺走了,分到每一個遊戲,利潤比十年前大很多,所以大家都拼了命的做質量,要擠進前十。

這就是良性循環。


6. 剛才提到小團隊 pre production,大團隊 production,啥意思?


製作一款遊戲,最開始都是小團隊開發,這個規模一般也就 50 號人撐死了。

這些人就是要搞清楚遊戲是啥,怎麼玩,怎麼做,等等一系列問題,這個階段很痛苦,但也很有成就感。當證明可以實現這個遊戲了以後,才完整鋪開production,這時候才根據成本的預算來招人,確定規模等等。

一般的情況,製作一個 AAA 的遊戲,production 要至少 150 號人(育碧這種為了解決就業的公司不算在其中)。這些人需要將近兩年的時間,把遊戲的原型徹徹底底製作完成,當然加班是必不可少的。


7. 那具體人的成本是多少?

咱們大體算算:

Pre production:50(人數)x 80k(平均年薪,Senior 居多)x1.5(年數)=6M
Production:150(人數)x 75k(平均年薪,一些 Junior 拖後腿)x1.5(年數)=16.8M

光算工資的話,這就已經22.8M了。按照公司運轉核算,這個真實成本得工資乘以2,所以一共是(6+16.8)x 2= 45.7 M

8. 你這個數對嗎?


我不敢說完全正確,但八九不離十。本人在國外幹了這麼久,周圍人們多少錢工資我還是知道的,而且也確實看到過一些具體的數據,比方說,一個製作人(producer)的工資水平,其實平均也只有 75K 一年而已,我第一次看到也嚇一跳,本以為製作人都得十幾萬輕輕鬆鬆,後來接觸了很多製作人才發現,真沒那麼高。

各位請不要給我舉反例,反例隨口說說,遠不如我這麼多年看到的普羅大眾來的實在。謝謝。


9. 50M 就夠了?


其實不夠,還有一大塊沒算進來,就是市場推廣費用。

GTA之所以成本高也是遊戲市場費花的爽氣。但問題是,一般情況市場費用算在發行的成本裡面,不做為開發成本核算。

60 美金的售價裡,除了 20 美金給開發商,剩下的錢裡早就包含發行的那塊蛋糕了。而且,做為發行商,每年終歸需要一定的市場費用,這個費用今年給這個遊戲,明年給那個遊戲,沒見過哪個發行商一年到頭不發遊戲的,所以這筆費用終歸在那裡,逃不掉,所以不計算在開發費用,是很合理的。


暫時說這麼多吧。

有網友問道「剛入職的程式設計人員薪資高嗎?」
答:

首先程序員工資本來就高,遊戲行業北美的程序員一年十萬以上很正常。另外你說的是灣區,全世界還有其他任何地方能給程序員的工資高過灣區的嗎?最重要一點,軟件行業包括遊戲業,程序員是實打實的技術,核心價值,當然拿最高的工資。一個公司可以沒有製作人,但絕對不能沒有程序員。


網友問道:「何為 UBI  為為了解決就業的公司?」

答:


育碧的經營模式跟其他公司不太一樣。育碧在人員上向來是能養多少養多少,在蒙特利爾,光開發人員就兩千多,可是真正需要這麼多嗎?當然不需要,可之所以有這麼多,是因為育碧在幫助解決本地的就業,這樣就可以拿到政府豐厚的補貼,這些補貼相當於員工工資的60%,你要是老闆你也拚命招人,因為你的成本還是很低的,就算我暫時不需要這麼多人,可是一旦需要就可以拿來就用。於是育碧每個項目現在都好幾百號人在做。但絕大部分公司把員工數量控制的很低來降低成本和風險。育碧四百號人做的項目,放其他地方兩百以下一定可以做得出來,雖然時間可能會稍微長一些。

網友問道:「Director & Producer 的差異」

答:


Director 和 Producer是兩個完全不同的職業功能。正好有邀請我回答一個相關的問題,晚些時候你去看我對於另一題的答案就好。簡單說,Director是管製作和創意,Producer是管錢和進度。

資料來源: http://h9856.blogspot.tw/2015/03/blog-post.html

[IOS] NSFileManager 應用

iOS的沙盒机制,应用只能访问自己应用目录下的文件。iOS不像android,没有SD卡概念,不能直接访问图像、视频等内容。iOS应用产生的内容,如图像、文件、缓存内容等都必须存储在自己的沙盒内。默认情况下,每个沙盒含有3个文件夹:Documents, Library 和 tmp。Library包含Caches、Preferences目录。
             
上面的完整路径为:用户->资源库->Application Support->iPhone Simulator->6.1->Aplications
Documents:苹果建议将程序创建产生的文件以及应用浏览产生的文件数据保存在该目录下,iTunes备份和恢复的时候会包括此目录
Library:存储程序的默认设置或其它状态信息;
Library/Caches:存放缓存文件,保存应用的持久化数据,用于应用升级或者应用关闭后的数据保存,不会被itunes同步,所以为了减少同步的时间,可以考虑将一些比较大的文件而又不需要备份的文件放到这个目录下。
tmp:提供一个即时创建临时文件的地方,但不需要持久化,在应用关闭后,该目录下的数据将删除,也可能系统在程序不运行的时候清除。
               
APP  Sandbox
iOS怎么获取沙盒路径,怎么操作文件呢?下面给出答案。

获取应用沙盒根路径:

  1. -(void)dirHome{  
  2.     NSString *dirHome=NSHomeDirectory();      
  3.     NSLog(@"app_home: %@",dirHome);  
  4. }  


获取Documents目录路径:

  1. //获取Documents目录  
  2. -(NSString *)dirDoc{  
  3.     //[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];  
  4.     NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);  
  5.     NSString *documentsDirectory = [paths objectAtIndex:0];  
  6.     NSLog(@"app_home_doc: %@",documentsDirectory);  
  7.     return documentsDirectory;  
  8. }  


获取Library目录路径:

  1. //获取Library目录  
  2. -(void)dirLib{  
  3.     //[NSHomeDirectory() stringByAppendingPathComponent:@"Library"];  
  4.     NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);  
  5.     NSString *libraryDirectory = [paths objectAtIndex:0];  
  6.     NSLog(@"app_home_lib: %@",libraryDirectory);  
  7. }  


获取Cache目录路径:

  1. //获取Cache目录  
  2. -(void)dirCache{  
  3.     NSArray *cacPath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);  
  4.     NSString *cachePath = [cacPath objectAtIndex:0];  
  5.     NSLog(@"app_home_lib_cache: %@",cachePath);  
  6. }  

获取Tmp目录路径:

  1. //获取Tmp目录  
  2. -(void)dirTmp{  
  3.     //[NSHomeDirectory() stringByAppendingPathComponent:@"tmp"];  
  4.     NSString *tmpDirectory = NSTemporaryDirectory();  
  5.     NSLog(@"app_home_tmp: %@",tmpDirectory);  
  6. }  

创建文件夹:

  1. //创建文件夹  
  2. -(void *)createDir{  
  3.     NSString *documentsPath =[self dirDoc];  
  4.     NSFileManager *fileManager = [NSFileManager defaultManager];  
  5.     NSString *testDirectory = [documentsPath stringByAppendingPathComponent:@"test"];  
  6.     // 创建目录  
  7.     BOOL res=[fileManager createDirectoryAtPath:testDirectory withIntermediateDirectories:YES attributes:nil error:nil];  
  8.     if (res) {  
  9.         NSLog(@"文件夹创建成功");  
  10.     }else  
  11.         NSLog(@"文件夹创建失败");  
  12.  }  


创建文件

  1. //创建文件  
  2. -(void *)createFile{  
  3.     NSString *documentsPath =[self dirDoc];  
  4.     NSString *testDirectory = [documentsPath stringByAppendingPathComponent:@"test"];  
  5.     NSFileManager *fileManager = [NSFileManager defaultManager];  
  6.     NSString *testPath = [testDirectory stringByAppendingPathComponent:@"test.txt"];  
  7.     BOOL res=[fileManager createFileAtPath:testPath contents:nil attributes:nil];  
  8.     if (res) {  
  9.         NSLog(@"文件创建成功: %@" ,testPath);  
  10.     }else  
  11.         NSLog(@"文件创建失败");  
  12. }  


写数据到文件:

  1. //写文件  
  2. -(void)writeFile{  
  3.     NSString *documentsPath =[self dirDoc];  
  4.     NSString *testDirectory = [documentsPath stringByAppendingPathComponent:@"test"];  
  5.     NSString *testPath = [testDirectory stringByAppendingPathComponent:@"test.txt"];  
  6.     NSString *content=@"测试写入内容!";  
  7.     BOOL res=[content writeToFile:testPath atomically:YES encoding:NSUTF8StringEncoding error:nil];  
  8.     if (res) {  
  9.         NSLog(@"文件写入成功");  
  10.     }else  
  11.         NSLog(@"文件写入失败");  
  12. }  

读文件数据:

  1. //读文件  
  2. -(void)readFile{  
  3.     NSString *documentsPath =[self dirDoc];  
  4.     NSString *testDirectory = [documentsPath stringByAppendingPathComponent:@"test"];  
  5.     NSString *testPath = [testDirectory stringByAppendingPathComponent:@"test.txt"];  
  6. //    NSData *data = [NSData dataWithContentsOfFile:testPath];  
  7. //    NSLog(@"文件读取成功: %@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);  
  8.     NSString *content=[NSString stringWithContentsOfFile:testPath encoding:NSUTF8StringEncoding error:nil];  
  9.     NSLog(@"文件读取成功: %@",content);  
  10. }  

文件属性:

  1. //文件属性  
  2. -(void)fileAttriutes{  
  3.     NSString *documentsPath =[self dirDoc];  
  4.     NSString *testDirectory = [documentsPath stringByAppendingPathComponent:@"test"];  
  5.     NSFileManager *fileManager = [NSFileManager defaultManager];  
  6.     NSString *testPath = [testDirectory stringByAppendingPathComponent:@"test.txt"];  
  7.     NSDictionary *fileAttributes = [fileManager attributesOfItemAtPath:testPath error:nil];     
  8.     NSArray *keys;  
  9.     id key, value;  
  10.     keys = [fileAttributes allKeys];  
  11.     int count = [keys count];  
  12.     for (int i = 0; i < count; i++)  
  13.     {  
  14.         key = [keys objectAtIndex: i];  
  15.         value = [fileAttributes objectForKey: key];  
  16.         NSLog (@"Key: %@ for value: %@", key, value);  
  17.     }  
  18. }  

删除文件:

  
  1. //删除文件  
  2. -(void)deleteFile{  
  3.     NSString *documentsPath =[self dirDoc];  
  4.     NSString *testDirectory = [documentsPath stringByAppendingPathComponent:@"test"];  
  5.     NSFileManager *fileManager = [NSFileManager defaultManager];  
  6.     NSString *testPath = [testDirectory stringByAppendingPathComponent:@"test.txt"];     
  7.     BOOL res=[fileManager removeItemAtPath:testPath error:nil];  
  8.     if (res) {  
  9.         NSLog(@"文件删除成功");  
  10.     }else  
  11.         NSLog(@"文件删除失败");     
  12.     NSLog(@"文件是否存在: %@",[fileManager isExecutableFileAtPath:testPath]?@"YES":@"NO");  
  13. }  
資料來源: http://blog.csdn.net/xyz_lmn/article/details/8968213