2014年8月24日 星期日

iOS 開發筆記 - UICollectionView resize after device rotation

最近在把玩 UICollectionView 並著手處理 resize 的時機點,經 StackOverflow - Change UICollectionViewCell size on different device orientations 的討論,純 coding without storyboard 時,需處理兩件事:

  • - (CGSize)collectionView:layout:sizeForItemAtIndexPath:
  • - (void)didRotateFromInterfaceOrientation:

就像在 UITableViewController 時,告訴 ViewController 這個 UITableViewCell 到底有多高,只是在 UICollectionViewCell 時,還能定義有多寬;在 didRotateFromInterfaceOrientation 事件中,則是告訴 UIViewController 更新畫面。

只是單純上述兩者並無法改變已經存在的 UICollectionViewCell ,對於已經存在的,必須強制處理,簡言之,需要再多幾件事:

  • 在 - (void)didRotateFromInterfaceOrientation: 時,請記得重新定義 UICollectionView frame 資訊,並且使用 [yourCollectionView reloadData] 的方式重繪資料
  • 在 - (UICollectionViewCell *)collectionView:cellForItemAtIndexPath: 中,若每一個 UICollectionViewCell 並非有規則的,則需要動態偵測並重新設定 frame 資訊
如此一來,就能達到 auto resize 的效果了 Orz  若沒這麼龜毛,大概用一下 Storyboard 就解掉了 XD

2014年8月23日 星期六

iOS 開發筆記 - UITextAlignmentLeft/UITextAlignmentCenter/UITextAlignmentRight is deprecated first deprecated in ios 6.0

從 UITextAlignment* 改用 NSTextAlignment* 即可。

iOS 開發筆記 - Use UICollectionView without Storyboard and XIB


最近才發現這個 Class ,真是乃覺三十里 XD 有可能已經習慣自己刻 UITableViewCell 了 Orz 所以一直沒去學習新技能,這次看到一些特效後,原本以為單純手動安排 View 變化,仔細一看才發現 UICollectionView 啦,就順手筆記一下,此外,坊間多為使用 Storyboard、XIB 的做法。
  1. Create an ViewControler extends UIViewController
  2. Add UICollectionView *collectionView property
  3. Init collectionView with UICollectionViewFlowLayout
  4. Use UICollectionViewDelegate and UICollectionViewDataSource
  5. Implement collectionView:numberOfItemsInSection: and collectionView:cellForItemAtIndexPath:
如此一來,就可以動了 XD

//
// TestCollectionViewController.h:
//
#import <UIKit/UIKit.h>

@interface TestCollectionViewController : UIViewController
@property (nonatomic, strong) UICollectionView *collectionView;
@end


//
// TestCollectionViewController.m:
//
#import "TestCollectionViewController.h"

@interface TestCollectionViewController () <UICollectionViewDelegate, UICollectionViewDataSource>

@end

@implementation TestCollectionViewController

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return 10;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewCell * collectionViewCell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
    
        CGFloat comps[3];
        for (int i = 0; i < 3; i++)
            comps[i] = (CGFloat)arc4random_uniform(256)/255.f;
        collectionViewCell.backgroundColor = [UIColor colorWithRed:comps[0] green:comps[1] blue:comps[2] alpha:1.0];
    return collectionViewCell;
}

- (UICollectionView *)collectionView
{
    if (!_collectionView) {
        UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
        flowLayout.itemSize = CGSizeMake(100, 100);
        flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
     
        _collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, 300, 300) collectionViewLayout:flowLayout];
        _collectionView.delegate = self;
        _collectionView.dataSource = self;
        _collectionView.backgroundColor = [UIColor whiteColor];
        [_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"Cell"];
    }
    return _collectionView;
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
 
    [self.view addSubview:self.collectionView];
 
    // Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

2014年8月22日 星期五

[PHP] 擴充 Mantis SOAP API 、處理 DB Query 心得

前置準備:
  • soap api source code 就擺在 mantis/api/soap 中
  • 記得清掉 SoapServer 跟 SoapClient 的 cache 資料,可以用 ini_set("soap.wsdl_cache_enabled", 0); 或是在 new SoapServer 或 SoapClient 時,指定 'cache_wsdl' => WSDL_CACHE_NONE 資訊
