顯示具有 iOS 標籤的文章。 顯示所有文章
顯示具有 iOS 標籤的文章。 顯示所有文章

2015年8月21日 星期五

[iOS] 上架須知

終於把iOS App上架了!

上架需要的幾個步驟花了我不少時間,在這邊記錄一下以免忘記

step1 : (當然首先已經有帳號了)

https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/wa/signOutCompleted

進入itunes connect 選擇 我的app



選左上角的+號,就會有出現一串需要設定的包刮icon,版權,截圖等等.....

特別需要注意的就是截圖,

如果你的版本支援5.5吋(iphone 6 plus),4.7吋(iphone 6),4吋(5/5s),3.5吋(4/4s)的話,

那必須要把這些截圖都對應尺寸放上去,否則是無法通關的!

接下來就是程式上傳,該如何上傳呢??

這邊是使用xcode 6.x上傳,以下為示範


在模擬器的部份必須要選擇iOS Device,然後才能在product 選擇 Archieve *沒選的話會變

成灰色不能按

在build/version的部份 也必須要特別注意(圖片中間偏右邊可以看到)

如果你已經上傳同一個version / build的話,那當然就是不能重複上傳,不然會有error!

進入到archieve的部份代表上傳已經完成到一半了(如果沒有錯誤就上傳完成,回到itunes

connect,選擇版本然後就可以上傳,不過需要花一些些時間才看的到,剛開始上傳是看不到

的)

這邊遇到一些問題ex: need 120x 120 icon 之類的



app icon + launch Image 這幾個是一定要填入的icon,

可以透過這個網站來製作


可以看一下是否有images.xcassets的警告,如果有很可能會過不了!

都完成以後,就可以順利上架囉! 審核時間還不確定多長,只能說一定比android長!


2015年7月13日 星期一

[iOS] 滑動式可模糊文字顯示框(PAC Blurry Scroll View)


一樣是逛cocoa controls逛到的一個元件,覺得很有用因此就把它拿來用了

(不過沒想到有點難操作0rz)

PACScrollView

步驟只有三到四步,基本上也是把檔案先copy進去專案,然後  #import (有import才能夠使用該元件)

不外乎就github上基本的操作:

Basic usage

First, import PACBlurryScrollView.h header in th e .h file.
XIB way :
just add a scrollView in your Xib file and change the class type to PACBlurryScrollView
then, add the following code
    [pacScrollView setBackgroundImage:[UIImage imageNamed:@"bg.jpg"]];
Code way
    PACBlurryScrollView *pacScrollView = [[PACBlurryScrollView alloc] initWithFrame:self.view.bounds];
    [pacScrollView setBackgroundImage:[UIImage imageNamed:@"bg.jpg"]];
    [self.view addSubview:pacScrollView];
Don't forget to add content to your scrollView !
上面意思是說有兩種方法
1.XIB檔拉一個ScrollView,改class為PACBlurryScrollView,程式碼裡面增加這一行:
[pacScrollView setBackgroundImage:[UIImage imageNamed:@"bg.jpg"]];

2.第二種當然就是使用coding

    PACBlurryScrollView *pacScrollView = [[PACBlurryScrollView alloc] initWithFrame:self.view.bounds];
    [pacScrollView setBackgroundImage:[UIImage imageNamed:@"bg.jpg"]];
    [self.view addSubview:pacScrollView];

初始化一個pacScrollview格式,然後後續差不多,最後一定要addSubView!


以為這樣教學就結束了嗎?

如果你希望一開始的模糊感就有的話,就需要調整一下他原本的.m file

在PACBlurryScrollView.m這邊有一行

[_backgroundImageLayer setOpacity:(1.0f - (self.contentOffset.y / (self.contentSize.height - self.frame.size.height)))];

[_backgroundBlurryImageLayer setOpacity:(1.0f - _backgroundImageLayer.opacity)];

把1.0f調整為0.5f 就可以看出效果囉!

本次的教學就到這邊 END

2015年7月9日 星期四

[iOS] 處理iphone4/4s 與iphone5/5s 和 iphone 6/6 plus 尺寸不同問題(xib file)

在開發iOS的時候一定會遇到當不同機身(4s,5s,6,6plus)介面會跑掉的問題!

而這個問題也讓我苦惱了一個禮拜,網路上沒有非常好的解法(stackoverflow有,不過你要看

的懂他寫的,而且解法非完美要結合另一篇才行)


首先,概念其實很簡單,為每一個xib檔案配一個不同尺寸的xib檔(也就是各尺寸各一)

然後,判定現在的機型是哪一種,iphone 4s ? 5/5s? 6? 6 plus? 決定要套用哪一個xib檔案

