วิธีที่ดีที่สุดในการแก้ไขการชนกันของเนมสเปซ Objective-C คืออะไร


174

วัตถุประสงค์ -C ไม่มีเนมสเปซ มันเหมือนกับ C ทุกอย่างอยู่ในเนมสเปซส่วนกลางเดียว วิธีปฏิบัติทั่วไปคือการเติมคำนำหน้าคลาสด้วยชื่อย่อเช่นถ้าคุณทำงานที่ IBM คุณสามารถใช้คำนำหน้าด้วย "IBM" ถ้าคุณทำงานให้ Microsoft คุณสามารถใช้ "MS"; และอื่น ๆ บางครั้งชื่อย่ออ้างถึงโครงการเช่น Adium นำหน้าคลาสด้วย "AI" (เนื่องจากไม่มี บริษัท ใดอยู่ด้านหลังซึ่งคุณสามารถใช้ชื่อย่อได้) คำนำหน้าของ Apple คลาสที่มี NS และบอกว่าคำนำหน้านี้สงวนไว้สำหรับ Apple เท่านั้น

จนถึงตอนนี้ก็ดี แต่การเพิ่มตัวอักษร 2 ถึง 4 ตัวต่อท้ายชื่อคลาสด้านหน้าเป็นเนมสเปซที่ จำกัด มาก เช่น MS หรือ AI อาจมีความหมายที่แตกต่างกันโดยสิ้นเชิง (เช่น AI เป็นปัญญาประดิษฐ์เป็นต้น) และผู้พัฒนารายอื่นอาจตัดสินใจใช้และสร้างคลาสที่มีชื่อเท่าเทียมกัน บางชน namespace

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

ใน C คุณสามารถหลีกเลี่ยงสิ่งเหล่านี้ได้โดยไม่เชื่อมโยงโดยตรงกับไลบรารีแทนคุณโหลดไลบรารี่ขณะใช้งานโดยใช้ dlopen () จากนั้นหาสัญลักษณ์ที่คุณต้องการใช้ dlsym () และกำหนดให้กับสัญลักษณ์ทั่วโลก สามารถตั้งชื่อตามที่คุณต้องการ) จากนั้นเข้าถึงผ่านสัญลักษณ์ระดับโลกนี้ เช่นถ้าคุณมีข้อขัดแย้งเพราะบางไลบรารี C มีฟังก์ชั่นชื่อ open () คุณสามารถกำหนดตัวแปรชื่อ myOpen และให้มันชี้ไปที่ฟังก์ชั่น open () ของไลบรารีดังนั้นเมื่อคุณต้องการใช้ระบบ open () คุณเพียงแค่ใช้ open () และเมื่อคุณต้องการใช้อีกอันคุณก็สามารถเข้าถึงมันได้ผ่านตัวระบุ myOpen

เป็นสิ่งที่คล้ายกันเป็นไปได้ใน Objective-C และถ้าไม่มีวิธีอื่นที่ฉลาดและมีเล่ห์เหลี่ยมที่คุณสามารถใช้แก้ไขเนมสเปซที่ขัดแย้งกันได้หรือไม่? ความคิดใด ๆ


ปรับปรุง:

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


7
คุณมีคำถามที่ดี (จะต้องทำอย่างไรถ้าคุณต้องการสองเฟรมเวิร์กที่มีการชนกันของชื่อ) แต่มันถูกฝังอยู่ในข้อความ แก้ไขเพื่อให้ชัดเจนขึ้นและคุณจะหลีกเลี่ยงคำตอบแบบง่าย ๆ เหมือนคำตอบที่คุณมีในขณะนี้
benzado

4
นี่คือสิ่งที่ฉันถนัดที่สุดด้วยการออกแบบในปัจจุบันของภาษา Objective-C ดูคำตอบด้านล่าง; ผู้ที่ตอบคำถาม (การขนถ่าย NSBundle โดยใช้ DO และอื่น ๆ ) เป็นแฮ็คที่น่าเกลียดที่ไม่ควรจำเป็นสำหรับบางสิ่งที่ไม่สำคัญเท่ากับการหลีกเลี่ยงความขัดแย้งของเนมสเปซ
erikprice

