自訂iOS選取器 附農曆選取器代碼

來源:互聯網
上載者:User

1.鑒於模擬器和真機的滾動效果的差異,建議大家真機調試的時候注釋掉IDJScrollComponent.m裡的如下內容:

 
  1. self.decelerationRate=0; 

2.My Code中使用了iOS5.0的UIImage的縮放圖片的resizableImageWithCapInsets:方法,如果你使用的是iOS5.0以下的SDK,請替換為stretchableImageWithLeftCapWidth:topCapHeight:方法。

3.幾處BUG:

(1.)copy的我忘記釋放記憶體了。

 
  1. NSString *pYear=[cal.year copy]; 
  2. NSString *pMonth=[cal.month copy]; 

這個pYear, pMonth沒釋放!

(2.)UITableViewCell的釋放有些問題。

cellForRowAtIndexPath方法裡面, cell的初始化有以下三種情況,

 
  1. cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 
  2. cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
  3. cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]; 

假設是調用這句 cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 初始化

然後最後return [cell autorelease]; 就有問題了!

這樣改, 把另外2種初始化改成

 
  1. cell=[[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 
  2. cell=[[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease]; 

然後最後return cell;就OK了。

(3.)演算法的局限性。

IDJScrollComponent.m裡的moveSubViews:方法由於演算法欠妥,導致了一個局限性,就是滾輪圖片的高度必須是可以被顯示的行數整除的數字,譬如:我的例子日期顯示三行,那麼滾輪的圖片高度就是177像素的,177恰好可以被3整除。

(4.)農曆資料提供器IDJChineseCalendar.mm的- (id)initWithYearStart:(NSUInteger)start end:(NSUInteger)end:方法:

 
  1. //擷取當年的西曆年份對應的農曆的年代和甲子年份 
  2. std::pair p=ChineseCalendarDB::GetEraAndYearOfLunar([self.year intValue]); 

需要移動到

 
  1. //設定目前時間的農曆日期欄位 
  2. self.year=[NSString stringWithFormat:@"%d", chineseDate.GetYear()]; 

的後面。

這個控制項並不是對iOS內建的UIPickerView貼圖,而是重新實現,我一周多的成果,期間走了不少彎路。哈!

此控制項開發的原因:

最近有個需求,需要做一個農曆的日期滾輪選取器,一開始想用iOS內建的UIPickerView,但是設計人員要求的比較高,必須實現她要求的樣式,也就是中大家看到的樣式。但是UIPickerView根本沒有提供可以定製樣式(也就是更換皮膚)的介面。首先我在論壇上找到了文章,按照這位兄台所述,確實可以在一定程度上修改UIPickerView的圖片,我之所以說一定程度上,有以下幾個原因:

(1.)他是用覆蓋原有的UIPickerView上的各個子視圖片的方法做的,那麼你提供新的圖片就必須與原圖片嚴絲合縫。這也說明,即便是圖片換了,樣式也是不能換的,譬如:分割線的粗細、上下左右的邊框的大小等,也就是不能完全DIY,不能滿足我的需求。

(2.)由於覆蓋UIPickerView上的各個子視圖片的做法不是蘋果官方給出的,一旦以後某個版本的UIPickerView實現策略改變,例如:3號子視圖不再是滾輪的背景圖片,你的做法就掛了。

於是我就實現了中的滾輪選取器,它與UIPickerView的區別是:

(1.)皮膚圖片提供了方法可以做替換的。

(2.)可以選擇滾輪上的資料是否迴圈滾動。

(3.)可以指定選擇條的位置。

為了代碼的複用,也就是所謂的OOP,我按照以下的方式實現(因為我覺得這個滾輪選取器的實現方案其實算不上亮點,因為有很多的方案可以選擇的,但是程式的結構、代碼的重用是很重要的):

(1.)pickerview目錄:這個目錄中的IDJPickerView.h是滾輪選取器視圖,沒有任何和與資料相關的東西,也就是你可以在IDJPickerView上顯示任何資料。IDJPickerView通過委託擷取需要顯示的資料。這個目錄下的IDJScrollComponent.h實現了UIScrollView上的內容可以反覆迴圈滾動的功能。

(2.)datepicker目錄:IDJDatePickerView.h實現了IDJPickerView裡的協議,並把IDJPickerView做為自己的一個私人成員,實現了一個可以根據type欄位顯示西曆、農曆的日期選取器,IDJDatePickerView.m裡的農曆演算法用的是solar_chinese_calendar目錄中的C++演算法,因此農曆的相關資料類使用了C++混編的代碼。其實iOS自己支援農曆的,但是存在BUG,具體的原因大家可以看我的IDJChineseCalendar.mm的源碼,裡面的注釋比較詳細的。我在這裡也使用了一層封裝,也就是IDJDatePickerView.m本身也不提供資料,而是通過IDJCalendar.h、IDJChineseCalendar.h、IDJCalendarUtil.h來提供,這樣既實現了資料與視圖的分離(因為農曆演算法太複雜了,直接寫在IDJDatePickerView.m裡會使得代碼看起來可讀性太差了),而且把C++的調用封裝在了資料層,使得IDJDatePickerView.m的視圖層代碼不會出現C++的API。

(3.)timepicker目錄:這個目錄純粹是一個Demo,展示了一個不迴圈滾動、顯示行數與選中條位置不對稱的選取器,沒有什麼實際的含義。

一開始我是純粹寫農曆的選取器,代碼都是耦合在一起的,後來逐個拆開的,這樣代碼就可以複用了,不僅僅是農曆選取器,而是可以承載任何資料。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.