2012年10月13日 星期六

iOS6 UI rotation issue

Apple does teach me a lesson that I should read the release note first!

If the app is navigation based, you may want to read this:
每個viewcontroller可支援的方向都能彈性調整 ,主要就是參照top-most viewcontroller (root viewcontroller)裡的設定

  • Autorotation is changing in iOS 6. In iOS 6, the shouldAutorotateToInterfaceOrientation: method of UIViewController is deprecated. In its place, you should use the supportedInterfaceOrientationsForWindow: and shouldAutorotate methods.
    簡單來說,
     shouldAutorotateToInterfaceOrientation在iOS6失效了,請改用supportedInterfaceOrientationsForWindow: 跟 shouldAutorotate:
    • More responsibility is moving to the app and the app delegate. Now, iOS containers (such as UINavigationController) do not consult their children to determine whether they should autorotate. By default, an app and a view controller’s supported interface orientations are set to UIInterfaceOrientationMaskAll for the iPad idiom and UIInterfaceOrientationMaskAllButUpsideDown for the iPhone idiom.
      控制方向旋轉的功能被提升到delegate來作管控,以往什麼self.navigationcontroller 沒辦法一招吃天下啦; 然後iPhone預設不支援頭上腳下的方向,iPad預設則是通通支援.
    • A view controller’s supported interface orientations can change over time—even an app’s supported interface orientations can change over time. The system asks the top-most full-screen view controller (typically the root view controller) for its supported interface orientations whenever the device rotates or whenever a view controller is presented with the full-screen modal presentation style. Moreover, the supported orientations are retrieved only if this view controller returns YES from its shouldAutorotate method. The system intersects the view controller’s supported orientations with the app’s supported orientations (as determined by the Info.plist file or the app delegate’s application:supportedInterfaceOrientationsForWindow: method) to determine whether to rotate.
      iOS6的autorotate方法是給top most view controller來做控管,可以在app delegate裡面透過application:supportedInterfaceOrientationsForWindow:來設定,或是寫在plist裡面;總之支援的方向可以隨時改變甚至是present view都沒問題,只要確定shouldAutorotate的回傳值是YES就對了.
    • The system determines whether an orientation is supported by intersecting the value returned by the app’s supportedInterfaceOrientationsForWindow: method with the value returned by the supportedInterfaceOrientations method of the top-most full-screen controller.
      系統決定app 支援哪些方向是取決於兩個method的交集: supportedInterfaceOrientationsForWindow:跟supportedInterfaceOrientations
    • The setStatusBarOrientation:animated: method is not deprecated outright. However, it now works only if the supportedInterfaceOrientations method of the top-most full-screen view controller returns 0. This puts the responsibility of ensuring that the status bar orientation is consistent into the hands of the caller.
      現在setStatusBarOrientation:animated:是由top-most view controller 來控制, 另外一個條件就是supportedInterfaceOrientations回傳值為0,這樣纔會work.
    • For compatibility, view controllers that still implement the shouldAutorotateToInterfaceOrientation: method do not get the new autorotation behaviors. (In other words, they do not fall back to using the app, app delegate, or Info.plist file to determine the supported orientations.) Instead, the shouldAutorotateToInterfaceOrientation: method is used to synthesize the information that would be returned by the supportedInterfaceOrientations method.
      由於兼容性的關係,所以一旦實作了shouldAutorotateToInterfaceOrientation:這個方法,那app就不會去管delegate或是plist裡面關於autorotation的設定;shouldAutorotateToInterfaceOrientation:這個方法可以視作為supportedInterfaceOrientations的getter&setter function
  • The willRotateToInterfaceOrientation:duration:willAnimateRotationToInterfaceOrientation:duration:, and didRotateFromInterfaceOrientation: methods are no longer called on any view controller that makes a full-screen presentation over itself—for example, by calling presentViewController:animated:completion:.
    這裡提到willRotateToInterfaceOrientation:duration:willAnimateRotationToInterfaceOrientation:duration:didRotateFromInterfaceOrientation:這三個function都不會再有event觸發,所以當present一個viewcontroller之後不能依靠這三個function來更新或是調整layout而是該改用下面的這個viewWillLayoutSubviews
    • You should make sure that your apps are not using these methods to manage the layout of any subviews. Instead, they should use the view controller’s viewWillLayoutSubviews method and adjust the layout using the view’s bounds rectangle.

前面廢話完了,回歸正題
如果app需要用到navigation controller的話:
1. 先check app delegate

1
2
urNavigationCtrl = [[UINavigationController alloc] initWithRootViewController:viewController];
[window addSubview:urNavigationCtrl.view];

改成

1
2
3
urNavigationCtrl = [[UINavigationController alloc] init];
[urNavigationCtrl pushViewController:firstViewCtrl animated:NO];
self.window.rootViewController = urNavigationCtrl;