@erikprice: สาธุ ฉันกำลังเรียนรู้ obj-c และประสบปัญหานี้มาก มาที่นี่กำลังมองหาทางออกที่ง่าย .... ง่อย
Dave Mateer

1
สำหรับเร็กคอร์ดเทคนิคทั้ง C และ Objective-C จัดเตรียมการสนับสนุนหลายชื่อพื้นที่ - ไม่ตรงกับที่ OP ต้องการ ดูobjectivistc.tumblr.com/post/3340816080/ …

อืมฉันไม่รู้ การตัดสินใจออกแบบที่แย่มาก
Nico

คำตอบ:


47

หากคุณไม่จำเป็นต้องใช้คลาสจากกรอบงานทั้งสองในเวลาเดียวกันและคุณกำลังกำหนดเป้าหมายแพลตฟอร์มที่รองรับการยกเลิกการโหลด NSBundle (OS X 10.4 หรือใหม่กว่าไม่มีการสนับสนุน GNUStep) และประสิทธิภาพไม่เป็นปัญหาสำหรับคุณฉันเชื่อว่า ที่คุณสามารถโหลดหนึ่งเฟรมเวิร์กทุกครั้งที่คุณต้องการใช้คลาสจากนั้นยกเลิกการโหลดและโหลดเฟรมเวิร์กอื่นเมื่อคุณต้องการใช้เฟรมเวิร์กอื่น

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

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

แก้ไข: ความแตกต่างพื้นฐานระหว่าง C และ Objective-C runtimes คือตามที่ฉันเข้าใจเมื่อมีการโหลดไลบรารีฟังก์ชันในไลบรารีเหล่านั้นจะมีตัวชี้ไปที่สัญลักษณ์ใด ๆ ที่อ้างอิงในขณะที่ Objective-C จะมีการแสดงสตริงของ ชื่อของสัญลักษณ์เหล่านี้ ดังนั้นในตัวอย่างของคุณคุณสามารถใช้ dlsym เพื่อรับที่อยู่ของสัญลักษณ์ในหน่วยความจำและแนบไปกับสัญลักษณ์อื่น รหัสอื่นในไลบรารียังคงใช้งานได้เพราะคุณไม่ได้เปลี่ยนที่อยู่ของสัญลักษณ์ดั้งเดิม Objective-C ใช้ตารางการค้นหาเพื่อจับคู่ชื่อคลาสกับที่อยู่และเป็นการแมป 1-1 ดังนั้นคุณจึงไม่สามารถมีสองคลาสที่มีชื่อเดียวกันได้ ดังนั้นในการโหลดทั้งสองคลาสหนึ่งในนั้นต้องเปลี่ยนชื่อ อย่างไรก็ตามเมื่อคลาสอื่นจำเป็นต้องเข้าถึงหนึ่งในคลาสด้วยชื่อนั้น


5
ฉันเชื่อว่าไม่สามารถโหลดบันเดิลการโหลดได้จนถึง 10.5 หรือใหม่กว่า
Quinn Taylor

93

คำนำหน้าชั้นเรียนของคุณด้วยคำนำหน้าที่ไม่ซ้ำกันเป็นพื้นฐานตัวเลือกเดียว แต่มีหลายวิธีที่จะทำให้มันลดน้อยลงและน่าเกลียด มีการอภิปรายยาวของตัวเลือกที่เป็นที่นี่ สิ่งที่ฉันชอบคือ@compatibility_aliasObjective-C compiler directive (อธิบายไว้ที่นี่ ) คุณสามารถใช้@compatibility_aliasเพื่อ "เปลี่ยนชื่อ" คลาสที่อนุญาตให้คุณตั้งชื่อคลาสของคุณโดยใช้ FQDN หรือคำนำหน้าบางอย่าง:

@interface COM_WHATEVER_ClassName : NSObject
@end