該怎樣判定呢?

先定義螢幕長寬吧!

#define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width)
#define SCREEN_HEIGHT ([[UIScreen mainScreen] bounds].size.height)
#define SCREEN_MAX_LENGTH (MAX(SCREEN_WIDTH, SCREEN_HEIGHT))
#define SCREEN_MIN_LENGTH (MIN(SCREEN_WIDTH, SCREEN_HEIGHT))

#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_RETINA ([[UIScreen mainScreen] scale] >= 2.0)

#define iPhone4s_or_less (IS_IPHONE && SCREEN_MAX_LENGTH < 568.0)
#define iphone5 (IS_IPHONE && SCREEN_MAX_LENGTH == 568.0)
#define iphone6 (IS_IPHONE && SCREEN_MAX_LENGTH == 667.0)

#define iphone6plus (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0)

接著我們需要在initWithNibName()這邊判斷

現在是4s,5,6,6plus

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    if (iphone6plus) {
        NSLog(@"iphone 6 +");
        self = [super initWithNibName:@"Page2_6_plus" bundle:nibBundleOrNil];
    }
    else if(iphone6)
    {
        NSLog(@"iphone 6");
        self = [super initWithNibName:@"Page2_6" bundle:nibBundleOrNil];
    }
    else if (iphone5) {
        NSLog(@"iphone 5/5s ");
        self = [super initWithNibName:@"Page2_5s" bundle:nibBundleOrNil];
    }
    else{
        NSLog(@"iphone 4s ");
        self = [super initWithNibName:@"Page2" bundle:nibBundleOrNil];
    }
    
    return self;
    
}

當然,也是要把xib檔案複製->改名為相對應的名稱,這樣一來,就完成囉!

end

[iOS] 特效進度條(ASProgressPopupView)的使用方法

在Code4app網站中找到一個不錯的特效包--ASProgressPopupView


點此連結到Code4app


上面寫的很簡單,但實際使用起來卻不是這樣

"使用方法:


self.progressView.font = [UIFont fontWithName:@"Futura-CondensedExtraBold" size:26]; 
self.progressView.popUpViewAnimatedColors = @[[UIColor redColor], [UIColor orangeColor], [UIColor greenColor]]; 
self.progressView.popUpViewCornerRadius = 16.0;"

實際在github上的描述是:

github

How to use it

It’s very simple. Drag a UIProgressView into your Storyboard/nib and set its class to ASProgressPopUpView – that's it. The example below demonstrates how to customize the appearance.
self.progressView.font = [UIFont fontWithName:@"Futura-CondensedExtraBold" size:26];
self.progressView.popUpViewAnimatedColors = @[[UIColor redColor], [UIColor orangeColor], [UIColor greenColor]];
self.progressView.popUpViewCornerRadius = 16.0;
To show the popUpView, just call:
[self.progressView showPopUpViewAnimated:YES];
And to hide:
[self.progressView hidePopUpViewAnimated:YES];
You update the value exactly as you would normally use a UIProgressView, just update theprogress property self.progressView.progress = 0.31;
詳細的可以去github上面看

這邊的教學:
1.先把下面這四個檔案copy進去專案,然後在你要寫的.m file裡面新增
#import "ASValueTrackingSlider.h"
2.開啟你的xib file,拉一個slider進去畫面,把class改為ASValueTrackingSlider
然後把該元件拉到.m file產生一個名叫slider1的物件

可以看到他的屬性是ASValueTrackingSlider,不是uislider,是的話就搞錯囉!

接著我們就可以使用slider1來做事情(控制他)

3.為了讓我的進度條上面顯示的文字最後面都有個"V",所以這邊要增加三行(第一行是宣告)

    NSNumberFormatter *voltFormatter = [[NSNumberFormatter alloc] init];
    [voltFormatter setPositiveSuffix:@"V"];
    [voltFormatter setNegativeSuffix:@"V"];
再來就是一些基本的設定
    self.slider1.popUpViewCornerRadius = 12.0;
    [self.slider1 setNumberFormatter:voltFormatter];
    [self.slider1 setMaxFractionDigitsDisplayed:0];
    self.slider1.popUpViewColor = [UIColor colorWithHue:0.55 saturation:0.8 brightness:0.9 alpha:0.7];
    self.slider1.font = [UIFont fontWithName:@"GillSans-Bold" size:22];
    self.slider1.popUpViewAnimatedColors = @[[UIColor redColor], [UIColor orangeColor], [UIColor greenColor]];
//這邊是讓我前中後段的顏色有不同

    [self.slider1 showPopUpViewAnimated:YES];
