2012年8月17日 星期五

grocer - 另一個 APNS 選擇

https://github.com/highgroove/grocer

好處:支援中文,支援度、擴充性更高

C:\Users\APNS>gem install grocer
Fetching: grocer-0.1.0.gem (100%)
Successfully installed grocer-0.1.0
1 gem installed
Installing ri documentation for grocer-0.1.0...
Installing RDoc documentation for grocer-0.1.0...



$pusher = Grocer.pusher(
  certificate: 'C:\Users\Ruby\APNS\push_test.pem',
  gateway:     "gateway.sandbox.push.apple.com" # optional;  defaults to gateway.push.apple.com.
)


n = Grocer::Notification.new(
      device_token: '12345',
      alert:        "Hello iPhone!",
      badge:        1)
$pusher.push(n)

Gem for APNS

PS: 這個版本 目前送中文會有問題

A gem for the Apple Push Notification Service


C:\Users\user\>gem install apns
Fetching: apns-0.9.0.gem (100%)
Successfully installed apns-0.9.0
1 gem installed
Installing ri documentation for apns-0.9.0...
Installing RDoc documentation for apns-0.9.0...


push.rb
require 'rubygems'
require 'apns'
# https://github.com/jpoz/APNS
    # APNS.host = 'gateway.push.apple.com'
    # gateway.sandbox.push.apple.com is default
    # APNS.pem  = '/path/to/pem/file'
    # this is the file you just created
   
    # APNS.port = 2195
    # this is also the default. Shouldn't ever have to set this, but just in case Apple goes crazy, you can.
APNS.pem  = 'C:\Users\APNS\apns.pem'
    device_token = '123abc456def'
    APNS.send_notification(device_token, 'Hello iPhone!' )
    APNS.send_notification(device_token, :alert => 'Hello iPhone!', :badge => 1, :sound => 'default')

如何在 Windows 上 安裝 Thin

如果安裝 Thin 一直出現這樣的錯誤
 error: cannot convert 'stat*' to '_stati64*' for argument '2' to 'int _fstati64(int
, _stati64*)'



參考來源
ruby - Cannot install thin on windows - Stack Overflow

假設已經裝好 DevKit
還沒裝好請參考 Development Kit · oneclick/rubyinstaller Wiki · GitHub

C:\Users\user>gem install eventmachine --pre
Fetching: eventmachine-1.0.0.rc.4-x86-mingw32.gem (100%)
Successfully installed eventmachine-1.0.0.rc.4-x86-mingw32
1 gem installed
Installing ri documentation for eventmachine-1.0.0.rc.4-x86-mingw32...
Installing RDoc documentation for eventmachine-1.0.0.rc.4-x86-mingw32...

C:\Users\user>gem install thin
Fetching: daemons-1.1.9.gem (100%)
Fetching: thin-1.4.1.gem (100%)
Temporarily enhancing PATH to include DevKit...
Building native extensions.  This could take a while...
Successfully installed daemons-1.1.9
Successfully installed thin-1.4.1
2 gems installed
Installing ri documentation for daemons-1.1.9...
Installing ri documentation for thin-1.4.1...
Installing RDoc documentation for daemons-1.1.9...
Installing RDoc documentation for thin-1.4.1...


2012年8月14日 星期二

PageControl



active_page_image.png
inactive_page_image.png


GrayPageControl.h

#import <UIKit/UIKit.h>

@interface GrayPageControl : UIPageControl
{
    UIImage* activeImage;
    UIImage* inactiveImage;
}

@end



GrayPageControl.m


#import "GrayPageControl.h"

@implementation GrayPageControl

-(id) initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    
    activeImage = [UIImage imageNamed:@"active_page_image.png"];
    inactiveImage = [UIImage imageNamed:@"inactive_page_image.png"];
    
    return self;
}

-(void) updateDots
{
    for (int i = 0; i < [self.subviews count]; i++)
    {
        UIImageView* dot = [self.subviews objectAtIndex:i];
        if (i == self.currentPage) dot.image = activeImage;
        else dot.image = inactiveImage;
    }
}

-(void) setCurrentPage:(NSInteger)page
{
    [super setCurrentPage:page];
    [self updateDots];
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
}
*/

@end

PickerViewController



PickerViewController.h


#import <UIKit/UIKit.h>


@interface PickerViewController : UIViewController
<UIPickerViewDelegate, UIPickerViewDataSource>

@property (nonatomic, strong) IBOutlet UIPickerView *modelPicker;
@property (nonatomic, strong) NSArray *modelArray;
@property (nonatomic, strong) NSArray *memoryArray;
@property (nonatomic, strong) IBOutlet UILabel *modelLabel;
@property (nonatomic, strong) IBOutlet UILabel *memoryLabel;

@end



PickerViewController.m