@compatibility_alias ClassName COM_WHATEVER_ClassName
// now ClassName is an alias for COM_WHATEVER_ClassName

@implementation ClassName //OK
//blah
@end

ClassName *myClass; //OK

ในฐานะส่วนหนึ่งของกลยุทธ์ที่สมบูรณ์คุณสามารถนำหน้าคลาสทั้งหมดของคุณด้วยคำนำหน้าที่ไม่ซ้ำกันเช่น FQDN แล้วสร้างส่วนหัวด้วยทั้งหมด@compatibility_alias(ฉันคิดว่าคุณสามารถสร้างส่วนหัวดังกล่าวโดยอัตโนมัติ)

ข้อเสียของคำนำหน้าเช่นนี้คือคุณต้องป้อนชื่อคลาสจริง (เช่นCOM_WHATEVER_ClassNameด้านบน) ในทุกสิ่งที่ต้องการชื่อคลาสจากสตริงข้างคอมไพเลอร์ โดยเฉพาะอย่างยิ่ง@compatibility_aliasเป็นคำสั่งคอมไพเลอร์ไม่ได้เป็นฟังก์ชั่นรันไทม์เพื่อNSClassFromString(ClassName)จะล้มเหลว (กลับnil) - NSClassFromString(COM_WHATERVER_ClassName)คุณจะต้องใช้ คุณสามารถใช้ibtoolผ่านขั้นตอนการสร้างเพื่อแก้ไขชื่อคลาสใน Interface Builder nib / xib เพื่อให้คุณไม่ต้องเขียน COM_WHATEVER _... แบบเต็มในเครื่องมือสร้างอินเตอร์เฟส

ข้อแม้สุดท้าย: เพราะนี่เป็นคำสั่งของคอมไพเลอร์ (และสิ่งที่คลุมเครือในตอนนั้น) จึงอาจไม่สามารถพกพาข้ามคอมไพเลอร์ได้ โดยเฉพาะอย่างยิ่งฉันไม่ทราบว่ามันใช้งานได้กับส่วนหน้าของ Clang จากโครงการ LLVM หรือไม่ แต่ควรใช้กับ LLVM-GCC (LLVM โดยใช้ส่วนหน้าของ GCC)


4
โหวตขึ้นสำหรับความเข้ากันได้ _alias ฉันไม่รู้เกี่ยวกับอันนั้น! ขอบคุณ แต่มันไม่ได้แก้ปัญหาของฉัน ฉันไม่ได้อยู่ในการควบคุมที่จะเปลี่ยนคำนำหน้าใด ๆ ของกรอบงานทั้งสองที่ฉันใช้ฉันมีเพียงพวกเขาในรูปแบบไบนารีและพวกเขาชนกัน ฉันควรทำอย่างไรเกี่ยวกับเรื่องนี้?
Mecki

ควร @ @ บรรทัดในแฟ้ม (.h หรือ. m)
Alex Basson

1
@Alex_Basson @compatibility_alias อาจจะอยู่ในส่วนหัวเพื่อให้สามารถมองเห็นได้ทุกที่ที่ประกาศ @interface สามารถมองเห็นได้
Barry Wark

ฉันสงสัยว่าคุณสามารถใช้ @compatibility_alias กับชื่อโปรโตคอลหรือนิยาม typedef หรือสิ่งอื่นใดสำหรับเรื่องนั้นได้หรือไม่
Ali

ความคิดที่ดีที่นี่ สามารถใช้วิธีการ swizzling เพื่อป้องกัน NSClassFromString (ClassName) จากการส่งกลับค่าศูนย์สำหรับคลาส aliased หรือไม่? อาจเป็นเรื่องยากที่จะค้นหาวิธีการทั้งหมดที่ใช้ชื่อคลาส
Dickey Singh