//這一段一定要show不然他不會顯示文字出來


如果是要有%數的話則改用這段

    NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
    [formatter setNumberStyle:NSNumberFormatterPercentStyle];
    [self.slider1 setNumberFormatter:formatter];
    self.slider1.popUpViewAnimatedColors = @[[UIColor greenColor], [UIColor orangeColor], [UIColor redColor]];
   self.slider1.font = [UIFont fontWithName:@"Futura-CondensedExtraBold" size:26];
    [self.slider1 showPopUpViewAnimated:YES];

又或者你想要到某個區段就顯示某些文字的話,請加入這一行

self.slider1.dataSource = self;

然後加入這一段

- (NSString *)slider:(ASValueTrackingSlider *)slider stringForValue:(float)value;
{
    value = roundf(value);
    NSString *s;
    if (value < 30) {
        s = @"Warning!! Low Voltage";
    } else if (value > 29.0 && value < 50.0) {
        s = [NSString stringWithFormat:@"😎 %@ 😎", [slider.numberFormatter stringFromNumber:@(value)]];
    } else if (value >= 50.0) {
        s = [NSString stringWithFormat:@"%dV", value];
    }
    return s;
}

最後,完成版本就像這樣~



























然後如果要調整他的弧度的話(邊角弧度)


self.slider2.popUpViewCornerRadius = 12.0;

這邊可以調整


希望大家都能夠開心使用,(畢竟作者沒有講很清楚,我也摸了一會兒才會),end

2015年6月9日 星期二

[iOS] 如何儲存使用者設定?(NSUserDefaults) / 類似Android的SharedPreferences

相信大家寫的app如果有登入之類的東西一定會遇到一個問題,就是儲存使用者設定!

不然每次叫使用者重新輸入應該會崩潰吧?!


--------------------------------------------------------------------------------------------------------------------------


正文開始:

Step1:

先到.h檔 (看是appdelegate.h or ViewController.h)

宣告一個NSUserDefaults屬性的變數

//
//  AppDelegate.h
//
//  Created by daniel on 2015/4/29.
//  Copyright (c) 2015 daniel. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "AsyncUdpSocket.h"
#define global ((AppDelegate *)[[UIApplication sharedApplication] delegate])

@interface AppDelegate : UIResponder <UIApplicationDelegate>
{
    NSUserDefaults *userDefaults;

}

這樣我們就可以在.m file內使用該變數(userDefaults)



Step2:

在.m file內的viewdidload()這裡面(反正就是第一個讀到的地方)

先初始化我們的userDefaults,這一部很重要!!沒有初始化會叫不出儲存的東西!!

初始化:userDefaults = [NSUserDefaults standardUserDefaults];

接下來就是儲存/讀取

儲存:

    NSString *string = @"192.168.0.1";
    [userDefaults setObject:string forKey:@"store IP"];

    NSArray *array = @[@"123",@"456"];
    [userDefaults setObject:array forKey:@"Array"];

    BOOL isValid = YES;
    [userDefaults setBool: isValid forKey:@"isValid"];

    int number = 100;
    [userDefaults setInteger:number forKey:@"number"];

可以看到上述四種不同的類型(nsstring,nsarray,BOOL,int)

大致上都是一樣的,差別只是在於setXXX(類型)

格式:(儲存)

[NSUserDefaults型態變數  setObject(或其他型態): 變數名稱 forKey: @"隨意取key 名稱"]

格式:(讀取)

[NSUserDefaults型態變數 stringforKey: @"隨意取key 名稱"]

(或是valueforKey:)

範例:NSString *store_ip = [userDefaults stringForKey:@"store IP"];


*****非常重要*****

在儲存完畢以後,要記得!!

[NSUserDefaults型態變數 synchronize];

如果沒有這行,就不會真正儲存到硬碟裡面!

完成以後,就可以透過這樣的方式來儲存使用者設定了:)

END


2015年6月4日 星期四

[iOS] NSData NSMutableData append / NSString to Char 等問題解法

不是我要說iOS,轉來轉去每個都好麻煩0rz

好吧!

首先,這邊目標是:結合NSString + char[] ,最後變成NSData輸出

NSString *myString = @"123abcdfhhhhhhh";
char *aa = [myString UTF8String];

NSLog(@"%s",aa);
NSLog(@"%lu",sizeof(aa));

NSLog(@"%lu",(unsigned long)[myString length]);

這邊設定一個string ,然後讓他轉utf8格式放到char指標裡面


nslog會顯示

2015-06-04 15:55:32.897 v1.0[4462:60b] 123abcdfhhhhhhh
2015-06-04 15:55:32.898 v1.0[4462:60b] 4