預計新增一個 api 名為 mc_user_group ,需要做的動作:
  • 規劃 mc_user_group 的 input 跟 output 資訊,此例 input 為 username, password,而 output 是 ObjectRefArray,由於都是既定 type ,所以不需額外定義
  • 更新 WSDL 定義,可以從已存在的 mc_enum_access_levels api 來仿照
    • <message name="mc_enum_groupRequest">
      <part name="username" type="xsd:string" />
      <part name="password" type="xsd:string" /></message>
      <message name="mc_enum_groupResponse">
      <part name="return" type="tns:ObjectRefArray" /></message>
    • <operation name="mc_enum_group">
      <documentation>Get the enumeration for group</documentation>
      <input message="tns:mc_enum_groupRequest"/>
      <output message="tns:mc_enum_groupResponse"/>
      </operation>
    • <operation name="mc_enum_group">
      <soap:operation soapAction="http://www.mantisbt.org/bugs/api/soap/mantisconnect.php/mc_enum_group" style="rpc"/>
      <input><soap:body use="encoded" namespace="http://futureware.biz/mantisconnect" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></input>
      <output><soap:body use="encoded" namespace="http://futureware.biz/mantisconnect" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></output>
      </operation>
  • 實作 function mc_enum_group( $p_username, $p_password ),若此 function 定義在其他檔案內,記得要更新 mantis/api/soap/mc_core.php 即可
如此一來,就完成擴充 Mantis SOAP api 的任務了,記得要把 Server 跟 Client 的 SOAP Cache 都必須清掉才會正常,不然 client site 會看到類似的訊息(扣除還沒實作的情況):

PHP Fatal error:  Uncaught SoapFault exception: [SOAP-ENV:Server] Procedure 'your_func' not present

以下是片段程式碼:

// Client
$TARGET_API='https://host/mantis/api/soap/mantisconnect.php?wsdl';
ini_set("soap.wsdl_cache_enabled","0");
$c = new SoapClient($TARGET_API);

// debug
// print_r($c->__getFunctions ());

print_r( $c->mc_enum_group($user, $pass) );


// Server
        require_once( 'mc_core.php' );
        ini_set("soap.wsdl_cache_enabled","0");
        $server = new SoapServer("mantisconnect.wsdl",
                        array('features' => SOAP_USE_XSI_ARRAY_TYPE + SOAP_SINGLE_ELEMENT_ARRAYS)
        );
        $server->addFunction(SOAP_FUNCTIONS_ALL);
        $server->handle();


其他心得:

  • 自定 Mantis SOAP API 時,需要留意 input, output 的地方,假設 output 的是 ObjectRefArray 形態,那輸出只能有 id, name ,其他欄位都會被濾掉
  • Mantis SOAP API 使用上要留意權限問題,例如發 issue 用的帳號,若是 repoter 的等級,不能去做 assign monitors 的行為,會有權限問題,有問題時,可以試著用 mc_issue_add 跟 mc_issue_update 交叉測試。

最後,再補一個 DB 操作方式,output 仍以 ObjectRefArray 為例:

function mc_enum_group( $p_username, $p_password ) {
        $t_user_id = mci_check_login( $p_username, $p_password );
        if ( $t_user_id === false ) {
                return mci_soap_fault_login_failed();
        }
         
        $t_result = array();
         
        $query = "SELECT * FROM mantis_user_table";
     
        $result = db_query( $query );
        //file_put_contents('/tmp/debug', print_r($result, true) );

// 此例把 username 充當回傳的 name 資訊、user id 當作回傳 id 資訊
        for( $i=0, $cnt=db_num_rows($result) ; $i<$cnt; ++$i ) {
                $row = db_fetch_array( $result );
                $obj = new stdClass();
                $obj->id = $row['id'];
                $obj->name = $row['username'];
                array_push( $t_result, $obj );
        }    
        return $t_result;
}

2014年8月21日 星期四

[Linux] 安裝 nicstat @ Ubuntu 12.04

在 Ubuntu 14.04 只需用 atp-get install nicstat 即可,但在 12.04 就得自己編了:

$ sudo apt-get install gcc gcc-multilib
$ cd /tmp
$ wget -qO- http://nchc.dl.sourceforge.net/project/nicstat/nicstat-1.92.tar.gz | tar -xvzf -
$ cp /tmp/nicstat-1.92/Makefile.Linux /tmp/nicstat-1.92/Makefile
$ cd /tmp/nicstat-1.92 && make && sudo make install