12

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

  1. ไม่ว่าในกรณีใดแจ้งให้ผู้พัฒนาทราบถึงกรอบความขัดแย้งทั้งสองและทำให้ชัดเจนว่าความล้มเหลวในการหลีกเลี่ยงและ / หรือจัดการกับปัญหานั้นทำให้คุณเกิดปัญหาทางธุรกิจจริงซึ่งอาจแปลเป็นรายได้ทางธุรกิจที่หายไป เน้นว่าในขณะที่การแก้ไขข้อขัดแย้งที่มีอยู่บนพื้นฐานสำหรับแต่ละคลาสเป็นการแก้ไขที่รบกวนน้อยกว่าการเปลี่ยนคำนำหน้าทั้งหมด (หรือใช้หากไม่ได้ในปัจจุบันและอัปยศพวกเขา!) เป็นวิธีที่ดีที่สุดเพื่อให้แน่ใจว่า ดูปัญหาเดิมอีกครั้ง
  2. หากความขัดแย้งของการตั้งชื่อถูก จำกัด ไว้ที่คลาสที่มีขนาดเล็กพอสมควรดูว่าคุณสามารถแก้ไขเฉพาะคลาสเหล่านั้นได้หรือไม่โดยเฉพาะอย่างยิ่งหากโค้ดที่คุณใช้นั้นไม่ตรงกับคลาสที่ขัดแย้งกัน ถ้าเป็นเช่นนั้นดูว่าผู้ขายจะให้กรอบงานที่กำหนดเองซึ่งไม่รวมคลาสที่ขัดแย้งกันหรือไม่ หากไม่ตรงไปตรงมาเกี่ยวกับความจริงที่ว่าความยืดหยุ่นของพวกเขาคือการลด ROI ของคุณจากการใช้กรอบงานของพวกเขา อย่ารู้สึกแย่กับการถูกผลักดันด้วยเหตุผล - ลูกค้าถูกเสมอ ;-)
  3. หากหนึ่งเฟรมเวิร์กมี "dispensable" มากกว่าคุณอาจลองแทนที่มันด้วยเฟรมเวิร์กอื่น (หรือการรวมกันของโค้ด) ไม่ว่าจะเป็นบุคคลที่สามหรือ homebrew (กรณีหลังเป็นกรณีที่เลวร้ายที่สุดที่ไม่พึงประสงค์เนื่องจากจะต้องเสียค่าใช้จ่ายทางธุรกิจเพิ่มเติมทั้งในการพัฒนาและบำรุงรักษา) หากคุณแจ้งผู้ขายของกรอบนั้นว่าทำไมคุณตัดสินใจที่จะไม่ใช้กรอบงาน
  4. หากทั้งสองเฟรมเวิร์กมีความสำคัญเท่ากันกับแอ็พพลิเคชันของคุณให้สำรวจวิธีแยกแยะการใช้งานหนึ่งในกระบวนการแยกต่างหากหนึ่งกระบวนการหรือมากกว่านั้นอาจสื่อสารผ่าน DO ตามที่ Louis Gerbarg แนะนำ ขึ้นอยู่กับระดับของการสื่อสารสิ่งนี้อาจไม่เลวร้ายอย่างที่คุณคาดหวัง หลายโปรแกรม (รวมถึง QuickTime ฉันเชื่อว่า) ใช้วิธีการนี้เพื่อให้ความปลอดภัยที่ละเอียดมากขึ้นโดยใช้โปรไฟล์ Sandbox ของ Seatbelt ใน Leopardเช่นว่าอนุญาตให้เฉพาะบางส่วนของรหัสของคุณในการดำเนินการที่สำคัญหรือละเอียดอ่อน ประสิทธิภาพจะเป็นการแลกเปลี่ยน แต่อาจเป็นตัวเลือกเดียวของคุณ

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


8

นี่คือขั้นต้น แต่คุณสามารถใช้ออบเจ็กต์แบบกระจายเพื่อเก็บคลาสหนึ่งในที่อยู่ของโปรแกรมรองและ RPC ให้กับมัน ซึ่งจะยุ่งเหยิงหากคุณส่งเรื่องไปมาหลายครั้ง (และอาจเป็นไปไม่ได้ถ้าทั้งสองคลาสจัดการกับมุมมองโดยตรง ฯลฯ )

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