2015-06-04 15:55:32.900 v1.0[4462:60b] 15

所以要特別注意sizeof()並不是mystring分開後的個數,而是4byte 

因為這個錯誤搞了半天0rz.....

到這邊已經很順利的把nsstring 改為char了,但是要怎樣把這兩樣結合呢?


    const unsigned char two[]    = {80 ,67 ,77 ,83 , 2 ,2};//第二個char[]
    
    NSMutableData * muData = [[NSMutableData alloc] init];//用來結合的容器
    
    NSMutableData * data = [NSData dataWithBytes:two length:sizeof(two)];
    NSMutableData * data2 = [NSData dataWithBytes:aa length:[myString length]];//這邊要用length


------------------結合--------------------

   [muData appendData:data];
   [muData appendData:data2];

------------------結合--------------------

    NSString *strData = [[NSString alloc]initWithData:muData encoding:NSUTF8StringEncoding];
   
    NSLog(@"%@",strData);

最後輸出成NSString 方便nslog看成果為如何?


2015-06-04 15:55:43.650 v1.0[4462:60b] PCMS123abcdfhhhhhhh


最後使用


NSData *aData = [strData dataUsingEncoding: NSASCIIStringEncoding];

轉為NSData~


完成!

end

2015年5月26日 星期二

[iOS]NSString & EXC_BAD_ACCESS ERROR solution

問題:

使用全域變數NSString *string,使用時候出現exc_BAD_ACCESS???


答案:


@property (nonatomic,retain)NSString *string;

不可以使用assign 要使用retain!


解決!

end

[iOS] Switch Case Error : switch case in protected scope

錯誤代碼:switch case in protected scope

解決方法:

case 1:

{
    code....

}

break;

case 2:

{
   code2....
 
}

break;


解決! end

2015年5月15日 星期五

[iOS] 可展開/收和型的tableView

在找expantable listview,結果找了半天沒有找到,

原來是android叫做listview,ios則是叫做tableview!

這次在.h file完全不用作任何事情,所以就不說.h file了!

原始檔案在這邊:

http://code4app.com/ios/ExpansionTableView/5121cac66803fae949000002

是參考這個弄出來的


------------------------------------------------------------------------------------------------------------------

首先,如果你有開ARC的話,那不需要release/dealloc之類的

第一步:

在viewDidLoad裡面加入

    NSString *path  = [[NSBundle mainBundle] pathForResource:@"ExpansionTableTestData" ofType:@"plist"];//指定要去哪一個檔案名稱,檔案類型找,放進去path裡面

    _dataList = [[NSMutableArray alloc] initWithContentsOfFile:path];


pathForResource這邊是檔案名稱 

ofType則是檔案類型

所以我們要讀取的列表就是ExpansionTableTestData.plist這個檔案


顯然還沒宣告_dataList,所以在前面interface下面就要先宣告一個

NSMutableArray *_dataList;


像這樣

@interface Page3 ()<UITableViewDataSource,UITabBarDelegate>
{
    NSMutableArray *_dataList;
}
@property (assign)BOOL isOpen;
@property (nonatomic,retain) NSIndexPath *selectIndex;
@property (nonatomic,retain) IBOutlet UITableView *expansionTableView;

@end

@implementation Page3
@synthesize isOpen,selectIndex;

紅色部分為新增的


再來就是新增加建構子,

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return [_dataList count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (self.isOpen) {
        if (self.selectIndex.section == section) {
            return [[[_dataList objectAtIndex:section] objectForKey:@"list"] count]+1;;
        }
    }
    return 1;
}

