Just My Life & My Work

Archive for the ‘iOS’ Category

[iOS] Scroll View 改變翻頁大小

在Scroll View上翻頁(Paging)似乎只能根據Scroll View這個元件的大小來決定,然而今日我有需求來改變其翻頁的大小,該如何做呢?

scroll view_

神人這麼建議⋯⋯

  1. turn off clipsToBounds
  2. put a UIView over the scrollview, wherever you want the user to be able to touch
  3. move the panGestureRecognizer to that view
    [touchableView addGestureRecognizer:_scrollView.panGestureRecognizer];

如果只是縮小Scroll View,且讓其上的元件不被切掉(第一點),那麼觸控範圍只有在被縮小Scroll View上頭,這樣不太合理,那麼我們就希望讓兩邊空白處也能觸控Scroll View。神人建議可以將panGestureRecognizer轉移共用,在Scroll View底下鋪View,將Scroll View的panGestureRecognizer設定到View上頭,這樣就大功告成!

scroll view

 

神人說這麼做,Apple是允許的,在WWDC的Session (WWDC Session 223, “Enhancing User Experience with Scroll Views)上有提到,Scroll View有兩個gesture recognizer,就是因為大家的期望而設計出來的,如此就能在非該Scroll View上的元件來移動縮放該Scroll View囉~

// Use these accessors to configure the scroll view’s built-in gesture recognizers.

// Do not change the gestures’ delegates or override the getters for these properties.

@property(nonatomic, readonly) UIPanGestureRecognizer *panGestureRecognizer NS_AVAILABLE_IOS(5_0);

// `pinchGestureRecognizer` will return nil when zooming is disabled.

@property(nonatomic, readonly) UIPinchGestureRecognizer *pinchGestureRecognizer NS_AVAILABLE_IOS(5_0);

參考:Changing the size of a paging scroll view

[Xcode] 前編譯標頭檔 (Pre-Compile Header)

更新到了Xcode 6,新建立的專案不再預設.pch檔,之前都將時常用到的class放置.pch檔,讓專案下所有的class都能引用,如今Xcode 6取消預設,我們該怎麼自行建立?

前編譯標頭檔 Pre-Compile Header4

我們可以看到Xcode 5所預設建立的.pch檔位置在專案檔的下一層,路徑就找到囉~

(繼續閱讀…)

[iOS] 多國語言化的預設語言 (Default (Fallback) Language of Localization)

繁體中文(因為是母語喲!)為主來做多國語言化,另外兩個語言是簡體中文英文,跟著多國語系 (Localization)這篇文章做,照理說已經沒有其它問題,但是呢⋯⋯若哪天日本人想用這個App,那麼他會看到哪個語言?實際跑過發現是偉大的繁體中文,然而我們的期望卻是套用英文,這時候該怎麼辦呢?打掉重練?噢~不。

Default (Fallback) Language of Localization

(繼續閱讀…)

[iOS] 反序陣列元素 (Reverse Array)

有時候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

參考:How can I reverse a NSArray in Objective-C?

[iOS] 偏好語言 (Prefer Language)

一個能夠跨國際使用的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

參考:Getting current device language in iOS?

[iOS] 加入聯絡人資料到通訊錄

想要將顯示在App上的聯絡人資料加入到通訊錄,但是不想要讓使用者自己到通訊錄一個字一個字慢慢打,這時候就可以用這些複雜的程式碼解決囉!

Address Book1

(繼續閱讀…)

[iOS] 顯示名稱多國語言化 (Bundle Display Name Localization)

跟程式裡的字串做多國語言化(Localization)不一樣,要讓App顯示名稱多國語言化 (Bundle Display Name Localization)必須經由別的做法,可以找尋檔案列表中InfoPlist.strings,在IDE右側界面「Localization」打勾所需的語系,即會出現我們想要的語系檔案如下。

Bundle Display Name 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" = "逍遙文";

參考:How to localize bundle display name in iPhone app?

[Xcode] 各尺寸畫面即時預覽

Apple今年推出的iPhone 6iPhone 6+螢幕大小為4.7吋5.5吋,這對開發者來說無疑是個新的考驗,因為先前我們只要在3.5吋和4吋做設計,如今一次多了兩款大小!以為一個專案要同時為四種大小做設計,事實上也是如此⋯⋯不過呢~Xcode也隨著iPhone進化,我們只要透過新的功能特性,即可簡化設計不同螢幕大小的程序!

寫程式同時也在設計(所以才叫做程式設計師),界面最好能夠直接在電腦螢幕上預覽,比起一維的程式碼,二維的畫面更加直覺!在新的專案中,我開始使用「自動佈局(Auto Layout)」技術,設定好後在四種螢幕大小顯示效果相當好,Xcode的各尺寸畫面即時預覽做得相當棒,且看一下我的一個畫面吧!

Xcode 3.5%22 Xcode 4%22 Xcode 4.7%22 Xcode 5.5%22

看得出來由上而下,分別是3.5吋、4吋、4.7吋、5.5吋嗎?我只是做切換預覽的動作,元件就依照我所設定來「自動佈局」!不太需要跑各種螢幕大小的實機模擬器囉~當然如果是用code寫自動佈局,還是要編譯執行跑結果啦:P~

參考:iPhone 4/5/6 手指觸及範圍[寫真] iPhone 5C[寫真] iPhone 6 與 iPhone 6+

[iOS] Navigation拋出View Controller次數

原生的Navigation只有實作拋出一次View Controller拋出所有View Controller,但是我想要拋出兩次(或是三次、四次等等)View Controller,該怎麼做呢?

查了Stack Over Flow才覺得非常簡單,其實每個人都想得到XD~

// in UINavigationController+popTwice.h

#import <UIKit/UIKit.h>
@interface UINavigationController (popTwice)

- (void) popTwoViewControllersAnimated:(BOOL)animated;

@end

// in UINavigationController+popTwice.m

#import "UINavigationController+popTwice.h"

@implementation UINavigationController (popTwice)

- (void) popTwoViewControllersAnimated:(BOOL)animated{
    [self popViewControllerAnimated:NO];
    [self popViewControllerAnimated:animated];
}
@end

我們可以多實作一個pop兩次View Controller的方法,將第一個pop設定無動畫,第二個pop設定有動畫,效果就如同我們期待的那樣!當然想要pop三次、四次以上也可以依此類推做到呢!

使用方法為:

#import “UINavigationController+popTwice.h"

[self.navigationController popTwoViewControllersAnimated:YES];

參考:How do I pop two views at once from a navigation controller?

[iOS] 影像旋轉 (Image Rotation)

原以為伺服器吐回來給我的會是「直向」的圖,那麼我就可以不去旋轉它,但事與願違,我還是得處理「橫向」的圖⋯⋯好在吐回來的圖像資料,除了有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?

標籤雲