2014年3月31日 星期一

同時支援 iOS6 與 iOS7

  • if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
  • // Load resources for iOS 6.1 or earlier
  • } else {
  • // Load resources for iOS 7 or later
  • }

2014年3月29日 星期六

自定義NavigationBar的Back鍵文字

UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStyleBordered target:nil action:nil];
        [self.navigationItem setBackBarButtonItem:backItem];
        

        [self.navigationController pushViewController:detailViewController animated:YES];

使用自己宣告的顏色

//在你的Class中新增一個UIColor的Category,在其中新增一些自定義的顏色

#pragma mark - Color Definition

@implementation UIColor (yourCategory)

+ (UIColor *) defaultColor
{
    return [UIColor colorWithRed:120.0/255 green:200.0/255 blue:120/255 alpha:1];
}



@end

設定TableViewCell文字顯示

self.textLabel.text = @"你要的Title";
//顏色
self.textLabel.textColor = [UIColor BlackColor];
//字型 大小
UIFont *myFont = [ UIFont fontWithName: @"Arial" size: 16.0 ];
self.textLabel.font  = myFont;

//置中
self.textLabel.textAlignment = NSTextAlignmentCenter;

在Mac OSX中製作加密的壓縮檔

打開終端機

//在Mac OSX中製作加密的壓縮檔
zip -e archivename.zip filetoprotect.txt

//在Mac OSX中製作加密的壓縮的資料夾
zip -er ~/Desktop/encrypted.zip ~/Documents/Confidential/


//要解壓縮 .xz的檔案
tar xvfJ filename.tar.xz

2014年3月28日 星期五

tableViewCell如果沒有給他textLabel的文字會視為nil

/*
tableViewCell如果沒有給他textLabel的文字,給空字串(@"")也一樣
在這裡讀到的textLabel會是nil
而不是沒有文字的textLabel
*/

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

   //因此如果我們要比對文字的話,要先給他一個文字(這裡是給空格)
   if( !cell.textLabel.text )
    {
        cell.textLabel.text = @" ";
    }
}

iOS7的TableView分格線(separator)

//在你的viewDidLoad實作

//分格線被imageView蓋住的問題
if ([self.tableView respondsToSelector:@selector(separatorInset)]) {
    [self.tableView setSeparatorInset:UIEdgeInsetsZero];
}

//分格線換顏色
self.tableView.separatorColor = [UIColor redColor];

2014年3月27日 星期四

for迴圈常犯問題

如果要在for迴圈中要push出UIView,一定要記得設break;

如果for是為了找東西,不是要全部跑完,一定要記得設break;

2014年3月26日 星期三

iOS7.1出現的如果把數字設為NSString會自動轉成NSNumber的問題

//結論,數字請以NSNumber存,文字再以NSString存,不然會不明不白地crash

//這裡把id物件強轉為String
NSString* accountString = (NSString*)[accountDetail objectForKey:@"id"];

//這裡在iOS7之後會crash,因為accountString裡面存的是數字,所以被自動轉為long,而並我們所認為的NSString
detailViewController.accountNumber = [[NSString alloc]initWithString: accountString];

2014年3月20日 星期四

UITableView didSelected事件在xib沒有作用的問題

去檢查右上角的Selection,如果是No Selection,就不再會觸發didSelected事件

手動以array設定 tab bar view controller

//先new幾個view controller
//...

self.tabBarController = [UITabBarController new];
    self.tabBarController.delegate = self;

//再把它們以Array的形式傳入tab bar controller
self.tabBarController.viewControllers = [NSArray arrayWithObjects:storeTab, mapTab, chatTab, aboutTab, nil];

//把tab bar controller設為rootViewController
    self.window.rootViewController = self.tabBarController;
    self.window.rootViewController.modalPresentationStyle = UIModalPresentationCurrentContext;
    [self.window makeKeyAndVisible];

2014年3月18日 星期二

i++與++i

