2014年12月30日 星期二

CLLocationManager在iOS8之後,如何新增權限的機制

在iOS8之後,要使用LocationManager之前,要先跟使用者要權限,可以要求的權限分為兩種:

  1. 只允許App在前景使用GPS。
  2. 允許App在進入後景之後仍可使用GPS。
因為我要開發的是iBeacon-based App,所以想當然爾要詢問的是第二種權限。

不過要求方式差不多,所以下面同時介紹兩種方式

一、在你的plist中加入這兩個Key(也可只加入你要用的),Value的部份選string並輸入你想要在要求權限的AlertView中出現的內容。
  • NSLocationAlwaysUsageDescription
  • NSLocationWhenInUseUsageDescription

、在你要使用GPS之前,用
//要求always權限

if ([self respondsToSelector:@selector(requestAlwaysAuthorization)]) {
                [self requestAlwaysAuthorization];
            }
//要求whenInUse權限
            if ([self respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
                [self requestWhenInUseAuthorization];

            }

2014年12月27日 星期六

區域監控的觸發時機

Monitoring of a geographical region begins immediately after registration for authorized apps. However, don’t expect to receive an event right away, because only boundary crossings generate an event. In particular, if the user’s location is already inside the region at registration time, the location manager doesn’t automatically generate an event. Instead, your app must wait for the user to cross the region boundary before an event is generated and sent to the delegate. To check whether the user is already inside the boundary of a region, use the requestStateForRegion: method of the CLLocationManager class.

要跨過區域才會觸發事件。
如果一開始就在區域內部,則不會觸發進入事件,
解決方法是要用requestStateForRegion去主動查看狀態。

P.S.我在寫iBeacon的時,遇到一模一樣的情況。

2014年12月26日 星期五

社群分享功能,在大陸已被做成SDK

//阿里巴巴投資
http://dev.umeng.com/social/ios/sdk-download

//也獲投資
http://sharesdk.mob.com

2014年12月18日 星期四

NSData UIImage 互轉

http://stackoverflow.com/questions/14133366/convert-uiimage-to-nsdata-and-save-with-core-data

If PNG image
UIImage *image = [UIImage imageNamed:@"imageName.png"];
NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(image)];
If JPG image
UIImage *image = [UIImage imageNamed:@"imageName.jpg"];
NSData *imageData = UIImageJPEGRepresentation(image, 1.0);
You can store it in CoreData like so (this is one possible useful solution):
[newManagedObject setValue:imageData forKey:@"image"];
You can load the data from CoreData like this:
NSManagedObject *selectedObject = [[self yourFetchCOntroller] objectAtIndexPath:indexPath];
UIImage *image = [UIImage imageWithData:[selectedObject valueForKey:@"image"]];

// Set the image to your image view  
yourimageView.image = image;

2014年12月16日 星期二

iAP線上改價格


結論:可以直接在itunesconnect改價格,不需要重新審核。


Changing Product Pricing

You can change the pricing for an In-App Purchase product at any time.


To change product pricing
  1. Go to the In-App Purchases page for the app, as described in To view In-App Purchase product configuration information.
  2. Click in the row of the In-App Purchase product you want to edit.
  3. In the In-App Purchase Summary section, click Edit.
  4. Make changes to the summary information.
    • If you want to replace the existing Price Tier, select the new Price Tier, then set the Price Effective Date to Now and the Price End Date to None. Click Add to Schedule.
    • If you want to have the product price change at some date in the future, select the future Price Tier, then set the Price Effective Date and Price End Date to define the interval for the new price. Click Add to Schedule.
  5. Click Save.
    The new values appear in the In-App Purchase Summary and are effective immediately. Apple doesn’t review these changes.

使用目前locale的資訊

//目前系統語言
NSString * language = [[NSLocale preferredLanguages] objectAtIndex:0];

