ฉันจะสร้างคลาสมุมมอง iOS ที่กำหนดเองและสร้างอินสแตนซ์สำเนาหลายชุด (ใน IB) ได้อย่างไร


114

ฉันกำลังสร้างแอพที่จะมีตัวจับเวลาหลายตัวซึ่งโดยพื้นฐานแล้วจะเหมือนกันทั้งหมด

ฉันต้องการสร้างคลาสแบบกำหนดเองที่ใช้โค้ดทั้งหมดสำหรับตัวจับเวลาตลอดจนเค้าโครง / ภาพเคลื่อนไหวดังนั้นฉันจึงมีตัวจับเวลาที่เหมือนกัน 5 ตัวที่ทำงานแยกกัน

ฉันสร้างเลย์เอาต์โดยใช้ IB (xcode 4.2) และโค้ดทั้งหมดสำหรับตัวจับเวลาขณะนี้อยู่ในคลาส viewcontroller

ฉันมีปัญหาในการห่อสมองของฉันเกี่ยวกับวิธีการห่อหุ้มทุกอย่างลงในคลาสที่กำหนดเองแล้วเพิ่มลงในตัวควบคุมมุมมองความช่วยเหลือใด ๆ จะได้รับการชื่นชมมาก


สำหรับใครก็ตามที่ไปที่นี่ ... ตอนนี้เป็นเวลาห้าปีแล้วที่มุมมองคอนเทนเนอร์จะมาถึง iOS! มุมมองคอนเทนเนอร์เป็นแนวคิดพื้นฐานที่สำคัญในการทำทุกอย่างใน iOS ตอนนี้ พวกเขาจะง่ายอย่างเหลือเชื่อที่จะใช้และมีหมายเลขใด ๆ ของบทเรียนที่ดีเยี่ยม (ห้าปีเก่า!) ในมุมมองของภาชนะรอบ ๆตัวอย่างเช่น , ตัวอย่างเช่น
Fattie

2
@JoeBlow ยกเว้นคุณไม่สามารถใช้มุมมองคอนเทนเนอร์ในUITableViewCellหรือUICollectionViewCell. ในกรณีของฉันฉันต้องการมุมมองที่เล็ก แต่ค่อนข้างซับซ้อนซึ่งฉันสามารถใช้หลาย ๆ ครั้งในตัวควบคุมและมุมมองคอลเลกชัน และนักออกแบบยังคงนำมันมาปรับปรุงใหม่ดังนั้นฉันต้องการให้มีการกำหนดเค้าโครงไว้ที่เดียว ดังนั้นปลายปากกา
Echelon

คำตอบ:


142

ดีที่จะตอบแนวคิดเวลาของคุณมีแนวโน้มที่ควรจะเป็น subclass ของแทนUIViewNSObject

ในการสร้างอินสแตนซ์ของตัวจับเวลาของคุณใน IB เพียงแค่ลากตัวจับเวลาออกจากUIViewมุมมองของตัวควบคุมมุมมองของคุณและตั้งค่าคลาสเป็นชื่อคลาสของตัวจับเวลาของคุณ

ใส่คำอธิบายภาพที่นี่

อย่าลืม#importคลาสจับเวลาของคุณในตัวควบคุมมุมมองของคุณ

แก้ไข: สำหรับการออกแบบ IB (สำหรับการสร้างอินสแตนซ์โค้ดดูประวัติการแก้ไข)

ฉันไม่ค่อยคุ้นเคยกับสตอรีบอร์ด แต่ฉันรู้ว่าคุณสามารถสร้างอินเทอร์เฟซของคุณใน IB โดยใช้.xibไฟล์ที่เกือบจะเหมือนกับการใช้สตอรีบอร์ดเวอร์ชัน คุณควรจะสามารถคัดลอกและวางมุมมองของคุณโดยรวมจากอินเทอร์เฟซที่คุณมีอยู่ไปยัง.xibไฟล์

เพื่อทดสอบสิ่งนี้ฉันได้สร้างช่องว่างใหม่.xibชื่อ "MyCustomTimerView.xib" จากนั้นฉันก็เพิ่มมุมมองและเพิ่มป้ายกำกับและปุ่มสองปุ่ม ชอบมาก:

ใส่คำอธิบายภาพที่นี่