如果與其他指令連用時,才會有差別(例如 用在for迴圈之中)

i++可以拆成i與++兩部份,其他指令會先對第一部份的i作用,之後對第二部份的++作用,而把i = i + 1
++i也可以視為兩部份,但其他指令無法對++作用,所以是對整體的i = i + 1之後的結果作用。

如果只是要把他當成單獨的i = i + 1來用;
則沒有什麼差異。

2014年3月15日 星期六

NavigationBar的LeftButton的顯示機制

NavigationBar的LeftButton的顯示機制
如果要從view1 push出view2,那麼顯示LeftButton的判斷順序如下
一,如果view2的NavigationItem有設定Left button,就顯示它。
二,如果view1有設定BackBarButtonItem,就顯示它。
三,如果上述都沒有,就用預設的顯示(左箭頭+view1的NavigationItem名稱)


上述第二點的sample code如下,
UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"Back" style:UIBarButtonItemStyleBordered target:nil action:nil];
        [self.navigationItem setBackBarButtonItem:backItem];

        [self.navigationController pushViewController:detailViewController animated:YES];

2014年3月13日 星期四

CoreBluetooth[WARNING] has no restore identifier but the delegate implements the centralManager:willRestoreState: method. Restoring will not be supported!

This is in regards to CoreBluetooth's save/restore optional feature, see "Opt In to State Preservation and Restoration" part of the documentation for more details.
What looks to be happening is that you are implementing the right delegate method to use this feature but you are not providing a restoration identifier in your call to initialize the CBCentralManager.
There are two options to resolve the warning:
  1. If you want to use this feature you should provide an identifier to CBCentralManager like so:
    myCentralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:@{ CBCentralManagerOptionRestoreIdentifierKey: @"myCentralManagerIdentifier" }];
  2. If you don't want to use this feature then remove the centralManager:willRestoreState:method from your delegate.
Doing either one should resolve your warning.

讓UITableView客製化的Cell不重覆出現的方法

//prepareForReuse會在cell被reuse時呼叫,在這裡把cell初始化就不會出現重覆顯示的問題
-(void)prepareForReuse{
    [super prepareForReuse];
    self.accessoryType = UITableViewCellAccessoryNone;
}

下面寫的方法雖然好用,但卻會造成Cell不被重覆使用的問題,造成大資料量時會吃光記憶體,所以正確的邏輯應該是,重覆使用相同的Cell,在prepareForReuse中把Cell的顯示畫面清空,再重新給他應該要有的畫面,而資料的正確對應關係,可以用Index.row與Data Array的index來對應!

//給UITableView裡的每個Cell一個唯一個Identifier
NSString *CellIdentifier = [NSString stringWithFormat:@"Cell%d%d", [indexPath section], [indexPath row]];
    
