[Xcode] 前編譯標頭檔 (Pre-Compile Header)
更新到了Xcode 6,新建立的專案不再預設.pch檔,之前都將時常用到的class放置.pch檔,讓專案下所有的class都能引用,如今Xcode 6取消預設,我們該怎麼自行建立?
我們可以看到Xcode 5所預設建立的.pch檔位置在專案檔的下一層,路徑就找到囉~
更新到了Xcode 6,新建立的專案不再預設.pch檔,之前都將時常用到的class放置.pch檔,讓專案下所有的class都能引用,如今Xcode 6取消預設,我們該怎麼自行建立?
我們可以看到Xcode 5所預設建立的.pch檔位置在專案檔的下一層,路徑就找到囉~
以繁體中文(因為是母語喲!)為主來做多國語言化,另外兩個語言是簡體中文和英文,跟著多國語系 (Localization)這篇文章做,照理說已經沒有其它問題,但是呢⋯⋯若哪天日本人想用這個App,那麼他會看到哪個語言?實際跑過發現是偉大的繁體中文,然而我們的期望卻是套用英文,這時候該怎麼辦呢?打掉重練?噢~不。
有時候server吐回來陣列元素的順序剛好跟我們所期望的相反,如想要[1,2,3,4,5],卻拿到[5,4,3,2,1]。
此時就需要做反序陣列元素 (Reverse Array)的動作。我們可以有兩種做法,一種是索引(index)由大到小存取陣列元素,一種是陣列元素前後對等交換(最左與最右,左數第二與右數第二,依此類推⋯⋯),下列程式碼實作後者,又分可變陣列(NSMutableArray)和不變陣列(NSArray)。
將程式碼放到.m檔裡即可使用,或是寫成類別來引用。
/**
Theme: Reverse Array
IDE: Xcode 6
Language: Objective C
Date: 103/10/14
Author: HappyMan
Blog: https://cg2010studio.wordpress.com/
*/
@implementation NSArray (Reverse)
- (NSArray *)reversedArray {
NSMutableArray *array = [NSMutableArray arrayWithCapacity:[self count]];
NSEnumerator *enumerator = [self reverseObjectEnumerator];
for (id element in enumerator) {
[array addObject:element];
}
return array;
}
@end
@implementation NSMutableArray (Reverse)
- (void)reverse {
if ([self count] == 0)
return;
NSUInteger i = 0;
NSUInteger j = [self count] - 1;
while (i < j) {
[self exchangeObjectAtIndex:i
withObjectAtIndex:j];
i++;
j--;
}
}
@end
一個能夠跨國際使用的App,需要多國語言化(Localization),之前介紹的是系統運行時自動轉換字串的語言,然而我們想要知道目前使用者的偏好語言 (Prefer Language),來做更進一步的運用,比如將語言碼當作參數傳遞。
/**
Theme: Language
IDE: Xcode 6
Language: Objective C
Date: 103/10/14
Author: HappyMan
Blog: https://cg2010studio.wordpress.com/
*/
// 記錄語言碼
NSString *languageStr = [[NSLocale preferredLanguages] objectAtIndex:0];
// NSString *languageStr = [[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0];
if ([languageStr isEqualToString:@"zh-Hant"]) {// 繁中
self.languageCode = @"2";
}
if ([languageStr isEqualToString:@"zh-Hans"]) {// 簡中
self.languageCode = @"1";
}
if ([languageStr isEqualToString:@"en"]) {// 英語
self.languageCode = @"0";
}
有兩種用法可行,注意事項請看文件說明!
+ (NSArray *)preferredLanguages NS_AVAILABLE(10_5, 2_0);
note that this list does not indicate what language the app is actually running in; the [NSBundle mainBundle] object determines that at launch and knows that information@property (readonly, copy) NSArray *preferredLocalizations;
a subset of this bundle’s localizations, re-ordered into the preferred order for this process’s current execution environment; the main bundle’s preferred localizations indicate the language (of text) the user is most likely seeing in the UI
跟程式裡的字串做多國語言化(Localization)不一樣,要讓App顯示名稱多國語言化 (Bundle Display Name Localization)必須經由別的做法,可以找尋檔案列表中InfoPlist.strings,在IDE右側界面「Localization」打勾所需的語系,即會出現我們想要的語系檔案如下。
分別在三個檔案內加入各語系想顯示的名稱即可!就是以Key-Value的方式設定。
/* Localized versions English of Info.plist keys */ "CFBundleDisplayName" = "HappyMan"; /* Localized versions Chinese Simplified of Info.plist keys */ "CFBundleDisplayName" = "逍遥文"; /* Localized versions Chinese Tradition of Info.plist keys */ "CFBundleDisplayName" = "逍遙文";
Apple今年推出的iPhone 6和iPhone 6+螢幕大小為4.7吋和5.5吋,這對開發者來說無疑是個新的考驗,因為先前我們只要在3.5吋和4吋做設計,如今一次多了兩款大小!以為一個專案要同時為四種大小做設計,事實上也是如此⋯⋯不過呢~Xcode也隨著iPhone進化,我們只要透過新的功能特性,即可簡化設計不同螢幕大小的程序!
寫程式同時也在設計(所以才叫做程式設計師),界面最好能夠直接在電腦螢幕上預覽,比起一維的程式碼,二維的畫面更加直覺!在新的專案中,我開始使用「自動佈局(Auto Layout)」技術,設定好後在四種螢幕大小顯示效果相當好,Xcode的各尺寸畫面即時預覽做得相當棒,且看一下我的一個畫面吧!
看得出來由上而下,分別是3.5吋、4吋、4.7吋、5.5吋嗎?我只是做切換預覽的動作,元件就依照我所設定來「自動佈局」!不太需要跑各種螢幕大小的實機或模擬器囉~當然如果是用code寫自動佈局,還是要編譯執行跑結果啦:P~
參考:iPhone 4/5/6 手指觸及範圍、[寫真] iPhone 5C、[寫真] iPhone 6 與 iPhone 6+。
原以為伺服器吐回來給我的會是「直向」的圖,那麼我就可以不去旋轉它,但事與願違,我還是得處理「橫向」的圖⋯⋯好在吐回來的圖像資料,除了有URL外,還有Orientation,那麼我就根據後者去判斷是否該旋轉90度!
把以下的code貼到想要使用的.m檔內即可:)~
/**
Theme: Image Rotation
IDE: Xcode 6
Language: Objective C
Date: 103/10/02
Author: HappyMan
Blog: https://cg2010studio.wordpress.com/
*/
@interface UIImage (RotationMethods)
- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees;
@end
@implementation UIImage (RotationMethods)
static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;};
- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees
{
// calculate the size of the rotated view's containing box for our drawing space
UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0,self.size.width, self.size.height)];
CGAffineTransform t = CGAffineTransformMakeRotation(DegreesToRadians(degrees));
rotatedViewBox.transform = t;
CGSize rotatedSize = rotatedViewBox.frame.size;
// Create the bitmap context
UIGraphicsBeginImageContextWithOptions(rotatedSize, NO, 2.0);
CGContextRef bitmap = UIGraphicsGetCurrentContext();
// Move the origin to the middle of the image so we will rotate and scale around the center.
CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2);
// Rotate the image context
CGContextRotateCTM(bitmap, DegreesToRadians(degrees));
// Now, draw the rotated/scaled image into the context
CGContextScaleCTM(bitmap, 1.0, -1.0);
CGContextDrawImage(bitmap, CGRectMake(-self.size.width / 2, -self.size.height / 2, self.size.width, self.size.height), [self CGImage]);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
@end
使用方式相當簡單,只要以UIImage的實體來呼叫此方法,然後它處理完會吐回UIImage。
UIImage *rotatedImage = [happyImage imageRotatedByDegrees:90.0];
如此就可以旋轉90度囉~當然你想轉180度、246度等等也是可以!
要注意的是,這裡不是UIImageView的做法喔!因為我想要直接轉存成檔案,所以是用UIImage來做到。
參考:StackOverFlow – How to rotate an image 90 degrees on iOS?。
這是個很奇妙的議題,明明是用去年人家寫的案子呼叫API的程式碼,連第三方套件也一模一樣,所帶入的方法和參數一模一樣,但是卻跑不出相同的結果⋯⋯
不知怎麼命名這篇文章,暫且以不合法的伺服器憑證問題為名吧!似乎跟http和https有關聯?還有什麼SSL?
然後就跑出這幾行訊息:
The certificate for this server is invalid. You might be connecting to a server that is pretending to be “xxx.ooo.com.tw” which could put your confidential information at risk.
查了網路前人的解法,原來只要在兩個delegate改成這樣⋯⋯
- (BOOL)connection:(NSURLConnection *)connection
canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
起初還想要請負責server端的人改安全性程度,不過既然去年的project都可以成功跑出結果,還是由我app端來處理問題吧!
寫了以上的code,還是不太明白意義⋯⋯知道的人請跟我說一下><;
參考:How to use NSURLConnection to connect with SSL for an untrusted cert?、NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813) iOS。
HappyMan・迴響