2015年4月29日 星期三

[iOS] Tab Bar分頁+UDP通訊

不知道怎樣寫分頁或是怎樣做UDP通訊嗎??

最近好不容易弄出了一點樣子,把它記錄起來,以免以後忘記.

首先分頁是使用tab bar元件-GG Tab Bar(https://github.com/Goles/GGTabBar)

,讓分頁切成四塊(同時建立四個.h+.m+.xib檔案)

可以看到有分了Page1,2,3,4分頁,以及對應的xib檔


首先,先在各個page.m裡面新增:


- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        self.tabBarItem = [[UITabBarItem alloc] initWithTitle:nil
                                                        image:[UIImage imageNamed:@"user_normal"]
                                                selectedImage:[UIImage imageNamed:@"user_pressed"]];
    }
    return self;
}

(image的部份就是要自己找圖或是下載source code,名稱自行調整,但需要對應到Images.xcassets裡面的檔案名稱)


step2: AppDelegate.h+m的部份

AppDelegate.h

#import <UIKit/UIKit.h>

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

@interface AppDelegate : UIResponder <UIApplicationDelegate>
{
    AsyncUdpSocket *udpSocket;
    NSTimer *timer;
    long tag;
}
@property (strong, nonatomic) UIWindow *window;
@property (nonatomic,retain) NSMutableArray *globalData;


@end


AppDelegate.m


#import "AppDelegate.h"
#import "GGTabBarController.h"
#import "Page1.h"
#import "Page2.h"
#import "Page3.h"
#import "Page4.h"


@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    
    NSLog(@"open");
    
    global.globalData = [[NSMutableArray alloc] initWithCapacity:300];
    
    udpSocket = [[AsyncUdpSocket alloc] initWithDelegate:self];
    NSError *error = nil;
    [udpSocket bindToPort:2601 error:&error]; //綁定一個port 讓發送的source port / 指定接收的port 都是這一個
    [udpSocket receiveWithTimeout:-1 tag:0];//Start listening for a UDP packet.
    timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(sender) userInfo:nil repeats:YES];
    
    GGTabBarController *tabBar = [[GGTabBarController alloc] init];
    
    Page1 *vc1 = [[Page1 alloc] init];
    Page2 *vc2 = [[Page2 alloc] init];
    Page3 *vc3 = [[Page3 alloc] init];
    Page4 *vc4 = [[Page4 alloc] init];
    
    tabBar.viewControllers = @[vc1, vc2, vc3, vc4];
    self.window.rootViewController = tabBar;
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

- (void)applicationWillTerminate:(UIApplication *)application {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

//Server 接收
-(BOOL) onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port
{
    //NSLog(@"in server");
    Byte *convert_to_byte = (Byte *)[data bytes];
    int length = data.length;
    //NSLog(@"length = %d",length);
    int receive[length];
    NSNumber *number;
    NSMutableArray *intArray = [[NSMutableArray alloc] init];
    
    for (int i = 0 ; i < [data length]; i++) {
        //printf("conver to byte = %d\n",convert_to_byte[i]);
        int combine = (int)convert_to_byte[i];
        //NSLog(@"%ld",combine);
        receive[i] = combine;
        number =[NSNumber numberWithInt:combine];
        [intArray addObject:number];
        NSLog(@"number =%@",number);
        //[global.globalData addObject:number];
        //NSLog(@"i=%@",global.globalData[i]);
        
        NSLog(@"%d",receive[i]);//詳細接收
    }
    [global.globalData setArray:intArray];
    [intArray removeAllObjects];
    
    for(int i = 0; i < global.globalData.count; i++){
        NSLog(@"i=%@",[global.globalData objectAtIndex:i]);
    }
    
    NSLog(@"global-data count= %lu",(unsigned long)global.globalData.count);
    
    //receive要解析,
    [udpSocket sendData:data toHost:host port:port withTimeout:-1 tag:0];
    [udpSocket receiveWithTimeout:-1 tag:0];
    return YES;
}


-(void) sender{
    //NSLog(@"timer");
    const unsigned char byte[] = {80,67,77,71,1,69,78,68};
    NSData *data = [NSData dataWithBytes:byte length:sizeof(byte)];
    [udpSocket sendData:data toHost:@"210.202.53.147" port:2601 withTimeout:-1 tag:tag];
}

@end

step3 : 建立udp通訊

這部份在前幾篇有講到附上網址:udp通訊part

(不過這部份已經有寫在上面了)



做完通訊,又有tab bar分頁功能以後,就是把分頁內容建立好囉!

教學到此結束,end.


[iOS] NSArray / NSMutableArray 與 全域變數

貓這次遇到的問題是,我需要一個全域變數而且是陣列,但是這個陣列需要可以變動式的.

因此NSArray就被排除在外面,講到NSArray就稍微講一下,基本上他是不能添加或減少任何元

素的,所以要改用mutable版本.


首先,第一步我們要在appdelegate.h這個檔案define一個全域的變數


#define global ((AppDelegate *)[[UIApplication sharedApplication] delegate])

global可以換成任何你想要的文字

然後還要宣告一個@property


@property (nonatomic, retain) NSMutableArray *globalData;

(globalData一樣可以換任何文字)


第二步,切換到appdelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    global.globalData = [[NSMutableArray alloc] initWithCapacity:300];
    
    return YES;

}

//初始化NSMutableArray

然後就可以使用囉!這邊可以用下面的for迴圈來看內容是什麼

    for(int i = 0; i < global.globalData.count; i++){
        NSLog(@"i=%@",[global.globalData objectAtIndex:i]);

    }

然後因為這是全域變數,所以不管在viewcontroller1,2,3,4....都可以看到這個變數

使用方法一樣是global.globalData來呼叫他,下一篇搭配UDP來操作,這次的教學完畢

end