หากคุณหมดหวังจริงๆสิ่งที่คุณสามารถทำได้คือ:

  1. ไม่เชื่อมโยงกับหนึ่งในห้องสมุดโดยตรง
  2. ใช้งานเวอร์ชันสำรองของรูทีน objc รันไทม์ที่เปลี่ยนชื่อ ณ เวลาโหลด ( เช็กเอาต์โครงการobjc4สิ่งที่คุณต้องทำขึ้นอยู่กับคำถามที่ฉันถามด้านบน แต่ควรเป็นไปได้ไม่ว่าคำตอบจะเป็นอะไร )
  3. ใช้บางอย่างเช่นmach_overrideเพื่อฉีดการนำไปใช้ใหม่ของคุณ
  4. โหลดไลบรารีใหม่โดยใช้วิธีปกติมันจะผ่านขั้นตอนการเชื่อมโยง patched และได้รับ className การเปลี่ยนแปลง

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


4

คุณได้พิจารณาการใช้ฟังก์ชั่นรันไทม์ (/usr/include/objc/runtime.h) เพื่อโคลนคลาสที่ขัดแย้งกันไปยังคลาสที่ไม่มีการชนกันหรือไม่จากนั้นโหลดเฟรมเวิร์กของการชนกันของคลาส? (สิ่งนี้จะต้องมีการโหลดเฟรมเวิร์กการชนกันในเวลาต่างกันเพื่อให้ทำงานได้)

คุณสามารถตรวจสอบคลาสของ ivars วิธีการ (ที่มีชื่อและที่อยู่การนำไปปฏิบัติ) และชื่อด้วยรันไทม์และสร้างของคุณเองเช่นกันแบบไดนามิกเพื่อให้มีรูปแบบ ivar เดียวกันชื่อวิธีการ / ที่อยู่การดำเนินงานและแตกต่างกันตามชื่อ ชน)


3

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

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


การเปลี่ยนไลบรารี่บนดิสก์เป็นปัญหาเพราะใบอนุญาตจะไม่อนุญาต การเปลี่ยนสัญลักษณ์ในหน่วยความจำจะเป็นไปได้ แต่ฉันไม่เห็นวิธีที่จะทำได้ (โหลด lib ลงในหน่วยความจำแก้ไขมันแล้วส่งมันไปยังตัวเชื่อมโยงแบบไดนามิก ... ไม่เห็นวิธีสำหรับสิ่งนั้น)
Mecki

3
ตกลง - เวลาที่จะตัดสินใจว่าห้องสมุดใดในสองแห่งนี้มีความสำคัญน้อยกว่าและหาการแทนที่ และอธิบายให้คนที่คุณจ่าย แต่คุณละทิ้งว่าเหตุผลที่คุณเปลี่ยนเป็นเพราะความขัดแย้งนี้และพวกเขาสามารถรักษาธุรกิจของคุณโดยการแก้ไขปัญหาของคุณ
Jonathan Leffler

2

@compatibility_alias จะสามารถแก้ไขความขัดแย้งของ namespace ของคลาสได้เช่น

@compatibility_alias NewAliasClass OriginalClass;

อย่างไรก็ตามการทำเช่นนี้จะไม่สามารถแก้ไขการชนกันของ enums, typedefs หรือ protocol namespaceใด ๆ ได้ ยิ่งไปกว่านั้นมันเล่นได้ไม่ดีนักกับการ@classลดลงของระดับเดิม เนื่องจากเฟรมเวิร์กส่วนใหญ่จะมาพร้อมกับสิ่งที่ไม่ใช่คลาสเช่น typedefs คุณอาจจะไม่สามารถแก้ไขปัญหาการกำหนดเนมสเปซด้วย