2. 參照aprato在stackoverflow的解答, 我們需要Category來解決使用加了navigation controller之後的後遺症.在第一個view的.m裡面加上這段code


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
@implementation UINavigationController (Rotation_IOS6)

-(BOOL)shouldAutorotate
{
    return [[self.viewControllers lastObject] shouldAutorotate];
}

-(NSUInteger)supportedInterfaceOrientations
{
    return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}

@end

3. 然後在每一個需要overwrite的頁面重新define自己想要的行為, for example:

1
2
3
4
5
6
7
- (BOOL)shouldAutorotate {
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

資料來源:9to5macdisanji.netroostersoftstudios


2012年10月1日 星期一

MJPEG Streaming Issue on iOS6

Well done Apple, I got many complains from users that their app will crash after upgrade to iOS6.

After I checked the log, there are all error messages from CFNetwork.
Seems the internal error will lead to run out of memory!

CFNetwork internal error (0xc01a:/SourceCache/CFNetwork_Sim/CFNetwork-609/Connection/URLConnectionClient.cpp:1145)

What's more, only particular ip camera will have this issue....@#$%
Can't wait to console worldwide users, that I am using workaround:

Due to mjpeg stream is consist of continuous jpeg images.
Thus I using snapshot cgi rather than mjpeg stream cgi.

Will keep digging the root cause, and will update if have any news~ sigh

update:2012/10/05
Seems the boundary format is invalid!
Because the vendor defines boundary=--video boundary-- in the header
But comes out --video boundary--
It should be ----video boundary--

Here is the wiki definition of MIME multipart message

update:2012/10/13
Fix the boundary format issue, but still have the same problem >"<
Back to the origin...

update:2012/10/18

Bingo! We got a new f/w and fix another format issue~
The CFNetwork error never happen anymore, but I believe there are still other traps will cause the error! The fault tolerance of CFNetwork is too weak!!


Right Format






















Wrong Format

2012年8月23日 星期四

讓空白的UITableViewCell消失吧~

有的時候總會小失落自已的app怎麼就是少人家一點什麼...
阿~你看看左邊醜陋的Table一眼就知道是系統預設樣式...



















明明只有三筆資料為什麼下面還有一條條的分隔線

想看看精緻版本嗎?右邊接著看下去...
右邊的如果你仔細去看他的原始碼,他還區分成最上面第一個cell,中間的,跟最下面的cell

換句話說,他取消了原本格線的風格,透過"美術"方式來達成
如果今天沒有"美術"的奧援要怎麼辦呢?

只有一個section時:
1
2
3
4
5
6
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
    if ([self numberOfSectionsInTableView:tableView] == (section + 1)){
        return [[UIView new] autorelease];
    }       
    return nil;
}


有一個以上的section可以用:
1
2
3
4
5
6
7
8
- (float)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
     // This will create a "invisible" footer
     return 0.01f;
 }
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
    // To "clear" the footer view
    return [[UIView new] autorelease];
}

完成圖如下~





















資料來源: stackoverflow & cocoawithlove

2014/07/04 UPDATE:

這也是一個不錯的方法.
1
tableView.tableFooterView = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];

2012年8月12日 星期日

宿霧 - 充滿歡笑聲與驚奇的旅程 Day3


早上4 5點起床去追逐海豚,去巴里卡薩浮潛
有被水母稍微螫到,海底的景色跟魚群好像還好
沒有到令人wow~的驚嘆地步

中午在薄荷島蜜蜂農場用餐
海景餐廳 + 有機料理
連冰淇淋都很好吃;)

不解歷史風情的我們,或盤踞或簇擁
開心的一群人好像把這嚴肅的場景給化解了

 繁華落盡,洗盡鉛華的華人餐廳
從挑高兩層樓的大廳
到一旁比人高的雕像,花瓶
水晶燈,雕梁畫棟無不凸顯當年盛況一時的模樣
長長的走廊盡頭剩下霓虹燈兀自閃爍着ㄡ...


回到宿霧的飯店發現有鸚鵡有老虎跟蟒蛇可以合照
這應該可以羨煞我女朋友了XD


oh ~ 還有Day 4,給我再整理一下 :P

2012年8月11日 星期六

宿霧 - 充滿歡笑聲與驚奇的旅程 Day2

- 晨景 -
早上醒來從20幾樓的高度遠眺,
真的會讓人一整個精神振奮吶~
連自助式早餐也是豐盛得讓人眼睛為之一亮.
遠處貨船慢慢的移動著,天空有白雲緩緩的飄著,
碧綠的山丘有陽光暖暖的灑著,這季節適合讓整顆心在宿霧盪漾著.