//當地的貨幣格式
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
    [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
    [numberFormatter setLocale:[NSLocale systemLocale]];
    NSString *formattedString = [numberFormatter stringFromNumber:@100];

2014年12月4日 星期四

直接抓取tableView目前選擇的indexPath

//直接抓取tableView目前選擇的indexPath
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];

//直接抓取tableView指定的indexPath的ManagedObject值
NSManagedObject *object = [_fetchedResultsController objectAtIndexPath:indexPath];

2014年12月2日 星期二

在itunesconnect中,不能用同名的app name或SKU,即使已經刪除不能用

From the iTunes Developer Guide:
Important: If you delete your app, you cannot reuse your SKU or app name in the same account again, and you cannot restore the app you have deleted. If you have uploaded a binary or set up this app for the iAd network, your Bundle ID cannot be reused.

意思是在itunesconnect中,不能用同名的app name或SKU,即使你新增完之後把它刪除也不能用。

所以,取名要小心!!!!

2014年11月26日 星期三

關於ViewController以及autolayout你應該要知道的事

一、生命週期的呼叫順序:

  1. initWithNibName
  2. loadView
  3. viewDidLoad
  4. viewWillAppear
  5. viewWillLayoutSubviews
  6. viewDidLayoutSubviews
  7. viewDidAppear
  8. viewWillDisappear
  9. viewDidDisappear
  10. dealloc
initWithNibName 
若以xib呼叫時,會執行這裡,不需要在這覆寫什麼東西。

loadView 
這裡要非常注意,因為在xcode會自動生成一些code在這裡,目的是連結Interface Builder與你的ViewController Class。
所以一般使用xib或storyboard是不需要去override這個methed,如果真的想不開,請記得先執行[super loadView],不然你肯定找不到你辛苦拉好的view。
如果你沒用xib,就是要在這裡建立你要的self.view。

viewDidLoad
當View被load好之後,會執行這裡,且在生命週期中只會執行一次,所以一些初始值的設定盡量放在這。

viewWillAppear
view被load好之後,就要將它顯示出來,在顯示之前會執行這裡。
這裡在每次顯示前都會被執行,所以可以在此設定一些隨著每次畫面出現,都要變動的值。

viewWillLayoutSubviews
viewDidLayoutSubviews
在viewWillAppear時,還沒有做些auto layout的調整,將會在這裡才實作,
意思是如果你想要抓取UI在auto layout之後的frame,從這裡被執行之後才能抓到。
值得注意的是,這兩個function是只要有畫面的變動時,就會被觸發,被觸發的頻率比viewWillAppear/viewDidAppear來的高很多。

其他的就差不多是類似的意思,例如viewWillDisappear,就是在畫面將消失前會觸發。

二、接下來要介紹的是接到memoryWarming的回收方式:

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];

     if ([self.view window] == nil)
    {
        // 如果view的window為nil,代表self.view已經不在顯示。
        
        //TODO:一、加入code讓你要保留的值存到安全的地方
        //TODO:二、把你設為strong的值,指定為nil

        // 最後讓你的self.view = nil;
        self.view = nil;
    }
}



三、改變self.view大小的流程(auto layout的執行過程)

當view controller的size改變時,他的subview們也會重新調整自己的位置。他們通常使用layout constraints和autoresizing masks,這時view controller會發生下列的步驟:

  1. self.view改變size.
  2. 如果沒使用autolayout,才會以autoresizing masks來調整大小
  3. view controller的 viewWillLayoutSubviews 方法將會被呼叫。
  4. self.view的 layoutSubviews 方法會被呼叫,如果使用auto layout他會執行下列步驟:
    1. view controller 的 updateViewConstraints 方法會被呼叫。
    2. updateViewConstraints會去呼叫各個view的 updateConstraints 方法。
    3. 計算新的layout,並重置views到新的位置。
  5. view controller的 viewDidLayoutSubviews 方法被呼叫。

