ฉันหลีกเลี่ยงการใช้UITableViewController
เพราะมันทำให้ความรับผิดชอบจำนวนมากเป็นวัตถุชิ้นเดียว ดังนั้นฉันจึงแยกUIViewController
คลาสย่อยออกจากแหล่งข้อมูลและผู้รับมอบสิทธิ์ ความรับผิดชอบของตัวควบคุมมุมมองคือการเตรียมมุมมองตารางสร้างแหล่งข้อมูลด้วยข้อมูลและเชื่อมโยงสิ่งเหล่านั้นเข้าด้วยกัน การเปลี่ยนวิธีการแสดง tableview นั้นสามารถทำได้โดยไม่ต้องเปลี่ยนคอนโทรลเลอร์มุมมองและแน่นอนว่าสามารถใช้คอนโทรลเลอร์มุมมองเดียวกันสำหรับแหล่งข้อมูลหลายแหล่งที่เป็นไปตามรูปแบบนี้ การเปลี่ยนเวิร์กโฟลว์ของแอปหมายถึงการเปลี่ยนแปลงตัวควบคุมมุมมองโดยไม่ต้องกังวลว่าจะเกิดอะไรขึ้นกับตาราง
ฉันได้ลองแยกUITableViewDataSource
และUITableViewDelegate
โปรโตคอลเป็นวัตถุที่แตกต่างกัน แต่ที่มักจะกลายเป็นการแบ่งที่ผิดพลาดเพราะเกือบทุกวิธีในผู้รับมอบสิทธิ์ต้องขุดลงในแหล่งข้อมูล (เช่นในการเลือกผู้เข้าร่วมประชุมต้องรู้ว่า แถวที่เลือก) ดังนั้นฉันจึงลงเอยด้วยวัตถุเดียวนั่นคือทั้งแหล่งข้อมูลและตัวแทน วัตถุนี้จะให้วิธีการ-(id)tableView: (UITableView *)tableView representedObjectAtIndexPath: (NSIndexPath *)indexPath
ที่ทั้งแหล่งข้อมูลและผู้รับมอบสิทธิ์ต้องรู้ว่าพวกเขากำลังทำอะไรอยู่
นั่นคือการแยก "ระดับ 0" ของความกังวล ระดับ 1 มีส่วนร่วมถ้าฉันต้องแสดงวัตถุต่าง ๆ ในมุมมองตารางเดียวกัน ตัวอย่างเช่นสมมติว่าคุณต้องเขียนแอปผู้ติดต่อ - สำหรับผู้ติดต่อรายเดียวคุณอาจมีแถวที่แสดงหมายเลขโทรศัพท์แถวอื่น ๆ แทนที่อยู่อื่น ๆ แทนที่อยู่อีเมลและอื่น ๆ ฉันต้องการหลีกเลี่ยงวิธีการนี้:
- (UITableViewCell *)tableView: (UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath {
id object = [self tableView: tableView representedObjectAtIndexPath: indexPath];
if ([object isKindOfClass: [PhoneNumber class]]) {
//configure phone number cell
}
else if …
}
สองวิธีได้นำเสนอตัวเองจนถึงขณะนี้ หนึ่งคือการสร้างตัวเลือกแบบไดนามิก:
- (UITableViewCell *)tableView: (UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath {
id object = [self tableView: tableView representedObjectAtIndexPath: indexPath];
NSString *cellSelectorName = [NSString stringWithFormat: @"tableView:cellFor%@AtIndexPath:", [object class]];
SEL cellSelector = NSSelectorFromString(cellSelectorName);
return [self performSelector: cellSelector withObject: tableView withObject: object];
}
- (UITableViewCell *)tableView: (UITableView *)tableView cellForPhoneNumberAtIndexPath: (NSIndexPath *)indexPath {
// configure phone number cell
}
ในวิธีการนี้คุณไม่จำเป็นต้องแก้ไขแผนผังif()
ลำดับต้นเพื่อรองรับชนิดใหม่ - เพียงเพิ่มวิธีที่รองรับคลาสใหม่ นี่เป็นวิธีการที่ยอดเยี่ยมหากมุมมองตารางนี้เป็นเพียงสิ่งเดียวที่ต้องการแสดงวัตถุเหล่านี้หรือต้องการนำเสนอในรูปแบบพิเศษ หากวัตถุเดียวกันจะถูกแสดงในตารางต่าง ๆ ที่มีแหล่งข้อมูลที่แตกต่างกันวิธีการนี้จะพังเพราะวิธีการสร้างเซลล์ต้องใช้ร่วมกันข้ามแหล่งข้อมูล - คุณสามารถกำหนดซูเปอร์คลาสทั่วไปที่ให้วิธีการเหล่านี้หรือคุณสามารถทำได้:
@interface PhoneNumber (TableViewRepresentation)
- (UITableViewCell *)tableView: (UITableView *)tableView representationAsCellForRowAtIndexPath: (NSIndexPath *)indexPath;
@end
@interface Address (TableViewRepresentation)
//more of the same…
@end
จากนั้นในคลาสแหล่งข้อมูลของคุณ:
- (UITableViewCell *)tableView: (UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath {
id object = [self tableView: tableView representedObjectAtIndexPath: indexPath];
return [object tableView: tableView representationAsCellForRowAtIndexPath: indexPath];
}
ซึ่งหมายความว่าแหล่งข้อมูลใด ๆที่ต้องการแสดงหมายเลขโทรศัพท์ที่อยู่ ฯลฯ สามารถถามวัตถุใดก็ได้ที่แสดงแทนเซลล์มุมมองตาราง แหล่งข้อมูลเองไม่จำเป็นต้องรู้อะไรเกี่ยวกับวัตถุที่กำลังแสดงอีกต่อไป
"แต่เดี๋ยวก่อน" ฉันได้ยิน interject ของ interlocutor สมมุติ "นั่นไม่ทำลาย MVC ใช่ไหมคุณไม่ใส่รายละเอียดการดูลงในคลาสโมเดล"
ไม่ไม่ทำลาย MVC คุณสามารถคิดประเภทในกรณีนี้เป็นการดำเนินการของมัณฑนากร ; เพื่อให้PhoneNumber
เป็นชั้นรูปแบบ แต่PhoneNumber(TableViewRepresentation)
เป็นหมวดหมู่มุมมอง แหล่งข้อมูล (วัตถุคอนโทรลเลอร์) เป็นสื่อกลางระหว่างโมเดลและมุมมองดังนั้นสถาปัตยกรรม MVC จึงยังคงมีอยู่
คุณสามารถเห็นการใช้หมวดหมู่นี้เป็นของตกแต่งในกรอบงานของ Apple เช่นกัน NSAttributedString
เป็น class model โดยมีข้อความและคุณสมบัติ AppKit ให้บริการNSAttributedString(AppKitAdditions)
และ UIKit ให้บริการNSAttributedString(NSStringDrawing)
หมวดหมู่มัณฑนากรที่เพิ่มพฤติกรรมการวาดภาพให้กับคลาสรุ่นเหล่านี้