ฉันสร้างคลาสย่อยUIViewObject -C คลาสใหม่ชื่อ "MyCustomTimer" ในของฉัน.xibฉันจะตั้งค่าของฉันเจ้าของไฟล์ของระดับที่จะMyCustomTimer ตอนนี้ฉันมีอิสระที่จะเชื่อมต่อการกระทำและร้านค้าเช่นเดียวกับมุมมอง / ตัวควบคุมอื่น ๆ ส่งผลให้.hไฟล์มีลักษณะเช่นนี้

@interface MyCustomTimer : UIView
@property (strong, nonatomic) IBOutlet UILabel *displayLabel;
@property (strong, nonatomic) IBOutlet UIButton *startButton;
@property (strong, nonatomic) IBOutlet UIButton *stopButton;
- (IBAction)startButtonPush:(id)sender;
- (IBAction)stopButtonPush:(id)sender;
@end

สิ่งกีดขวางเดียวที่เหลือในการกระโดดคือการได้รับสิ่งนี้.xibในUIViewคลาสย่อยของฉัน การใช้.xibการตั้งค่าที่จำเป็นต้องลดลงอย่างมาก และเนื่องจากคุณใช้สตอรีบอร์ดเพื่อโหลดตัวจับเวลาเราจึงทราบว่า-(id)initWithCoder:เป็นตัวเริ่มต้นเพียงตัวเดียวที่จะถูกเรียก นี่คือลักษณะของไฟล์การนำไปใช้งาน:

#import "MyCustomTimer.h"
@implementation MyCustomTimer
@synthesize displayLabel;
@synthesize startButton;
@synthesize stopButton;
-(id)initWithCoder:(NSCoder *)aDecoder{
    if ((self = [super initWithCoder:aDecoder])){
        [self addSubview:
         [[[NSBundle mainBundle] loadNibNamed:@"MyCustomTimerView" 
                                        owner:self 
                                      options:nil] objectAtIndex:0]];
    }
    return self;
}
- (IBAction)startButtonPush:(id)sender {
    self.displayLabel.backgroundColor = [UIColor greenColor];
}
- (IBAction)stopButtonPush:(id)sender {
    self.displayLabel.backgroundColor = [UIColor redColor];
}
@end

เมธอดที่ตั้งชื่อloadNibNamed:owner:options:ทำสิ่งที่ดูเหมือนเป็นอย่างนั้น มันโหลด Nib และตั้งค่าคุณสมบัติ "File's Owner" เป็น self เราแยกออบเจ็กต์แรกในอาร์เรย์และนั่นคือมุมมองรูทของ Nib เราเพิ่มมุมมองเป็นมุมมองย่อยและ Voila อยู่บนหน้าจอ

เห็นได้ชัดว่านี่เป็นเพียงการเปลี่ยนสีพื้นหลังของป้ายกำกับเมื่อกดปุ่ม แต่ตัวอย่างนี้จะช่วยให้คุณเดินทางได้ดี

หมายเหตุตามความคิดเห็น:

เป็นที่น่าสังเกตว่าหากคุณได้รับปัญหาการเรียกซ้ำแบบไม่สิ้นสุดคุณอาจพลาดเคล็ดลับเล็กน้อยของวิธีแก้ปัญหานี้ มันไม่ได้ทำอย่างที่คุณคิด มุมมองที่ใส่ในสตอรีบอร์ดจะไม่เห็น แต่จะโหลดมุมมองอื่นเป็นมุมมองย่อยแทน มุมมองที่โหลดคือมุมมองที่กำหนดไว้ในปลายปากกา "เจ้าของไฟล์" ในปลายปากกาคือมุมมองที่มองไม่เห็น ส่วนที่น่าสนใจคือมุมมองที่มองไม่เห็นนี้ยังคงเป็นคลาส Objective-C ซึ่งอาจใช้เป็นตัวควบคุมมุมมองประเภทต่างๆสำหรับมุมมองที่นำเข้ามาจากปลายปากกา ตัวอย่างเช่นIBActionวิธีการในMyCustomTimerคลาสเป็นสิ่งที่คุณคาดหวังในตัวควบคุมมุมมองมากกว่าในมุมมอง

ตามหมายเหตุด้านข้างบางคนอาจโต้แย้งว่าการหยุดพักนี้MVCและฉันเห็นด้วยบ้าง จากมุมมองของฉันมันเกี่ยวข้องอย่างใกล้ชิดกับประเพณีUITableViewCellซึ่งบางครั้งก็ต้องมีส่วนควบคุมด้วย