//如果TableView裡還有Cell的話,把cell叫出來使用
MerchandiseCell *cell = (MerchandiseCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    
//如果叫不出來cell,就new一個新的cell
if (cell == nil)
{
    cell = [[MerchandiseCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

}

//其中的MerchandiseCell就是我用來客製化的cell
//你可以新增一個屬於自己的TableViewCell,並在其中任意新增或修改View到你想到的排版,最後再像上面這code的MerchandiseCell的方式加入TableView即可。

//點選cell的事件,依舊可在TableView的delegate中didSelected觸發

//下面列出從客製化cell要取用自己寫的view的範例
-(void)setCustomViewWithMerchandiseInfo:(NSDictionary *)merchandiseInfo
{
    MerchandiseView *merchandiseView = (MerchandiseView *)[self.contentView viewWithTag:_merchandiseViewTag];
    BOOL _isMakeNew         = NO;
    if( !merchandiseView )
    {
        //merchandiseView  = [MerchandiseView new];
        merchandiseView = [[[NSBundle mainBundle] loadNibNamed:@"MerchandiseView" owner:self.contentView options:nil] objectAtIndex:0] ;
        [merchandiseView setTag:_merchandiseViewTag];
        //設定圓角
        [merchandiseView.backGroundView.layer setCornerRadius:10];
        [merchandiseView.backGroundView.layer setMasksToBounds:YES];
        
        //設定圖片的url位址
        if (![[merchandiseInfo objectForKey:@"pictures"]isEqual:[NSNull null]]) {
            NSArray* pictures = [merchandiseInfo objectForKey:@"pictures"][0];
            NSLog(@"picture:%@",pictures);
            //Api有提供5個圖片尺寸,這裡取用第4:320*320
            NSURL *url = [NSURL URLWithString:[pictures[3] objectForKey:@"url"]];
            UIImage *urlImage = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:url]];
            merchandiseView.pictureImageView.image = urlImage;
        }
            //設定商品名稱
        merchandiseView.nameLabel.text = [NSString stringWithFormat:@"%@",[merchandiseInfo objectForKey:@"name"]];
        
        _isMakeNew = YES;
    }
    
    [merchandiseView setUserInteractionEnabled:YES];
    if( _isMakeNew )
    {
        [self.contentView addSubview:merchandiseView];
    }
}

-(CGFloat)getCustomViewHeight
{
    MerchandiseView *merchandiseView = (MerchandiseView *)[self.contentView viewWithTag:_merchandiseViewTag];
    return merchandiseView.frame.size.height;

}

layoutSubviews:
1、init不會觸發layoutSubviews
2、addSubview會觸發layoutSubviews
3、設置view的Frame會觸發layoutSubviews,前提是frame的值有所變動
4、捲動UIScrollView會觸發layoutSubviews
5、旋轉Screen會觸發父UIView上的layoutSubviews事件
6、改變一個UIView大小的時候也會觸發父UIView上的layoutSubviews事件
- (void)layoutSubviews {
    [super layoutSubviews];
    self.imageView.frame = CGRectMake(2,2,40,40);
}

//給不同的identifier不同的nib
[self.tableView registerNib:[UINib nibWithNibName:@"YourCell" bundle:nil]; forCellReuseIdentifier:PhotoCellIdentifier];

2014年3月12日 星期三

把UIView設定成正圓形

//View設定成正圓形
        [profileImageView.layer setCornerRadius:profileImageView.frame.size.width / 2];
        [profileImageView.layer setMasksToBounds:YES];
//在View外面加上白框
        CALayer *_viewLayer = profileImageView.layer;
        UIColor *_borderColor    = [UIColor whiteColor];
        _viewLayer.borderColor   = [_borderColor CGColor];
        _viewLayer.borderWidth   = 2.0f;
        _viewLayer.shadowColor   = [[UIColor grayColor] CGColor];
        _viewLayer.shadowOffset  = CGSizeMake(0, 2);
        _viewLayer.shadowOpacity = 0.5;

        _viewLayer.shadowRadius  = 5.0f;

2014年3月11日 星期二

「無條件進位」、「無條件捨去」、「四捨五入」、「滿千加逗號」

// 四捨五入
round(number);
// 無條件捨去
down = floor(number);
// 無條件進位
up = ceil(number);


//所有的數字轉文字的格式,都可以在NSNumberFormatter class中找到。
//滿千加逗號
+ (NSString *)formatNumberWithComma:(NSNumber *)number
{
    NSNumberFormatter *formatter = [[NSNumberFormatter alloc]init];
    //設顯示小數點下第二位
    [formatter setMaximumFractionDigits:2];
    //設千分位的逗點
    [formatter setUsesGroupingSeparator:YES];
    [formatter setNumberStyle:NSNumberFormatterDecimalStyle];
        
    double entryFieldFloat = [number doubleValue];
    if ([number.stringValue rangeOfString:@"."].length == 1) {
        formatter.alwaysShowsDecimalSeparator = YES;
        return [formatter stringFromNumber:[NSNumber numberWithDouble:entryFieldFloat]];
    }
    
    formatter.alwaysShowsDecimalSeparator = NO;
    return [formatter stringFromNumber:[NSNumber numberWithDouble:entryFieldFloat]];

}

2014年3月10日 星期一

取用特定的Subview實體

//我們想要指定一個View去取用
UIImageView *iv = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"btn"]];
            [iv setTag:978];