#import "PickerViewController.h"

@interface PickerViewController ()

@end

@implementation PickerViewController
@synthesize modelPicker, memoryArray, modelArray;
@synthesize memoryLabel, modelLabel;

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.modelArray = [[NSArray alloc] initWithObjects:
                       @"iPad WiFi", @"iPad WiFi+3G (AT&T)",
                       @"iPad WiFi+3G (Verizon)", nil];
    
    self.memoryArray = [[NSArray alloc] initWithObjects:
                        @"16GB", @"32GB", @"64GB", nil];
}




#pragma mark -
#pragma mark PickerView DataSource

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
    
    return 2;
}

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
    
    if (component == 0) {
        return [modelArray count];
    }
    return [memoryArray count];
}

- (NSString *)pickerView:(UIPickerView *)pickerView
             titleForRow:(NSInteger)row
            forComponent:(NSInteger)component
{
    if (component == 0) {
        return [modelArray objectAtIndex:row];
    }
    return [memoryArray objectAtIndex:row];
}


#pragma mark -
#pragma mark PickerView Delegate

-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row
      inComponent:(NSInteger)component
{
    if (component == 0)
    {
        NSString *resultString = [[NSString alloc] initWithFormat:
                                  @"Model: %@",
                                  [modelArray objectAtIndex:row]];
        self.modelLabel.text = resultString;
    } else {
        NSString *resultString = [[NSString alloc] initWithFormat:
                                  @"Memory: %@",
                                  [memoryArray objectAtIndex:row]];
        self.memoryLabel.text = resultString;
    }
}


- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    self.memoryArray = nil;
    self.modelArray = nil;
    self.modelLabel = nil;
    self.memoryLabel = nil;
}


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

@end




2012年8月10日 星期五

Sinatra

on Windows

首先需要 安裝 Ruby
選擇安裝 Ruby Installer 一鍵安裝 免設定
在這邊安裝的版本是 Ruby 1.9.3-p194

打開 Command Line
確認一下環境&版本

C:\Users\user>ruby -v

ruby 1.9.3p194 (2012-04-20) [i386-mingw32]

C:\Users\user>gem -v

1.8.23


安裝 Sinatra

C:\Users\user>gem install sinatra

Fetching: rack-1.4.1.gem (100%)

Fetching: rack-protection-1.2.0.gem (100%)

Fetching: tilt-1.3.3.gem (100%)

Fetching: sinatra-1.3.2.gem (100%)

Successfully installed rack-1.4.1

Successfully installed rack-protection-1.2.0

Successfully installed tilt-1.3.3

Successfully installed sinatra-1.3.2

4 gems installed

Installing ri documentation for rack-1.4.1...

Installing ri documentation for rack-protection-1.2.0...

Installing ri documentation for tilt-1.3.3...

Installing ri documentation for sinatra-1.3.2...

Installing RDoc documentation for rack-1.4.1...

Installing RDoc documentation for rack-protection-1.2.0...

Installing RDoc documentation for tilt-1.3.3...

Installing RDoc documentation for sinatra-1.3.2...

寫個測試程式

# myapp.rb
require 'sinatra'

get '/' do
  'Hello world!'
end


執行

C:\Users\user>ruby myapp.rb
[2012-08-10 15:36:21] INFO  WEBrick 1.3.1
[2012-08-10 15:36:21] INFO  ruby 1.9.3 (2012-04-20) [i386-mingw32]
== Sinatra/1.3.2 has taken the stage on 4567 for development with backup from WEBrick
[2012-08-10 15:36:21] INFO  WEBrick::HTTPServer#start: pid=140360 port=4567


就跟他的網頁一樣

簡潔


製作 APNS 憑證
How to build an Apple Push Notification provider server (tutorial)

gem for APNS
https://github.com/jpoz/APNS

如何載入預設資料,使用 Core Data

Core Data on iOS 5 Tutorial: How To Preload and Import Existing Data

裡面提到兩種方式

  1. 執行App時,從其他資料匯入到資料戶,例如 JSON, XML, PLIST。
  2. 提供已經載入資料的資料庫。

在這裡我個人是採用第二種方式,

原因是,在邊寫程式邊調整資料庫的結構時,

最後也把資料庫弄好,並且整理好了,

所以在 App 第一次啟動時,

在 Core Data 初始化之前,需要先判斷 .sqlite 檔是否已經存在,

(Core Data 是 基於 SQLite 技術的物件式關連資料庫)

不存在,把之前準備好的資料庫檔 .sqlite (放在 App 的資料夾裡,跟 .h .m 放一起)

複製到 App 的 Document 目錄即可。


沒有採用第一種方式的原因是,

需要判斷是否已經載入之外,

還得另外寫匯入程式,

因為懶惰的關係,所以採用第二種方式唷!