- 航向薄荷 -
很幸運的有藍天,白雲之外,還有平靜的海面及爽朗的海風
大家在甲板上嬉笑拍照好不愜意,
不過後來可能是惹得太陽嫉妒了,越來越曬...
除了我來回全程都座在船尾甲板吹風,大家還是選擇在船艙內休息
Tips: 全程2個小時
不是什麼偉大的航道,但是仍有美麗的水花跟漣漪
甲板上可以發呆也可以參透很多人生哲理 ;)

- 靠岸 -
一台寫著"仙台空港"的退休巴士跟太陽一樣熱情的等著我們,
噢~巴士身後的碧綠海水也吸引了我們不少的目光.

街上,一種更鄉村的樣貌在我眼前展開.
一台台迷你逗趣的巴士?計程車?
大部分的人好奇的望向我們,我也好奇的用相機記錄著這一切.

- 遊河 -
在竹筏船上用餐真的還挺新鮮的,
別太在意過鹹的食物,品嚐個香甜的水果,試試不同風味的甜點,
再好好的享受民謠歌手的現場演唱,心情特好阿~
竹簾隨風搖曳著,伴著粗獷而閒逸的歌聲,一點都不輸威尼斯的遊河阿~

Tips: 半途會停靠個原住民小島,讓遊客可以拍照留念.
有牽蜥蜴,背弓箭的;
有嚇人的噴火跟動感小女孩,一次拍照都是20 peso
多鼓勵他們保留那最單純的一面吧~

Balik sa Bohol! Balik!
輕快的歌聲中,訴說著薄荷島不捨遊人離開,
並期待人們再回來的淡淡惆悵.

- 巧克力山 -
對不起,安安靜靜的眼鏡猴真的躲得很好
不是我的iPhone能拍出來的
我還打趣的跟同事說,該不會都是玩偶放在樹上阿.

巧克力山可說是百聞不如一見,
你會讚嘆廣闊的景象以及大自然鬼斧神工的奧妙.

- 沙灘 烤肉 卡拉OK -
薄荷島的住宿,有人嫌棄,我倒是覺得還算滿ok的.
可能就像墾丁度假的小木屋一樣,算不上華麗但是中庭游泳池,
棕櫚打上造景燈,海灘上的躺椅,
嗯~放寬心的迎接這一切吧~

晚上也是自助式的buffet,
大家在沙灘上載歌載舞好不歡樂.
嗯~一開始真的覺得好"台式"的風格阿,
但是後來大家也玩開了,好像也挺OK的.
 躲開人群,在晚餐結束後,
逃離沙灘上的投射燈,雖然眼前漆黑難辨,
但是頭頂的點點星光可是會震攝人心的.

Good night, Bohol!
明天早起追海豚去~

2012年8月10日 星期五

宿霧 - 充滿歡笑聲與驚奇的旅程 Day1

原先,不怎麼看好的宿霧之旅
在老天的冥冥安排之下,完全顛覆了我的預期~

早上4.30出門,6.00機場集合,8.00的飛機
第一眼遇到領隊就覺得他很有喜感
大家在小飛機前拍照後就起飛前往 - 宿霧

由於團體旅遊,座位安排一般都不是太好
我勉強從夾縫中拍了幾張

- 機場 -
離開飛機上的舒適小空間,一踏到地面
嗯~微熱的空氣迅速包圍上來
機場大廳不算明亮,簡單的兩層樓跟水泥外牆,
走廊上還有穿著制服的航廈人員隔著太陽眼鏡望著我們這邊.

一台台吐著黑煙的遊覽車,伴著些許塵土飛揚
似乎訴說著當年驍勇的樣子

- 午後 比佛利山莊 -
小莊,是我們在地的導遊,長得有點像洪金寶XD
教著幾句簡單菲律賓話,也介紹了宿霧的人文地理
中餐有享用到極力推薦的"芒果冰沙" (80peso)

Tips: 去宿霧換錢的部份如果能先換一兩張小鈔,那會方便一些.
沒有也沒關係,反正會有到大賣場的機會
路邊小販的開水,或是餐廳的冰沙就忍耐一下囉~

阿~豆點般的雨珠在我們下車後越下越大
謝謝Summer夫婦的雨傘讓我免於穿上黏呼呼又不透氣的雨衣.
午後一場雨,空氣還是有點悶,我們依然循階而上.
可能是台灣的廟宇都太過於富麗堂皇了,
定光寶殿 倒是透露著樸實的氣息.
倚欄遠望,附近是蓊鬱的樹林以及一戶戶有錢人家
跟小莊分析著幾戶人家用的磁磚,屋頂貼著的瓦,挺有意思的