//直接用viewWithTag就可以針對我們想取用的View去抓到實體
UIView *_subview = [cell.contentView viewWithTag:978];
                if( _subview )
                {
                    [_subview removeFromSuperview];
                }

在switch中要加上判斷的code,要用{ }大刮號

NSString *title, *subtitle;
        switch (indexPath.row) {
            case PROFILE_NAME:
                title = @"User name";
                subtitle = _userEntity.name;
                break;
            case PROFILE_BIRTHDAY:
                title = @"Birthday";
                subtitle = [_userEntity.birthday yyyy__MM__dd];
                break;
            case PROFILE_HEIGHT:
                title = @"Height";
                if (unitUSA) {
                    NSInteger feet, inch;
                    [UserEntity translateMeter:_userEntity.height.integerValue toFeet:&feet inch:&inch];
                    subtitle = [NSString stringWithFormat:@"%d'%d\"", feet, inch];
                } else
                    subtitle = [NSString stringWithFormat:@"%d cm", _userEntity.height.integerValue];
                break;
            case PROFILE_WEIGHT:
                title = @"Weight";
                subtitle =unitUSA ? [NSString stringWithFormat:@"%.1f lbs", [UserEntity translateLbFromKg:_userEntity.weight.integerValue]] : [NSString stringWithFormat:@"%d kg", _userEntity.weight.integerValue];
                break;
            case PROFILE_STRIDE:
                title = @"Stride";
                subtitle = unitUSA ? [NSString stringWithFormat:@"%d\"", (int)(_userEntity.stride.integerValue / 2.54)] : [NSString stringWithFormat:@"%d cm", _userEntity.stride.integerValue];
                break;
            case PROFILE_EMAIL:
                title = @"Email";
                subtitle = [apis getUserEmail];
            {
                UIView *_subview = [cell.contentView viewWithTag:978];
                if( _subview )
                {
                    [_subview removeFromSuperview];
                }
                
            }
                break;
            default:
                break;

        }

一次移除所有subview的方式

[[someUIView subviews]
 makeObjectsPerformSelector:@selector(removeFromSuperview)];

2014年3月6日 星期四

UIAlertView的慣用法

//UploadViewController.h

@interface UploadViewController : UIViewController <UIAlertViewDelegate>



//UploadViewController.m

- (IBAction)logoutPressed:(id)sender
{
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Logout" message:@"Are you sure you want to logout?" delegate:self cancelButtonTitle:@"NO" otherButtonTitles:@"YES", nil];
    [alert show];
}

- (void)logout
{
    //TODO:Implement Logout code here...
}


#pragma mark - UIAlertView Delegate

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == alertView.firstOtherButtonIndex) {
        [self logout];
    }

}

2014年3月3日 星期一

NSMutableArray的addObject是直接加入pointer而不是copy一份進去

NSMutableArray *array = [NSMutableArray new];
NSNumber *number = [[NSNumber new];
For (int i = 0, i<10 , i++){
   number = [NSNumber numberWithInt:i];
   [array addObject:number];
}
這樣的結果會是
10
10
10
10
10
10
10
10
10
10


NSMutableArray *array = [NSMutableArray new];
For (int i = 0, i<10 , i++){
   NSNumber *number = [[NSNumber new];
   number = [NSNumber numberWithInt:i];
   [array addObject:number];
}
而這樣的結果才會是
1
2
3
4
5
6
7
8
9
10

2014年3月2日 星期日

抓取另一個storyboard上的view controller

YourViewControllerClass *viewController = [[UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil] instantiateViewControllerWithIdentifier:@"ViewController"];