นอกจากนี้ยังเป็นที่น่าสังเกตว่าคำตอบนี้เป็นวิธีแก้ปัญหาที่เฉพาะเจาะจงมาก สร้างปลายปากกาหนึ่งอันที่สามารถสร้างอินสแตนซ์ได้หลายครั้งในมุมมองเดียวกับที่วางไว้บนกระดานเรื่องราว ตัวอย่างเช่นคุณสามารถนึกภาพตัวจับเวลาทั้งหมดหกตัวบนหน้าจอ iPad พร้อมกันได้อย่างง่ายดาย หากคุณต้องการเพียงระบุมุมมองสำหรับตัวควบคุมมุมมองที่จะต้องใช้หลาย ๆ ครั้งในแอปพลิเคชันของคุณโซลูชันที่ jyavenard ให้ไว้สำหรับคำถามนี้เกือบจะเป็นทางออกที่ดีกว่าสำหรับคุณ


นี่ดูเหมือนเป็นคำถามแยกต่างหาก แต่ฉันคิดว่ามันสามารถตอบได้อย่างรวดเร็วดังนั้นนี่ไป ทุกครั้งที่คุณสร้างการแจ้งเตือนใหม่จะเป็นการแจ้งเตือนใหม่ แต่ถ้าคุณต้องการให้พวกเขามีชื่อเดียวกันต้องการเพิ่มบางอย่างเพื่อแยกความแตกต่างให้ใช้userInfoคุณสมบัติในการแจ้งเตือน@property(nonatomic,copy) NSDictionary *userInfo;
NJones

28
ฉันได้รับการเรียกซ้ำแบบไม่มีที่สิ้นสุดจาก initWithCoder ความคิดใด ๆ ?
หายตัวไป

6
ขออภัยที่ต้องรื้อฟื้นกระทู้เก่าตรวจสอบให้แน่ใจว่าการFile's Ownerตั้งชื่อชั้นเรียนของคุณช่วยแก้ปัญหาการเรียกซ้ำที่ไม่สิ้นสุด
themanatuf

20
อีกเหตุผลหนึ่งสำหรับการเรียกซ้ำแบบไม่สิ้นสุดคือการตั้งค่ามุมมองรูทใน xib เป็นคลาสที่คุณกำหนดเอง คุณไม่ต้องการทำเช่นนั้นปล่อยให้เป็น "UIView" เริ่มต้น
XY

11
มีเพียงสิ่งเดียวที่ดึงดูดความสนใจของฉันเกี่ยวกับแนวทางนี้ ... ไม่รบกวนใครเลยหรือว่าตอนนี้ 2 Views อยู่ในคลาสเดียวกัน? ไฟล์ต้นฉบับ. h / .m ที่สืบทอดมาจาก UIView เป็นไฟล์แรกและโดยการ [self addSubview:[[[NSBundle mainBundle] loadNibNamed:@"MyCustomTimerView" owner:self options:nil] objectAtIndex:0]]; เพิ่ม UIView ที่สอง ... แบบนี้ดูแปลกสำหรับฉันไม่มีใครรู้สึกแบบเดียวกันอีกแล้ว? ถ้าเป็นเช่นนั้นนี่คือสิ่งที่แอปเปิ้ลสร้างขึ้นโดยการออกแบบหรือไม่? หรือวิธีแก้ปัญหาที่ใครบางคนค้นพบจากการทำเช่นนี้?
SH

137

ตัวอย่างรวดเร็ว

อัปเดตสำหรับ Xcode 10 และ Swift 4

นี่คือการเดินผ่านขั้นพื้นฐาน เดิมทีฉันได้เรียนรู้สิ่งนี้มากมายจากการดูซีรีส์วิดีโอ Youtubeนี้ ต่อมาผมปรับปรุงคำตอบของฉันอยู่บนพื้นฐานของบทความนี้

เพิ่มไฟล์มุมมองแบบกำหนดเอง

สองไฟล์ต่อไปนี้จะสร้างมุมมองแบบกำหนดเองของคุณ:

  • .xib มีเค้าโครง
  • ไฟล์. swift เป็นUIViewคลาสย่อย

รายละเอียดการเพิ่มอยู่ด้านล่าง

ไฟล์ Xib

เพิ่มไฟล์ .xib กับโครงการของคุณ(File> New> File ... > User Interface> ดู) ReusableCustomView.xibฉันโทรเหมือง