其實宿霧市區的景點不算遠,
好像沒有一些網友說的那麼恐怖,
可能是非假日的緣故吧~
路上經過一條水溝,不深但飄著一些垃圾.
一個光著屁股的小孩似乎正接受著岸上老爸的指令,
在水裡撈著些什麼...景象有點令人鼻酸


- 聖嬰大教堂 -
受過西班牙殖民統治的影響,
這古老的建築散發著濃濃的西方色彩.
教堂前有很多婆婆拿著蠟燭跳著舞為人祝念,
教堂裡更是聚集著虔誠的信徒在禱告.
大門透進了些許光線,門上的肖像活靈活現了起來.


 - Crown Regency -
時間沒有讓我們能停留太久,
我們下榻飯店是宿霧最高的建築 - 皇冠麗晶

Tips: 出發前旅行社提供的旅遊須知裡面,就醜話說在前頭,
沒想到剛到宿霧,導遊就不斷的為我們打預防針:
1. 這裡食物比較偏鹹,吃粗飽就好,重點在觀光,大家請見諒.
2. 飯店有六星級外觀,五星級大廳,四星級房間,
三星級設備,二星級服務...大家多包涵
3. 這裡的人生活悠閒,步調較"慢",請大家忍耐.

不過說真的,打過預防針有差.
感覺一切都還滿不錯的 (中式餐廳真的很鹹)
霓虹燈管爬往了天際,天際的那端或許是宿霧人民的希望吧


 小莊有特別提到飯店有靶場可以自費參加 (兩人3000 peso)
我跟朋友興沖沖的放了行李就直奔靶場.
碰~碰~ 體驗了當男子漢的過程挺過癮的,
旁邊還有美女教練,這怎麼會瞄的準呢? XD


呼~要早點睡了,明個兒要早起去"薄荷島"了!
Good night, Cebu.


2012年8月7日 星期二

山獅 & 消失的網站分享功能

昨天才意外發現升上osx 10.8之後 web sharing的功能被默默移除了
不過Mountain Lion還是有內建Apache的,只是沒有以前這麼方便設置頁面了

我先找到了Clickontyler 他提供了一個系統設定的捷徑可以去開關Apache server

















但是...
問題好像還是沒有解決,因為index網頁開起來就只秀著:





充其量不過是Apache有起來而已 ~"~

Mac store上面有一套Simple HTTP Server可以解決這個問題
1. 安裝完,執行選定要做web sharing的資料夾即可(預設應該都是"網站"/"Sites"這個資料夾)
2. 複製路徑就可以使用了!!










如果老手一點,直接修改一下config更快啦!!
1. 到/etc/apache2/users/(yourname).conf底下

2. 確認自己使用者名稱有修改到
< Directory "/Users/(yourname)/Sites/">
     Options Indexes MultiViews
     AllowOverride All
     Order allow,deny
     Allow from all
</ Directory>

3. apachectl restart 一下就好了,localhost/~(yourname)/index.html 趕快看一下


















熟悉的身影又回來了,真好
我是菜鳥,小小心得希望有幫到需要幫助的人 ;)

2012年2月23日 星期四

OS X 10.7.3 submit app時可能遇到的狀況


今天遇到另一個比較特別的問題,
害我在submit過程被檔了下來...

iPhone/iPod Touch: Icon.png: icon dimensions (0 x 0) don't meet the size requirements. The icon file must be 57x57 pixels, in .png format


原本還以為是icon的問題有缺漏,再看一下卻是好端端的.
參考iPhone Dev SDK論壇上的討論有提到解決之道

作法一: 到project > build setting > 尋找compress PNG files 並且設定成NO

但是Duncan C大大有特別指出,這樣的作法不是頂好,會讓app變肥

又這是最近Lion升級到10.7.3才有的問題
作法二: 可以到iTunes connect > Manage Applications > Download Application Loader
            下載ApplicationLoader_2.5.1


我偷懶,所以我選第一個作法就丟上去了XD  哈~大家還是用第二個方法吧!

2012年2月20日 星期一

噓~可以讓NSLog安靜一點嗎?

NSLog是開發iOS常用的好夥伴.
但是真的要release給QA或是NSLog量一大的時候,
系統整個performance完全會被這個怪獸給生吞 QQ

所以除了設定debug level來控制吐log的量以外,
可以在(projectname)_Prefix.pch裡面加個幾行code.
保證NSLog在release mode安安靜靜 :)


#ifndef __OPTIMIZE__
#    define NSLog(...) NSLog(__VA_ARGS__)
#else
#    define NSLog(...) {}
#endif

其實差異就在,release mode會將project設定成__OPTIMIZE__,
而debug mode並沒有這樣的設定...

資料來源:
http://iamcam.wordpress.com/2011/07/31/quiet-nslog-in-release-builds/

內容回應