四、autolayout的最佳執行方式建議

    如果你是開發於iOS 6 and later
    先使用layout constraints來自動設定你的view的位置(iOS 6 and later)
    你可以去覆寫updateViewConstraints方法 來加入一些需求額外客製化的layout constraints,但記得一定要在方法中先加入[super updateViewConstraints];來實作自動產生的UI constrains.

    如果你是用iOS 5.x
    使用autoresizing masks,你要覆寫layoutSubviews來設定一些無法用resizing masks自動達成的位置。

    2014年11月25日 星期二

    iOS 6以後,要如何呼叫客製化的tableView Cell

    分為Cell是「自定義出來的」或是「已經放在storyboard上的」兩種:

    一,自定義出來的:

    先來viewDidLoad中加入這行註冊你要call的cell,
    [self.tableView registerClass:[CustomCell class] forCellReuseIdentifier:@"CustomCell"];
    //如果要用xib,那就使用iOS5之後就有的method
    //- (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(5_0);

    註冊之後,你就可以在cellForRowAtIndexPath:中直接呼叫UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CustomCell" forIndexPath:indexPath];

    //而不需要如下的傳統寫法
    static NSString *CellIdentifier = @"CustomCell";
    if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

    二,從storyboard上抓
    先把你客製化的cell放到你storyboard上的tableView中,然後設定identifier為@"CustomCell"

    接下來,直接在cellForRowAtIndexPath:中呼叫cell即可
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CustomCell" forIndexPath:indexPath];
        
    注意:如果你用storyboard的方式,那不可以呼叫registerClass:[CustomCell class] 方法,否則它會建立一組新的cell,而不會直接取用storyboard上畫好的!!!

    2014年11月21日 星期五

    auto layout的觸發時機

    viewDidLoad      
            \/
    viewWillAppear
            \/
    auto layout
            \/
    viewDidAppear

    2014年11月14日 星期五

    tableView的cell的width會給定一個default值,reuse的時候才會以tableView為主

    //如下NSLog所示,一開始進入cell == nil判斷時,cell的width都會是320,當你下拉tableView再拉回時,reuse的cell才會跟tableView的width一樣大。
    //由此可知,一開始new的cell因為不知道你的tableView的frame,所以會先給定一個default值!你要自行去修改。

     static NSString *CellIdentifier = @"Cell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
         
    NSLog(@"%@ cellForRowAtIndexPath cell.frame.size.width 1 =%f", [self class], cell.frame.size.width);

        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
            NSLog(@"%@ cellForRowAtIndexPath cell.frame.size.width 2 =%f", [self class], cell.frame.size.width);
            [cell setFrame:CGRectMake(0.f, 0.f, tableView.frame.size.width, tableView.frame.size.height)];
        }
        NSLog(@"%@ cellForRowAtIndexPath cell.frame.size.width 3 =%f", [self class], cell.frame.size.width);

    2014年11月10日 星期一

    抓一個月有幾天

    - (NSInteger)numberOfDaysInMonth:(NSDate *)today
    {
        NSRange range = [[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit inUnit:NSMonthCalendarUnit forDate:today];
        return range.length;
    }

    }

    2014年11月5日 星期三

    如何用程式切換tabbar到你要的navigationController然後push到你要的頁面

    UITabBarController *tabbarController = self.tabBarController;
        dispatch_async(dispatch_get_main_queue(), ^{
            
            //選取tabbar第三個controller:Family
            [tabbarController setSelectedIndex:2];
            
            UINavigationController *navController = (UINavigationController *)tabbarController.selectedViewController;
            
            //如果已經被push到下一頁的,都拉回到
            [navController popToRootViewControllerAnimated:NO];
            
            for (UIViewController *subViewController in navController.viewControllers) {
                
                if( [subViewController isKindOfClass:[SFFamilyViewController class]] )
                {
                    SFFamilyViewController *familyVC = (SFFamilyViewController *)subViewController;

                    [familyVC performSegueWithIdentifier:@"familyeditpet" sender:nil];
                    
                }
            }

        });

    2014年11月4日 星期二

    改掉Navigation Controller的back button事件

    //在viewDidLoad中加入這兩行,override返回鍵的方法
    self.navigationItem.backBarButtonItem.target = self;
    self.navigationItem.backBarButtonItem.action = @selector(backButtonDidPressed:);
    
    //宣告這個方法來執行你要在back前做的事
    - (void)backButtonDidPressed:(id)aResponder {
        //do your stuff
        //but don't forget to dismiss the viewcontroller
        [self.navigationController popViewControllerAnimated:YES];
    }

    2014年10月29日 星期三

    使用DataSource接外部資料提供自己的模組之用

    模組平常都是用delegate去呼叫外部method來當作Callback使用,然而我們也可以利用delegate來作為DataSource去接外部資料回來使用。

    //在.m中這樣呼叫你由外部輸入的Data
    NSString *myKey = [self.dataSource getMyKey:self];

    //在.h中這樣宣告
    @protocol ReportChartDataSource;

    @interface ReportChart : UIView

    @property (weak, nonatomic) id<ReportChartDataSource> dataSource;

    @property (nonatomic, readonly) ReportDuration duration;

    - (void)reloadData;
    - (void)reloadDataWithDuration:(ReportDuration)duration;

    @end

    //宣告實作
    @protocol ReportChartDataSource <NSObject>

    - (NSInteger) getMyKey:(ReportChart *)chart;

    @end

    NSMutableArray initWithCapacity 的用途

    對於Mutable的物件,init不會配置足夠的記憶體,隨著內容物件的增加而重新配置記憶體,這會造成效能上的損失,為了解決這個問題,我們可以使用這個方法,在初始化時就先指定之後會用到的記憶體大小給你的Array,但不用擔心overflow因為如果使用超過了,仍然會幫你增加。
    Returns an array, initialized with enough memory to initially hold a given number of objects.

    Return Value

    An array initialized with enough memory to hold numItems objects. The returned object might be different than the original receiver.

    Discussion

    Mutable arrays expand as needed; numItems simply establishes the object’s initial capacity.
    This method is a designated initializer.

    2014年10月28日 星期二

    對NSArray中的ManagedObjects做排序

    NSArray *recordMOArray = [self.petInfoMO.recordEntities allObjects];
        NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO];
        NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
        NSArray *sortedArray = [recordMOArray sortedArrayUsingDescriptors:sortDescriptors];
        
        NSDate* end = [NSDate date];

        NSDate* start = ((RecordMO *)[sortedArray firstObject]).date;

    2014年10月17日 星期五

    修改狀態列樣式

    Go to Info tab of the project target, Add Row:

    UIViewControllerBasedStatusBarAppearance, set value NO

    Then in appdelegate.m

    - (BOOL)application:(UIApplication *)application
        didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{

    [application setStatusBarStyle:UIStatusBarStyleLightContent];
    }

    判別iOS是否是64位元機器(pre-compile的code)

    #if __LP64__
        \\You're running on 64 bit
    #else
        \\You're running on 32 bit
    #endif

    2014年10月9日 星期四

    viewWillAppear在NavigationController下無法發揮作用

    先宣告<UINavigationControllerDelegate>
    然後再把NavigationController.delegate = self;

    - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
    {
        if ([viewController isEqual:self]) {
                [viewController viewWillAppear:animated];
        } else if ([viewController conformsToProtocol:@protocol(UINavigationControllerDelegate)]){
                // Set the navigation controller delegate to the passed-in view controller and call the UINavigationViewControllerDelegate method on the new delegate.
                [navigationController setDelegate:(id<UINavigationControllerDelegate>)viewController];
                [[navigationController delegate] navigationController:navigationController willShowViewController:viewController animated:YES];
        }
    }
    - (void)navigationController:(UINavigationController *)navigationController 
           didShowViewController:(UIViewController *)viewController 
                        animated:(BOOL)animated
    {
        if ([viewController isEqual:self]) {
            [self viewDidAppear:animated];
        }
    }

    不錯的iOS開發網站

    星期五Q&A
    https://mikeash.com/pyblog/

    2014年10月8日 星期三

    CoreData的資料型態

    我要的重點是decimal type是一種不會被四捨五入掉的小數型態!

    節錄自這本書「Core Data iOS Essentials」

    Types of attributes

    Using the Type drop-down list control, we select the data type (that is, numerical, string, date, and so on) of the attribute to specify the kind of information that can be stored in the attribute. The following is the list of data types:
    • Integer 16, Integer 32, and Integer 64 data types are for storing signed integers. The range of values that these types are able to store is as follows:
      • Integer 16:-32,768 to 32, 767
      • Integer 32:-2,147,483,648 to 2,147,483,647
      • Integer 64:-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
    • Decimal, Double, and Float data types are for storing fractional numbers. The Double data type uses 64 bits to store a value while the Float data type uses 32 bits for storing a value. The only limitation with these two data types is that they round off the values. To avoid any rounding of values, the Decimaldata type is preferred. The Decimal type uses fixed point numbers for storing values, so the numerical value stored in it is not rounded off.
    • String data type is used for storing text contents.
    • Boolean data type is used for storing YES or NO values.
    • Date data type is used for storing dates as well as timestamps.
    • Binary data type is used for storing binary data.
    • Transformable data type works along with Value Transformers that help us create attributes based on any Objective-C class, that is, we can create custom data types other than the standard data types. This data type can be used to store an instance of UIColor, UIImage, and so on. It archives objects to instances of NSData.

    2014年10月6日 星期一

    tableView顯示多層cell的動畫

    //有Cell出現的動畫
    [tableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationNone];

    //沒有動畫
    [tableView reloadData];

    要用reloadSections達到這樣子的動畫效果,可以用一個NSArray來包多個NSMutableArray代表不同的Section內容(二元矩陣),降子在改動MutableArray之後,才不會因為reloadSections造成程式crash。

    2014年9月30日 星期二

    iOS 8 Location 定位 失效

    一,先在Info.plist加入這二個Key(value是string,你可以不加,也可以加上Location is required to find out where you are之類的文字
    NSLocationAlwaysUsageDescription
    NSLocationWhenInUseUsageDescription

    二,在啟用location update之前加入這段,來要求權限
    // Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7.
            if ([_locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
    //要求權限:前景背景都允許使用定位
                [_locationManager requestAlwaysAuthorization];
            }
            if ([_locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
    //要求權限:只有在前景允許使用定位
                [_locationManager requestWhenInUseAuthorization];

            }

    取得iAP的receipt

    //取得iAPreceipt
    +(NSData *) getReceiptData:(SKPaymentTransaction *)transaction{
        NSData *receiptData = nil;
        if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
            receiptData = transaction.transactionReceipt;
        }
        else {
            NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle] appStoreReceiptURL]];
            NSError *error = nil;
            receiptData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:&error];
        }
        return receiptData;

    }

    2014年9月29日 星期一

    UUID保存在KeyChain裡面

    用這個方式將第一次取得的Vender UUID存到KeyChain內,
    之後換新App就可以取得之前UUID來充當UDID使用。

    https://github.com/ObjColumnist/MCSMKeychainItem

    單獨reload一個section

    [tableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationNone];

    2014年9月25日 星期四

    navigationController在push新view前,把tabBar隱藏起來

    有時候我們會想要用navigation bar來push一個新的view,但又不想要下面看到原本的tab bar,但限於navigation controller在 tabbar controller的階層下。又不想用present modal view的方式破壞原本的結構。

    這時候我們可以在push前把tab bar隱藏起來,在pop的時候記得要解開隱藏。
    程式碼:
            AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
            appDelegate.rootTabBarController.tabBar.hidden = YES;

            [self.navViewController pushViewController:main animated:YES];

    2014年9月24日 星期三

    繼承自managed object的class不能用object method存取

    因為xcode中自動產生的managed object,很容易因為修改db,而重新產生,
    所以習慣上,我會再寫一個managed object去繼承自動生成的來使用,
    然而今天發現用自己寫的class創建object仍然會被視為自動產生的那個class,造成object method無法被呼叫而發出例外。

    解決方式有兩種:
    一種是把object method寫進自動生成的managed object,但降子就背離了原來用繼承的原意,所以我採用第二種。
    第二種是把object method全部寫成class method。

    2014年9月22日 星期一

    [轉錄]plist解說

    本文轉錄自
    http://iphone4.tw/forums/showthread.php?t=195508
    kes729的文章

    1. Application does not run in background(鍵名:UIApplicationExistsOnSuspend)自從iOS4.0之後,當你在應用程式執行的時候按下Home鍵,應用程式並不會中斷目前的執行,而是躲到背景去了。因此希望使用者在按下Home鍵之後就要中斷目前程式的執行,請勾選這個選項。

    2. Application requires iPhone environment(鍵名:LSRequiresIPhoneOS)iOS的家族繫***ㄧ誒主要包含了iPhoneiPadiPod Touch這三種設備。因此如果你的應用程式只能在iPhone環境下使用的話,請勾選這選項。

    3. Application supports iTunes file sharing(鍵名:UIFileSharingEnabled)iTunes9.1之後的版本增加了一個檔案共享的功能,只要打開info.plist裡面的這個選項,然後把你要共享的檔案儲存在Documents目錄裡面,就可以在iTunes裡面的應用程式標籤頁看到這份文件。

    4. Application uses Wi-Fi(鍵名:UIRequiresPersistentWiFi)如果你的應用程式需要使用的WiFi來連線的話,那麼你可以開啓這個功能。當使用者在執行這個應用程式的時候並未開啓WiFi,那麼在畫面上會自動跳出對話框要求開啓WiFi

    5. Bundle creator OS Type code (鍵名:CFBundleSignature)CFBundleSignature是一個四個字母長度的字串,用以表示開發者對於應用程式的標識。例如:在一個文字編輯的應用程式,你可以標識為”ttext”

    6. Bundle display name(鍵名:CFBundleDisplayName)應用程式本土化的顯示名稱,預設值為${PRODUCT_NAME}。這個變數可以在雙敲擊Targets後出現的專案設定畫面中修改,找到”Product Name”後修改為你的產品名稱就可以了,編譯後的.app也會以這個名稱命名。

    7. Bundle identifier(鍵名:CFBundleIdentifier)用來標示應用程式的唯一ID,通常是以反向的DNS方式命名的,例如:com.myCompany.myApp,這個名稱應該在iTunes Connect裡面新增的應用程式ID一致。

    8. Bundle name(鍵名:CFBundleName)應用程式的短名稱,通常就是你的應用程式名稱。

    9. Bundle OS Type code(鍵名:CFBundlePackageType)用來標識整個封包的(bundle)的類型。在Mac裡面,一個封包可能是一個檔案或目錄,其目的在於將軟體使用到的資源包在一起。例如應用程式應標識為APPL

    10. Bundle version(鍵名:CFBundleVersion)用以標識編譯版本(Bundle number),你可以使用任何字串格式來表示這個版本。例如使用一個數字來表示編譯次數。

    11. Bundle version string,short (鍵名:CFBundleShortVersionString)應用程式的版本,通常是以三個數字來表示版本號,例如:1.0.1

    12. Executable architectures(鍵名:LSExcutableArchitectures)為一個陣列形態的設定值。用以設*****绦袚蹩梢赃\行的架構環境,例如:i386ppcppc64x86_64

    13. Executable file(鍵名:CFBundleExecutable)執行檔的名稱。

    14. Fonts provide by application(鍵名:UIAppFonts)為一個陣列形態的設定值。用來指定應用程式所使用的外部字型。你可以在應用程式內使用自己的字型檔,只要將字型檔案加入到專案內,在設定值指定字型檔名稱就可以在程式碼裡面使用到這些字型了。

    15. Get Info string (鍵名:CFBundleGetInfoString)用於MacFinder上的應用程式的描述。

    16. Icon already includes gloss effects(鍵名:UIPrerenderedIcon)指定應用程式的圖示是否加上光暈效果,如果不希望加上光暈效果,那麼勾選此選項。

    17. Icon file(鍵名:CFBundleIconFile)用來設定應用程式的圖示檔,如果沒有指定的話,則使用預設值Default.png,依照Apple的規定,這個圖是必須是57x57的圖形檔。

    18. Icon files(鍵名:CFBundleIconFiles)由於iPhoneiPad的開發工具以及SDK都是相同的,因此同一個應用程式也可以同時在兩個設備上使用,只不過兩著的圖是不太一樣。這個鍵值是一個陣列類型的設定值,用來指定iPhoneiPad的應用程式圖示,你只要給兩個圖示檔名,其中iPhone的圖示為57x57 pixeliPad則為72x72 pixel,系統會自動依照圖示大小判斷該圖示是使用在哪種設備上。

    19. Info dictionary version(鍵名:CFBundleInfoDictionaryVersion)info.plist格式的版本。一般來說,我們不會變動這個數值。

    20. Initial interface orientateon(鍵名:UIInterfaceOrientation)指定應用程式初始時的方向。

    21. Laumch image(鍵名:UILaunchImageFile)用以指定應用程式啓動時的圖檔。

    22. Localization native development region(鍵名:CFBundleDevelopmentRegion)應用程式原始的語系版本。

    23. Localizations(鍵名:CFBundleLocalizations)用以指定應用程式所支援的語系。

    24. Localized resources can be mixed(鍵名:CFBundleAllowedMimxedLocalizations)是否允許應用程式可以取得框架庫內的語系檔。

    25. Main nib file base name(鍵名:NSMainNibFile)主要的Nib檔案名稱,預設值為MainWindow

    26. Renders with edge antialisasing(鍵名:UIViewEdgeAntialiasing)設定core animation的圖層是否開啓抗鋸齒功能。

    27. Renders with group opacity(鍵名:UIViewGroupOpacity)設定core animation的圖層使否繼承上一層透明度。

    28. Required background modes(鍵名:UIBackgroundModes)設定當應用程式進入背景執行後,哪些動作要繼續在背景執行。這個鍵值是一個陣列類型的設定,可設定動作包括:audiolocateonvoip

    29. Required device capabilities(鍵名:UIRequiredDeviceCapabilities)設定應用程式需要使用到的硬體,如此可以確定應用程式在該設備上執行時不會發生錯誤。

    30. Status bar is initially hidden(鍵名:UIStatusBarHidden)設定狀態列是否一開始隱藏。

    31. Status bar style(UIStatusBarStyle)設定狀態列的顯示類型。

    32. Supported external accessory protocols(鍵名:UISupportedExternalAccessoryProtocols)指定應用程式與外界硬體配件間支援的通訊協定,這個鍵值是一個陣列設定,可以指定多個通訊協定。

    33. Supported interface orientateons(鍵名:UISupportedInterfaceOrientations)設定應用程式所支援的顯示模式(肖像模式或風景模式),這個鍵值是一個陣列,可以支援多個不同的顯示模式。

    34. Supported interface orientateons(鍵名:UIUpgradeOtherBundleIdentifier)設定應用程式所支援的顯示模式(肖像或是風景模式),這個鍵值可以支援多個不同的顯示模式。