สร้างเค้าโครงที่คุณต้องการให้มุมมองแบบกำหนดเองของคุณมี ตัวอย่างเช่นฉันจะสร้างเค้าโครงด้วย a UILabelและUIButton. เป็นความคิดที่ดีที่จะใช้การจัดวางอัตโนมัติเพื่อให้สิ่งต่างๆปรับขนาดโดยอัตโนมัติไม่ว่าคุณจะตั้งค่าเป็นขนาดใดในภายหลัง (ฉันใช้Freeformสำหรับขนาด xib ในตัวตรวจสอบแอตทริบิวต์เพื่อที่ฉันจะสามารถปรับเมตริกจำลองได้ แต่ไม่จำเป็น)

ใส่คำอธิบายภาพที่นี่

ไฟล์ Swift

เพิ่มไฟล์ .swift กับโครงการของคุณ(File> New> File ... > ที่มา> Swift File) มันเป็น subclass ของและฉันเรียกเหมืองUIViewReusableCustomView.swift

import UIKit
class ResuableCustomView: UIView {

}

ทำให้ไฟล์ Swift เป็นเจ้าของ

กลับไปที่ไฟล์. xibของคุณและคลิกที่ "เจ้าของไฟล์" ในโครงร่างเอกสาร ใน Identity Inspector ให้เขียนชื่อไฟล์. swiftของคุณเป็นชื่อคลาสที่กำหนดเอง

ใส่คำอธิบายภาพที่นี่

เพิ่มรหัสมุมมองที่กำหนดเอง

แทนที่ReusableCustomView.swiftเนื้อหาของไฟล์ด้วยรหัสต่อไปนี้:

import UIKit

@IBDesignable
class ResuableCustomView: UIView {

    let nibName = "ReusableCustomView"
    var contentView:UIView?

    @IBOutlet weak var label: UILabel!

    @IBAction func buttonTap(_ sender: UIButton) {
        label.text = "Hi"
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commonInit()
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }

    func commonInit() {
        guard let view = loadViewFromNib() else { return }
        view.frame = self.bounds
        self.addSubview(view)
        contentView = view
    }

    func loadViewFromNib() -> UIView? {
        let bundle = Bundle(for: type(of: self))
        let nib = UINib(nibName: nibName, bundle: bundle)
        return nib.instantiate(withOwner: self, options: nil).first as? UIView
    }
}

ตรวจสอบให้แน่ใจว่าสะกดถูกต้องสำหรับชื่อไฟล์. xib ของคุณ

เชื่อมต่อร้านค้าและการดำเนินการ

เชื่อมต่อร้านค้าและการดำเนินการโดยการควบคุมการลากจากป้ายกำกับและปุ่มในเค้าโครง xib ไปยังโค้ดมุมมองแบบกำหนดเองที่รวดเร็ว

ใช้มุมมองที่คุณกำหนดเอง

มุมมองแบบกำหนดเองของคุณเสร็จสิ้นแล้ว สิ่งที่คุณต้องทำคือเพิ่มUIViewทุกที่ที่คุณต้องการในกระดานเรื่องราวหลักของคุณ ตั้งชื่อคลาสของมุมมองReusableCustomViewใน Identity Inspector

ใส่คำอธิบายภาพที่นี่


31
สิ่งสำคัญอย่าตั้งค่าคลาสมุมมอง Xib เป็น ResuableCustomView แต่เป็นเจ้าของ Xib นี้ มิฉะนั้นคุณจะมีข้อผิดพลาด
RealNmae

5
ใช่คำเตือนที่ดี ฉันไม่รู้ว่าฉันเสียเวลามากแค่ไหนในการพยายามแก้ปัญหาการเรียกซ้ำแบบไม่สิ้นสุดที่เกิดจากการตั้งค่ามุมมองของ Xib (แทนที่จะเป็นเจ้าของไฟล์) เป็นชื่อคลาส
Suragch

2
@ TomCalmon ฉันเปลี่ยนโปรเจ็กต์นี้ใน Xcode 8 ด้วย Swift 3 และ Auto Layout ก็ใช้ได้สำหรับฉัน
Suragch

6
หากใครมีปัญหากับการแสดงผลมุมมองใน IB ฉันพบว่าการเปลี่ยนBundle.mainเพื่อBundle(for: ...)ทำเคล็ดลับ เห็นได้ชัดว่าBundle.mainไม่พร้อมใช้งานในเวลาออกแบบ
crizzis

