顯示具有 教學 標籤的文章。 顯示所有文章
顯示具有 教學 標籤的文章。 顯示所有文章

2014-11-14

Xcode 6 在模擬器 iPhone 5 + iOS 7 的版面上下黑邊

如果您在 Xcode 6 發現了模擬器以 iPhone 5 執行 iOS 7 時,是以 320x480 的版面而非 320x568 時,應該如何排解?
Xcode 6 執行選擇 iPhone 5/5s + iOS 7.1

iPhone 5 + iOS 7 不應該上下有黑邊
照理說,iPhone 5 應該是 4 吋 Retina 的解析度 320x568 不應該成為 320x480 而讓畫面留下上下的黑邊。

原因是這樣:

原來是在 4 吋 Retina 的設備,少了 Default-568h@2x.png 的啟始畫面。

註:在 iOS 7.1 以前需要的啟始畫面檔案
  • Default.png - 320 x 480 pixels (standard resolution iPhone)
  • Default@2x.png - 640 x 960 pixels (high resolution iPhone 4)
  • Default-568h@2x.png - 640 x 1136 pixels (iPhone 5)



所以,如果您的 App 專案有這樣的設定時:

解決的方式,除了可以加入一個 640 x 1136 的 Default-568h@2x.png 檔案之外,可以在 Project 的 TARGETS 設定內,從 General 頁面內的 App Icons and Launch Images 將 Launch Images Source,按下「Use Asset Catalog」


您再執行看看,結果就不會在 iPhone 5/5s + iOS 7.1 的畫面上下出現黑邊了。

.

2014-07-09

Mac App 的 NSTextField Number Formatter - 處理小數點位數

前陣子為了解決 MacBook 畫面頂端功能表,因為程式的不同而有項目多寡,導致常駐程式被隱藏起來,像這樣:
Finder,有些常駐程式看不到


Xcode,常駐程式看到更少



於是做了一個 Mac App 叫做 M。
常駐程式全部都出來了吧

畫面很簡單:只有留一個 M 的程式名
後來加了「度分秒」與「度數」轉換,在查閱 Google 地圖時可以換算。
但是習慣小數點後面 4 位數,於是就找了一下:



按照這 4 個步驟,Xcode 夠可愛吧,簡單!

於是,小數點位數也正確了。


如果你有需要的朋友,可以免費下載使用

.

2013-06-05

UIColor 存放到 NSDictionary/NSMutableDictionary 內

之前有篇提到「UIImage 存放到 NSArray/NSMutableArray 內」讀過之後,是不是了解到 imageNamed:imagePath 並不是直接將 imagePath 路徑內的圖片載入 Array 內了?

這次來看看 UIColor。

如果你這樣用:

NSDictionary *dict0 = [[NSDictionary allocinitWithObjectsAndKeys:
                           @"紅色"@"CColor",
                           [UIColor redColor], @"EColor",
                           @"YES"@"Fill",
                           nil];

Xcode 會跟你這樣說:
-[UICachedDeviceRGBColor bytes]: unrecognized selector sent to instance 0xa9671e0
ColorInDictionary[7955:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UICachedDeviceRGBColor bytes]: unrecognized selector sent to instance 0xa9671e0'
原因是 NSDictionary 內容不允許你直接存入 [UIColor redColor] 的關係。


於是你要將 [UIColor redColor] 包裝起來,改用 [NSKeyedArchiver archivedDataWithRootObject:[UIColor redColor]]

像這樣:

NSDictionary *dict0 = [[NSDictionary allocinitWithObjectsAndKeys:
                           @"紅色"@"CColor",
                           [NSKeyedArchiver archivedDataWithRootObject:[UIColor redColor]], @"EColor",
                           @"YES"@"Fill",
                           nil];

取用時再拆開,還原成 UIColor 即可

UIColor *colorNow = [NSKeyedUnarchiver unarchiveObjectWithData:[dict0 objectForKey:@"EColor"]];


.

2013-04-30

Mac Wi-Fi 網路分享

在簡報時,我不會常在電腦旁。所以,不是在講台中央,就是在聽眾群中的走道。

通常,我會使用手機執行 Keynote Remote,這樣就可以一邊走動,一邊控制播放流程。

但是,在沒有 Wi-Fi AP 的環境下,用藍牙又不可以走太遠,所以 Wi-Fi 會是不錯的選擇。

Mac 有分享網路的功能,我來幫你打開,甚至還可以透過 Mac 當成 Wi-Fi AP 讓其他設備上網。
⬆建立 Wi-Fi 網路,不要連接現有的 Wi-Fi AP


⬆網路名稱自己設定,最好也加上 AP 密碼


⬆此時,你的 Wi-Fi 符號會變成這樣

在這個階段,你的 Mac 可以與其他電腦互相連接。


⬆開啟「系統偏好設定」的「共享」


⬆將「Internet 共享」勾選
我這裡是透過區域網路上網,如果你是透過手機分享 3G 網路,那麼「共享連線來源」可以制定為你的 iPhone USB。



⬆這樣就可以分享網路


⬆開啟手機的 Keynote Remote



⬆這樣就可以在手機滑動切換內容


就這樣幾個步驟,你的 Mac 就可以分享給 iPhone、iPad,甚至其他需要 Wi-Fi 連接的電腦或智慧型設備。

.

2013-04-19

UIImage 存放到 NSArray/NSMutableArray 內

最近學員遇到一個問題,要將 UIImage 放到 NSMutableArray 內,但是很不幸地會發生這樣的錯誤訊息:
ImageArray[5343:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'

不管是從 NSBundle 或是從 NSFileManager 取得 Documents 的都一樣。

載入如下:

NSArray *directoryContent = [[NSBundle mainBundle] pathsForResourcesOfType:@"png" inDirectory:nil];
NSMutableArray *items = [[NSMutableArray alloc] initWithCapacity:0];

for (NSString *imagePath in directoryContent) {
    UIImage *img = [UIImage imageNamed:imagePath];
    [items addObject:img];
}
NSLog(@"imagesArray:%@", items);

可是執行之後,就會得到上述的錯誤訊息。

錯誤的原因就在這句:
UIImage *img=[UIImage imageNamed: imagePath];

只要改成
UIImage *img = [UIImage imageWithContentsOfFile:imagePath];

錯誤就可以修正


最後正確的程式碼如下:

NSArray *directoryContent = [[NSBundle mainBundlepathsForResourcesOfType:@"png" inDirectory:nil];
NSMutableArray *items = [[NSMutableArray allocinitWithCapacity:0];

for (NSString *imagePath in directoryContent) {
    UIImage *img = [UIImage imageWithContentsOfFile:imagePath];
    [items addObject:img];
}
NSLog(@"imagesArray:%@", items);


善用你在 Xcode 的 Option+Click,你就可以找到答案了:

+ (UIImage *)imageWithContentsOfFile:(NSString *)path
Creates and returns an image object by loading the image data from the file at the specified path.
This method does not cache the image object.

+ (UIImage *)imageNamed:(NSString *)name
Returns the image object associated with the specified filename.
This method looks in the system caches for an image object with the specified name and returns that object if it exists


下載範例檔案
.

2013-04-01

Storyboard 有兩個 Segue 的問題

剛好有學員問到這樣的問題,我就拿該程式畫面在這裡做個圖文解說。
這個畫面連結了兩個 Segue
一般 Segue 都是要在  - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 內安排,如果有 Object 或 Value 要往下個 ViewController 傳遞的話,也是在這裡處理。


另外,如果只有一個 Segue 是從 UIButton 發生,可以這樣做:
- (IBAction)btnSyp:(id)sender {
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    Game01VC *vc = [storyboard instantiateViewControllerWithIdentifier:@"CustomerAdd"];
    vc.Flag = 1;
}

但是,第二個 UIButton 就無法如預期發生。
- (IBAction)btnKiller:(id)sender {
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    Game01VC *vc = [storyboard instantiateViewControllerWithIdentifier:@"CustomerAdd"];

    vc.Flag = 2;
}

所以,還是要回來以 prepareForSegue 處理。


先在 Storyboard 內設定好 Segue 的 Identifier 為 @"btnSyp" 與 @"btnKiller"


在第一個 UIButton 連結的 Segue 設定 Identifier 為 @"btnSyp"
另一個 UIButton 連結的 Segue 設定 Identifier 為 @"btnKiller"

在 prepareForSegue 內的程式如下:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    Game01VC *vc = segue.destinationViewController;

// 原本在 -(IBAction)btnSyp:(id)sender 內的,移到這裡來,以這種方式做
    if ([segue.identifier isEqualToString:@"btnSyp"]) {
        vc.Flag = 1;
    }
    
// 原本在 -(IBAction)btnKiller:(id)sender 內的,移到這裡來,以這種方式做
    if ([segue.identifier isEqualToString:@"btnKiller"]) {
        vc.Flag = 2;
    }
}

如此,就可以讓下個 ViewController 收到 Object 或 Value 了。


.

2013-03-30

iOS Dev Club 聚會 2013-03-30 活動影片

張景隆分享 Passbook 的實作,向隅的朋友可以觀看影片。


很久沒有來的家銘,這段時間都在開發這個平台,InWedding



iOS Dev Club : iPhone/iPad/iPod touch 軟體應用開發
https://www.facebook.com/groups/iostw/

姻為妳 inWedding 粉絲頁
https://www.facebook.com/OurInWedding




2012-10-10

初學者的困擾-英文,找一套可以在 iOS 設備點選查詢字典的App

我的工作中還有針對非本科系者的程式設計教學,從 1996 年以來,我都會在第一堂課,直接做個範例讓初學者看到一個程式如何的誕生,也會讓初學者按照我的方法親自做一次。

我都會問初學者:「你最大的困難在哪裡」?

「英文」

是的,大部份的學員都很有熱情學習程式設計,而我發現,在台灣受教育的人到了社會之後,生活中有英文的絕大部份都是... 跳過去。

跳過去,久而久之,英文就與你不認識了,更別說程式語言很像英文口語化的 Objective-C 了,所以會擔心自己學不來。

我都會給初學者鼓勵,你就利用這個機會一併將英文學好!其實程式語言的英文文件、手冊用詞、語法並不會艱澀難懂,初期辛苦一些,持之以恆就可以隨心所欲了!

而查詢是一件幫助很大的事,有沒有像 Windows 的 Dr.Eye 嗎?

有,在 Mac 我是從 Mac App Store 安裝「欧路词典」,安裝

如果你是將手冊安裝在 iPad 看,也可以安裝「欧路词典 For iPad」,安裝

它也有「螢幕取詞」的方法。


在 iPad 使用方法很簡單,先執行「欧路词典」,按 Home 按鍵再開啟你的閱讀器。


選區要查詢的單字






































選取 Copy 複製,查詢後的英文字會以「通知」的方式呈現







































將通知中心拉下來也可以看到之前查詢過的單字







































這樣是不是可以減少你的障礙了呢?




2012-10-01

Mac Trackpad 觸控式軌跡板技巧

觸控板在一些操作行為比鍵盤滑鼠方便許多,雖然剛開始有些手勢要學,但是以我的經驗來看,很快就可以進入狀況,不用擔心要學、要背。

其中一個方法,可以「使用四指向上滑動」呼叫 Mission Control,但是遇到相同的程式,他們就會聚集在一起,無法分辨哪個視窗,我發現可以再用兩指向上滑動,這時候畫面就會分開了。


2012-05-30

快速自製 App Icon

通常在開發電腦相關產品,大概會區分兩個領域:程式與美工。
而且很有趣的是:做程式的不熟美工,做美工的不熟程式。

舉凡軟體、網站都一樣。

然而在 iOS 行動設備 App 普及的市場,美工的需求變大了,其貌不揚的 App UI 會讓人對其第一印象很差,就算你有很強固的軟體,但沒有美工底子的程式設計師會滿吃虧的。

最近找到這個 Photoshop 用的 iOS App Icon Template,實在是幫了 Programmer 一個大忙,它就像孫悟空一樣,你只要專心做好一個,就可以幫你變成 10 個 Icon 出來。


開始吧!

首先來這裡取得 Photoshop 的樣板 http://appicontemplate.com/

下載 appicontemplate_v2.zip 解壓縮。
解開後的內容

複製一份 App Icon Template [2.0].psd,保留原稿。
我複製了 Cat.psd
從 Layers 找到 1024x1024 Smart Object 內的 EDIT THIS SMART OBJECT


點選兩下開啟 Icon.psb
修改 Smart Object 會提醒

編輯修改你的 icon 內容


關閉 Icon.psb 會問你要不要存檔,選 Save


原本的樣板


全部就會變成你剛剛做的


再來選取 Actions 的 App Icon Template [2.0],看你是要 Squared 或是 Rounded
(這個 Action 需要開啟 App Icon Template [2.0].atn 檔案,就會 plug 到 Photoshop)


右上角選 png-24,然後按 Save


給路徑與檔名


就會自動產生了



.

2012-04-13

如何取出 Application 的 icns ?

在你的 /Application 裡,每個 .app 的 Contents\Resources 內都有 .icns,像這個:
如果你想把它們取出來,要如何做?

1.打開 Terminal
2.用 pico 新增 shell 檔案,自己取個名字,我是用 fetchicons
3.將以下內容貼入

find / -name "*.icns" > ~/icnsfile
echo "items to copy found"
IFS="
"
for i in $(cat ~/icnsfile)
do
echo "copying $i"
cp $i ~/ICNS/${i//\//$}
done
4.然後 sudo 執行 ./fetchicons,過一會兒就可以在你的 home 看到一堆 .icns
再開啓預覽程式就可以另存 .png 檔案自行應用了。


.

2010-10-16

網路傳輸時 UIActivityIndicatorView 的動作

這已經是習慣了,大家都習慣要有這個符號出現。
當你的程式有使用到網路傳輸,通常就需要放一個 UIActivityIndicatorView 在畫面上,讓使用者知道目前正在傳輸中,以免讓人覺得沒有回應,像是當機一樣。
可是,為何你照著書本範例加到自己的程式卻不會動呢?

原因是:UIKit 的 main thread 一次只有做一件事,如果你在 ViewController 傳輸檔案,那麼其他的動作會等傳輸完之後再接下去做,所以你要另外再生出一個 thread 去處理 UIActivityIndicatorView 的動作。

使用 Objective-C 來處理 thread 是很簡單的,比 Java 還容易,在後面的說明裡會看到。


首先,在 .h 檔的 @interface 內加上

UIActivityIndicatorView *activityIndicator;


以及

@property (nonatomic, retain) IBOutlet UIActivityIndicatorView *activityIndicator;


另外,再加上兩個 method

-(void)actIndicatorBegin;
-(void)actIndicatorEnd;


開啓 .m 檔,在 @implementation 的下面加上

@synthesize activityIndicator;


在 (void)loadView 內把你的 UIActivityIndicatorView 加上去你要的 View 上面,我這裡加在 UIToolbar 工具列裡面的一個 UIBarButtonItem 按鈕

activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 0, 24, 24)];
[activityIndicator setCenter:CGPointMake(12, 12)];
[activityIndicator setHidesWhenStopped:YES];
[activityIndicator setActivityIndicatorViewStyle: UIActivityIndicatorViewStyleWhite];
[activityIndicator startAnimating];
UIBarButtonItem *activityItem = [[[UIBarButtonItem alloc] initWithCustomView: activityIndicator] autorelease];


再把這個 UIBarButtonItem 加到 UIToolbar 內

NSArray *items = [NSArray arrayWithObjects:activityItem, nil];
toolbarTop.items = items;


在處理網路傳輸之前先執行這個 thread

[NSThread detachNewThreadSelector: @selector(actIndicatorBegin) toTarget:self withObject:nil];

//需要時間下載檔案的程式寫在這裡

url = [NSURL URLWithString:@"http://網址/圖片檔.jpg"];
img =[UIImage imageWithData:[NSData dataWithContentsOfURL:url]];


網路傳輸完之後再執行這個 thread

[NSThread detachNewThreadSelector: @selector(actIndicatorEnd) toTarget:self withObject:nil];


再加上這兩個 method 開關旋轉狀態
- (void) actIndicatorBegin {
[activityIndicator startAnimating];
}

-(void) actIndicatorEnd {
[activityIndicator stopAnimating];
}


就這麼簡單,做看看吧!

.

2009-08-16

給 Delphi 設計師快速入門 iPhone 程式設計

我最近在想,要如何幫助 Delphi 或是 VB 的設計師們可以快速入門 iPhone 程式開發。
Delphi 之所以方便使用,是提供了一系列方便使用的 VCL 元件,讓設計師可以快速地把視窗軟體實作出來。
所以,這次我就把 IB (Interface Builder) 與 Xcode 之間很類似 VCL 的拖曳觀念,來寫一篇教學文件給大家參考,希望可以有拋磚引玉的作用。
我在這裡的範例是做一個調色盤,有三個分別是紅綠藍的 Slider Bar,藉由 Slider Bar 的調整,讓整個背景隨時呈現色彩。


首先,開啟 Xcode 新增一個 Window-based Application
取名 palette

產生新的 Project 如下:

找到 MainWindow.xib 開啓,會交由 Interface Builder (IB)

在 IB 會看到兩個視窗,一個是 MainWindow.xib (像是 Delphi 的 View Forms/Units)。
(如果畫面不一樣,改變工具列上面的 View Mode)

另一個是 Window 的 View。(像是 Delphi 的 Form)

在 IB 按下 +SHIFT+L 開啓 Library (像是 Delphi 上面的 Components Palette)

將 Slider 拖曳到 Window 的 View 上面排列、調整位置、大小 (會 Delphi 這個就不難)

在 IB 按下 +SHIFT+I 開啓 Inspector (像是 Delphi 的 Object Inspector)。
設定 Slider 的『屬性』(記得 Window 點選到 Slider,跟 Delphi 設定屬性原理一樣)
Value Minimum: 0,Maximum: 255

再拖曳兩個 Label 進來 Window 的 View 上面排列,只要對該 Label 點兩下,就可以直接修改內容,分別給 Red Value 與 0

把這三個選取後,複製貼上(就像在 Delphi 的 Form 上面作業一樣),一共產生三組,分別要處理 RGB 用。

您也可變更 Label 的顏色『屬性』

這樣會比較好辨識
到這裡都很簡單吧!
把 Object 拉到 Window 的 View 上面,就像是在 Delphi 把 VCL 元件拉到 Form 上面一樣簡單。



接下來我們把元件的關係連結起來。

從 Library 把 NSObject(金黃色正方體) 拉到 MainWindow.xib 上面
看到這樣:
然後按 +4 把 Inspector 切換到 Identidy

這裡我們要設定 Class Identity, Class Action, Class Outlets 等三個部份

Class Identity 類別識別,目前是 NSObject,我們設定名稱為 Controller
Class Action 是指元件的動作,相當於 Delphi 的事件
Class Outlets 是哪些元件會在程式內用到的、會與畫面互動的,可以在這裡指定

再看一次我們的畫面,我命名如下:
sliderR, sliderG, sliderB 會觸發事件,我們要在程式內安排程式碼。
labelR, labelG, labelB 會因為事件發生,在程式碼內改變他們的屬性。

所以把這6個加到 Class Outlets 內。


確認 MainWindow.xib 點選到的是剛剛加進來的 Object (Type: NSObject)。
Class Identity 的 Class 命名為 Controller。
Class Action 分別加上 (在框框下面有個 + 號)
  • sliderChangedR: (Type: id)
  • sliderChangedG: (Type: id)
  • sliderChangedB: (Type: id)
Class Outlets 分別加上
  • sliderR (Type: UISlider)
  • sliderG (Type: UISlider)
  • sliderB (Type: UISlider)
  • labelR (Type: UILabel)
  • labelG (Type: UILabel)
  • labelB (Type: UILabel)

接著我們把 IB 建立的產生成 Class 檔案,選取功能表 File\Write Class Files...
接著的視窗內,Save As: 會依照剛剛 Class Identity 的 Class: Controller 命名
把檔案儲存在 Classes 的檔案夾內(我習慣把 Class 都放到 Classes 檔案夾內)
按下 Save 後,會出現詢問視窗,是否要把 Controller.m 與 Controller. h 加到 palette 專案裡,記得勾選 palette 後按下 Add
回到 Xcode 會多出這兩個檔案 Controller.m 與 Controller.h

Controller.h 的內容


Controller.m 的內容


開啓 Controller.h 將 @interface Controller: 後面加上 NSObject
這裡可以看到 6 個 IBOutlet 與 3 個 IBAction 的定義

再來開啓 Controller.m 來安排事件程式:
依照 sliderR, sliderG, sliderB 的變化而改變 labelR, labelG, labelG 的值。

這時候興奮地按下 Build and go,出現 iPhone 的畫面了!
可是拉動 Slider 並不會看到數值改變啊!

那是因為我們在 IB 還沒有把 Connections 建立起來。
所以回到 IB 點選 MainWindows.xib 的 Controller,然後按 +2 把 Inspector 切換到 Connections Inspector:
這裡區分三個部份,我們要用前面兩個:Outlets 與 Received Actions。
看到 Outlets 內的 labelB 右邊的圈圈吧!將游標移到上面,會出現一個 + 號,然後按住滑鼠左鍵,移動到 Window 上面的 labelB 然後放開滑鼠左鍵。在移動滑鼠的時候,會看到一條藍色的連結線,讓設計者很清楚哪一個要連結。


Connections Inspector 的 Outlets 內 labelB 會有連結 Label (0) 的顯示

依此類推,將 labelG, labelR, sliderR, sliderG, sliderB 也都連結起來

然後換 Received Actions 內的三個。

一樣從 sliderChangedB 右邊的圈圈開始,拉到 Window 的藍色 Slider 上面,然後放開滑鼠左鍵

在放開滑鼠左鍵後會看到這個視窗,點選 Value Changed
依此類推,可以看到 Received Actions 顯示

記得把 MainWindow.xib 存檔後,回到 Xcode
Build and go 就可以看到結果了!

最後階段要改變 Window 背景顏色

開啓 Controller.h 加上 #import "paletteAppDeledate.h"

開啓 Controller.m 在 @implementation 上面加上 @class paletteAppDelegate;

因為 window 的這個元件是在 paletteAppDelegate 內,我們要從 Controller 去使用 paletteAppDelegate 內的元件。
(有點像是 Delphi 要把被使用的 Unit 加到 uses 內)

接著在這三個事件內加上這兩行

最後的 Controller.m 程式

執行看看,成功了吧,恭喜!

*最後的 Controller.m 內,三個事件 sliderChangedR, sliderChangedG, sliderChangedB 重複的那兩行程式,可以另外做一個 Method 處理,就留給各位練習看看。

範例程式下載1(github)

範例程式下載2(bitbucket)
.