ฉันมองปัญหาคล้ายกันกับคุณแต่ฉันสามารถเข้าถึงแหล่งข้อมูลและกำลังสร้างกรอบงาน ทางออกที่ดีที่สุดที่ฉันพบคือการใช้@compatibility_aliasเงื่อนไขกับ #defines เพื่อสนับสนุน enums / typedefs / โปรโตคอล / etc คุณสามารถทำสิ่งนี้ได้อย่างมีเงื่อนไขบนหน่วยการคอมไพล์สำหรับส่วนหัวที่มีปัญหาเพื่อลดความเสี่ยงของการขยายเนื้อหาในกรอบการชนอื่น ๆ


1

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

ฉันไม่ได้มีประสบการณ์เพียงพอในเรื่องนี้ในวัตถุประสงค์ -c (เพิ่งเริ่มต้น) แต่ฉันเชื่อว่านั่นคือสิ่งที่ฉันจะทำในซี


1
แต่คุณจะไม่เจอกับการชนกันหรือไม่ถ้าคุณพยายามรวมส่วนหัวของ wrapper ไว้ในไฟล์เดียวกัน
Wilco

0

คำนำหน้าไฟล์เป็นวิธีที่ง่ายที่สุดที่ฉันรู้ Cocoadev มีหน้าเนมสเปซซึ่งเป็นความพยายามของชุมชนเพื่อหลีกเลี่ยงการชนของเนมสเปซ รู้สึกอิสระที่จะเพิ่มของคุณเองในรายการนี้ฉันเชื่อว่านั่นคือสิ่งที่มันมีไว้สำหรับ

http://www.cocoadev.com/index.pl?ChooseYourOwnPrefix


คำนำหน้าไฟล์จะช่วยได้อย่างไรหากวัตถุที่กำหนดไว้ในไฟล์ทำให้เกิดปัญหา ฉันสามารถจัดการไฟล์ h ได้อย่างแน่นอน แต่ตัวเชื่อมโยงจะไม่พบวัตถุอีกต่อไปเมื่อชอบกรอบ: - /
Mecki

ฉันเชื่อว่านี่จะเป็นวิธีที่ดีที่สุด - กว่าการแก้ปัญหาเบื้องต้น
อาลี

นี่ไม่ได้ตอบคำถามทั้งหมด
Madbreaks

0

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

ถ้าหากฉันอยู่ในตำแหน่งของคุณนี่จะเป็นทางเลือกของฉัน


0

หากการชนกันอยู่ที่ระดับลิงก์แบบคงที่เท่านั้นคุณสามารถเลือกไลบรารีที่จะใช้แก้ไขสัญลักษณ์:

cc foo.o -ldog bar.o -lcat

หากfoo.oและbar.oการอ้างอิงทั้งสัญลักษณ์ratแล้วlibdogจะแก้foo.o's ratและlibcatจะแก้bar.o' rats


0

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

หากคุณต้องเขียน wrapper รอบ ๆ เฟรมเวิร์กที่เรียบง่าย (หรืออินเทอร์เฟซที่คุณเข้าถึงน้อยที่สุด) จะไม่สามารถคอมไพล์ wrapper นั้นในไลบรารีได้ ป.ร. ให้ไว้ ณ ห้องสมุด precompiled และคนเดียวของส่วนหัวจำเป็นต้องกระจายคุณต้องการจะมีประสิทธิภาพในการหลบซ่อนตัวอยู่ในกรอบอ้างอิงและจะมีอิสระที่จะรวมกับกรอบที่สองกับการปะทะกัน

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

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

อีกครั้งในวิธีที่พิสูจน์แล้ว แต่รู้สึกเหมือนเพิ่มมุมมอง หวังว่ามันจะช่วย :)


-1

หากคุณมีสองเฟรมเวิร์กที่มีชื่อฟังก์ชันเหมือนกันคุณสามารถลองโหลดเฟรมเวิร์กแบบไดนามิกได้ มันจะไม่สุภาพ แต่เป็นไปได้ ฉันจะทำอย่างไรกับคลาส Objective-C ฉันไม่รู้ ฉันเดาว่าNSBundleคลาสจะมีวิธีที่จะโหลดคลาสเฉพาะ

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