4
เหตุผลนี้ไม่ได้ทำงานกับ @IBDesignable init(frame:)คือการที่คุณไม่ได้ใช้ เมื่อคุณเพิ่มสิ่งนี้ (และดึงรหัสเริ่มต้นทั้งหมดไปยังcommonInit()ฟังก์ชันบางอย่าง) มันจะทำงานได้ดีและแสดงใน IB ดูข้อมูลเพิ่มเติมได้ที่นี่: stackoverflow.com/questions/31265906/…
Dimitris

39

คำตอบสำหรับตัวควบคุมมุมมองไม่ใช่มุมมอง :

มีวิธีที่ง่ายกว่าในการโหลด xib จากสตอรี่บอร์ด สมมติว่าคอนโทรลเลอร์ของคุณเป็นประเภท MyClassController ซึ่งสืบทอดมาจากUIViewControllerซึ่งสืบทอดมาจาก

คุณเพิ่มไฟล์ UIViewController IB โดยใช้ในสตอรีบอร์ดของคุณ เปลี่ยนประเภทคลาสเป็น MyClassController ลบมุมมองที่เพิ่มโดยอัตโนมัติในกระดานเรื่องราว

ตรวจสอบให้แน่ใจว่า XIB ที่คุณต้องการเรียกนั้นเรียกว่า MyClassController.xib

เมื่อชั้นเรียนถูกสร้างอินสแตนซ์ระหว่างการโหลดสตอรี่บอร์ด xib จะโหลดโดยอัตโนมัติ สาเหตุนี้เกิดจากการใช้งานเริ่มต้นUIViewControllerซึ่งเรียกใช้ XIB ที่ตั้งชื่อด้วยชื่อคลาส


1
ฉันขยายมุมมองที่กำหนดเองตลอดเวลา แต่ไม่เคยรู้เคล็ดลับเล็ก ๆ น้อย ๆ นี้ในการโหลดลงในกระดานเรื่องราว ชื่นชมมาก!
MrTristan

38
คำถามเกี่ยวกับมุมมองไม่ใช่เกี่ยวกับตัวควบคุมมุมมอง
Ricardo

เพิ่มชื่อเรื่องสำหรับการชี้แจง "คำตอบสำหรับผู้ควบคุมมุมมองไม่ใช่มุมมอง:"
nacho4d

1
ดูเหมือนจะไม่ทำงานใน iOS 9.1 ถ้าฉันลบมุมมองที่สร้างขึ้นโดยอัตโนมัติ (ค่าเริ่มต้น) มันจะขัดข้องหลังจากกลับจาก viewDidLoad ของ VC ฉันไม่คิดว่ามุมมองใน XIB จะเชื่อมต่อแทนที่มุมมองเริ่มต้น
Jeff

1
'Could not load NIB in bundle: 'NSBundle </Users/me/.../MyAppName.app> (loaded)' with name 'uB0-aR-WjG-view-4OA-9v-tyV''ยกเว้นในกรณีที่ฉันได้รับคือ หมายเหตุ whacko nibName ฉันใช้ชื่อคลาสที่ถูกต้องสำหรับในปลายปากกา
Jeff

16

นี่ไม่ใช่คำตอบจริงๆ แต่ฉันคิดว่าการแบ่งปันแนวทางนี้มีประโยชน์

Objective-C

  1. นำเข้าCustomViewWithXib.hและCustomViewWithXib.m ไปยังโครงการของคุณ
  2. สร้างไฟล์มุมมองแบบกำหนดเองด้วยชื่อเดียวกัน (.h / .m / .xib)
  3. สืบทอดคลาสที่กำหนดเองของคุณจาก CustomViewWithXib

รวดเร็ว

  1. นำเข้าCustomViewWithXib.swiftไปยังโครงการของคุณ
  2. สร้างไฟล์มุมมองแบบกำหนดเองด้วยชื่อเดียวกัน (.swift และ. xib)
  3. สืบทอดคลาสที่กำหนดเองของคุณจาก CustomViewWithXib

ไม่จำเป็น :

  1. ไปที่ไฟล์ xib ของคุณตั้งค่าเจ้าของด้วยชื่อคลาสที่คุณกำหนดเองหากคุณต้องการเชื่อมต่อองค์ประกอบบางอย่าง (สำหรับรายละเอียดเพิ่มเติมโปรดดูที่ส่วนทำให้ไฟล์ Swift เป็นเจ้าของคำตอบ @Suragch)