//iphone 5以下可以用float,5s~6 plus CGFloat
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 40;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (self.isOpen&&self.selectIndex.section == indexPath.section&&indexPath.row!=0) {
        static NSString *CellIdentifier = @"Cell2";
        Cell2 *cell = (Cell2*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        
        if (!cell) {
            cell = [[[NSBundle mainBundle] loadNibNamed:CellIdentifier owner:self options:nil] objectAtIndex:0];
        }
        NSArray *list = [[_dataList objectAtIndex:self.selectIndex.section] objectForKey:@"list"];
        cell.titleLabel.text = [list objectAtIndex:indexPath.row-1];
        return cell;
    }else
    {
        static NSString *CellIdentifier = @"Cell1";
        Cell1 *cell = (Cell1*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (!cell) {
            cell = [[[NSBundle mainBundle] loadNibNamed:CellIdentifier owner:self options:nil] objectAtIndex:0];
        }
        NSString *name = [[_dataList objectAtIndex:indexPath.section] objectForKey:@"name"];
        cell.titleLabel.text = name;
        [cell changeArrowWithUp:([self.selectIndex isEqual:indexPath]?YES:NO)];
        return cell;
    }
}


#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    //展開items,開始判斷式
    if (indexPath.row == 0) {
        //第一層
        if ([indexPath isEqual:self.selectIndex]) {
            self.isOpen = NO;
            [self didSelectCellRowFirstDo:NO nextDo:NO];//進入下一段函式
            self.selectIndex = nil;
            
        }else
        {
            if (!self.selectIndex) {
                self.selectIndex = indexPath;
                [self didSelectCellRowFirstDo:YES nextDo:NO];
                
            }else
            {
                
                [self didSelectCellRowFirstDo:NO nextDo:YES];
            }
        }
        
    }else
    {
        //第二層
        NSDictionary *dic = [_dataList objectAtIndex:indexPath.section];
        NSArray *list = [dic objectForKey:@"list"];
        NSString *item = [list objectAtIndex:indexPath.row-1];
        //顯示點擊的item
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:item message:nil delegate:nil cancelButtonTitle:@"取消" otherButtonTitles: nil];
        [alert show];//跳出訊息
    }
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}


- (void)didSelectCellRowFirstDo:(BOOL)firstDoInsert nextDo:(BOOL)nextDoInsert
{
    self.isOpen = firstDoInsert;
    
    Cell1 *cell = (Cell1 *)[self.expansionTableView cellForRowAtIndexPath:self.selectIndex];
    [cell changeArrowWithUp:firstDoInsert];//疑似把箭頭往上?
    
    [self.expansionTableView beginUpdates];
    
    int section = self.selectIndex.section;
    int contentCount = [[[_dataList objectAtIndex:section] objectForKey:@"list"] count];
    NSMutableArray* rowToInsert = [[NSMutableArray alloc] init];
    for (NSUInteger i = 1; i < contentCount + 1; i++) { //第二層有幾行 content count
        NSIndexPath* indexPathToInsert = [NSIndexPath indexPathForRow:i inSection:section];
        [rowToInsert addObject:indexPathToInsert];
    }
    
    if (firstDoInsert)
    {   [self.expansionTableView insertRowsAtIndexPaths:rowToInsert withRowAnimation:UITableViewRowAnimationTop];
    }
    else
    {
        [self.expansionTableView deleteRowsAtIndexPaths:rowToInsert withRowAnimation:UITableViewRowAnimationTop];
    }
    
    //[rowToInsert release];
    
    [self.expansionTableView endUpdates];
    if (nextDoInsert) {
        self.isOpen = YES;
        self.selectIndex = [self.expansionTableView indexPathForSelectedRow];
        [self didSelectCellRowFirstDo:YES nextDo:NO];
    }
    if (self.isOpen) [self.expansionTableView scrollToNearestSelectedRowAtScrollPosition:UITableViewScrollPositionTop animated:YES];
}

然後我們要建構xib檔,拉出一個table view (記得要選autolayer)

然後要與@property (nonatomic,retain) IBOutlet UITableView *expansionTableView;

這一行做連結(滑鼠右鍵拉過去connect)

















然後還要把dataSource/delegate也連結到file's Owner

如果要修改列表的內容,就要去expansiontabletestdata.plist那邊修改喔!

完整檔案在code4app可以下載,這邊就不附上囉!

end

2015年5月11日 星期一

[iOS] 可輸入文字(textfield)之警告視窗(alertview)

又遇到問題,於是找了方法來解決


android上面的alertview十分簡單(custom的部份)

iOS呢?是否一樣簡單?

[ iOS 7 + Xcode 6.3.1 ]


第一次看別人的code:


    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"輸入IP" message:@" " delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:@"確認",nil];
    UITextField * txt = [[UITextField alloc] init];
    txt.backgroundColor = [UIColor whiteColor];
    txt.frame = CGRectMake(alert.center.x+65,alert.center.y+48, 150,23);
    [alert addSubview:txt];

    [alert show];

結果有跳出警告視窗,但是沒有可以輸入的阿!

於是就繼續查,才發現要加上

alert.alertViewStyle = UIAlertViewStylePlainTextInput;


正確版本:

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"輸入IP" message:@" " delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:@"確認",nil];
    alert.alertViewStyle = UIAlertViewStylePlainTextInput;
    UITextField * txt = [[UITextField alloc] init];
    txt.backgroundColor = [UIColor whiteColor];
    txt.frame = CGRectMake(alert.center.x+65,alert.center.y+48, 150,23);
    [alert addSubview:txt];
    [alert show];

當然style也有password/default(無法顯示)/login..之類的,大家可以自行嘗試喔!

end