ตอนนี้คุณสามารถเพิ่มมุมมองที่กำหนดเองลงในสตอรีบอร์ดของคุณได้แล้วและจะแสดง :)

CustomViewWithXib.h :

 #import <UIKit/UIKit.h>

/**
 *  All classes inherit from CustomViewWithXib should have the same xib file name and class name (.h and .m)
 MyCustomView.h
 MyCustomView.m
 MyCustomView.xib
 */

// This allows seeing how your custom views will appear without building and running your app after each change.
IB_DESIGNABLE
@interface CustomViewWithXib : UIView

@end

CustomViewWithXib.m :

#import "CustomViewWithXib.h"

@implementation CustomViewWithXib

#pragma mark - init methods

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // load view frame XIB
        [self commonSetup];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        // load view frame XIB
        [self commonSetup];
    }
    return self;
}

#pragma mark - setup view

- (UIView *)loadViewFromNib {
    NSBundle *bundle = [NSBundle bundleForClass:[self class]];

    //  An exception will be thrown if the xib file with this class name not found,
    UIView *view = [[bundle loadNibNamed:NSStringFromClass([self class])  owner:self options:nil] firstObject];
    return view;
}

- (void)commonSetup {
    UIView *nibView = [self loadViewFromNib];
    nibView.frame = self.bounds;
    // the autoresizingMask will be converted to constraints, the frame will match the parent view frame
    nibView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    // Adding nibView on the top of our view
    [self addSubview:nibView];
}

@end

CustomViewWithXib.swift :

import UIKit

@IBDesignable
class CustomViewWithXib: UIView {

    // MARK: init methods
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        commonSetup()
    }

    override init(frame: CGRect) {
        super.init(frame: frame)

        commonSetup()
    }

    // MARK: setup view 

    private func loadViewFromNib() -> UIView {
        let viewBundle = NSBundle(forClass: self.dynamicType)
        //  An exception will be thrown if the xib file with this class name not found,
        let view = viewBundle.loadNibNamed(String(self.dynamicType), owner: self, options: nil)[0]
        return view as! UIView
    }

    private func commonSetup() {
        let nibView = loadViewFromNib()
        nibView.frame = bounds
        // the autoresizingMask will be converted to constraints, the frame will match the parent view frame
        nibView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
        // Adding nibView on the top of our view
        addSubview(nibView)
    }
}

คุณสามารถค้นหาตัวอย่างบางส่วนที่นี่

หวังว่าจะช่วยได้


ดังนั้นเราจะเพิ่ม iboutlet สำหรับ uicontrols มุมมองได้อย่างไร
Amr Angry

1
สวัสดี @AmrAngry ในการเชื่อมต่อมุมมองคุณควรทำขั้นตอนที่ 4: ไปที่ไฟล์ xib ของคุณใน "เจ้าของไฟล์" ตั้งค่าชั้นเรียนของคุณแล้วลากและวางมุมมองของคุณไปยังอินเทอร์เฟซโดยแตะที่ "ctrl" ฉันอัปเดต รหัสที่มาพร้อมตัวอย่างนี้อย่าลังเลหากคุณมีคำถามหวังว่าจะช่วยได้
HamzaGhazouani

ขอบคุณมากสำหรับการเล่นซ้ำของคุณฉันทำสิ่งนี้ไปแล้ว แต่ฉันเดาว่าปัญหาของฉันไม่ได้อยู่ในส่วนนี้ ปัญหาของฉันคือฉันเพิ่ม UIDatePIcker และพยายามเพิ่มการดำเนินการเป้าหมายสำหรับการควบคุมนี้จาก ViewController เพื่อตั้งค่าและเหตุการณ์ uiControleer มีการเปลี่ยนแปลงค่า แต่วิธีการไม่ถูกเรียก / ไฟ
Amr Angry

1
@AmrAngry ฉันอัปเดตตัวอย่างโดยเพิ่มมุมมองตัวเลือกอาจเป็นเพราะมันจะช่วยคุณได้ :) github.com/HamzaGhazouani/Stackoverflow/tree/master/…
HamzaGhazouani

1
ขอบคุณที่ฉันมองหาสิ่งนี้มานาน
MH175
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.