দমন সতর্কতা "বিভাগ একটি পদ্ধতি প্রয়োগ করছে যা এটির প্রাথমিক শ্রেণি দ্বারা প্রয়োগ করা হবে"


98

আমি ভাবছিলাম যে কীভাবে সতর্কতা দমন করতে হবে:

বিভাগ একটি পদ্ধতি বাস্তবায়ন করছে যা এর প্রাথমিক শ্রেণি দ্বারা প্রয়োগ করা হবে।

আমার কাছে এটি একটি নির্দিষ্ট কোড বিভাগের জন্য রয়েছে:

+ (UIFont *)systemFontOfSize:(CGFloat)fontSize {
    return [self aCustomFontOfSize:fontSize];
}

পদ্ধতি দ্বারা swizzling। যদিও আমি এটি না করতাম - সম্ভবত আপনি একটি ইউআইএফন্ট সাবক্লাস তৈরি করতে পারেন যা পরিবর্তে একই পদ্ধতিটিকে ওভাররাইড করে এবং superঅন্যথায় কল করতে পারেন।
অ্যালান জেইনো

4
আপনার সমস্যাটি হুঁশিয়ারি নয়। আপনার সমস্যাটি হ'ল আপনার একই পদ্ধতির নাম রয়েছে যা সমস্যা বাড়ে।
gnasher729

দেখুন উপেক্ষা উদ্দেশ্য সি মধ্যে বিভাগ ব্যবহার পদ্ধতি বিকল্প সমাধানের জন্য কারণে আপনি কেন শ্রেণী ব্যবহারের পদ্ধতি না অগ্রাহ্য করা উচিত, এবং।
সেনসফুল

আপনি যদি লোকেরা অ্যাপ্লিকেশন-বিস্তৃত ফন্ট সেট করতে আরও মার্জিত সমাধান জানেন তবে আমি সত্যিই এটি শুনতে চাই!
To1ne

উত্তর:


64

একটি বিভাগ আপনাকে বিদ্যমান শ্রেণিতে নতুন পদ্ধতি যুক্ত করতে দেয়। আপনি যদি ক্লাসে ইতিমধ্যে বিদ্যমান কোনও পদ্ধতিটিকে পুনরায় প্রতিস্থাপন করতে চান তবে আপনি সাধারণত বিভাগের পরিবর্তে একটি সাবক্লাস তৈরি করেন।

অ্যাপল ডকুমেন্টেশন: বিদ্যমান ক্লাসগুলি কাস্টমাইজ করা

কোনও বিভাগে ঘোষিত কোনও পদ্ধতির নামটি যদি মূল শ্রেণীর একটি পদ্ধতি বা একই শ্রেণীর অন্য শ্রেণির কোনও পদ্ধতি (বা এমনকি একটি সুপারক্লাস) এর মতো হয়, তবে কোন পদ্ধতিতে প্রয়োগ পদ্ধতিটি ব্যবহার করা হয়েছে তা আচরণটি অনির্ধারিত is রানটাইম

একই শ্রেণিতে হুবহু একই স্বাক্ষর সহ দুটি পদ্ধতি অনির্দেশ্য আচরণের দিকে পরিচালিত করবে, কারণ প্রতিটি আহ্বানকারী নির্দিষ্টকরণ করতে পারে না যে তারা কোন বাস্তবায়ন চায়।

সুতরাং, আপনি হয় একটি বিভাগ ব্যবহার করুন এবং শ্রেণীর জন্য নতুন এবং অনন্য পদ্ধতি পদ্ধতির নাম সরবরাহ করতে হবে, বা আপনি যদি ক্লাসে বিদ্যমান পদ্ধতির আচরণ পরিবর্তন করতে চান তবে সাবক্লাস।


4
আমি উপরে বর্ণিত সেই ধারণাগুলির সাথে সম্পূর্ণ সম্মত এবং বিকাশের সময় সেগুলি অনুসরণ করার চেষ্টা করছি। তবে এখনও কেস থাকতে পারে, যেখানে বিভাগে ওভাররাইড পদ্ধতিগুলি উপযুক্ত হতে পারে। উদাহরণস্বরূপ, একাধিক উত্তরাধিকার (সি ++ এর মতো) বা ইন্টারফেস (সি # এর মতো) ব্যবহৃত হতে পারে এমন ক্ষেত্রে। আমার প্রকল্পের সাথে এটির মুখোমুখি হয়েছি এবং বুঝতে পেরেছি যে বিভাগগুলিতে ওভাররাইডিং পদ্ধতিগুলি সেরা পছন্দ।
পিটনন

4
এটিতে সিঙ্গলটন রয়েছে এমন কিছু কোড পরীক্ষা করার সময় এটি কার্যকর হতে পারে। আদর্শভাবে, সিঙ্গেলনগুলি প্রোটোকল হিসাবে কোডের মধ্যে ইনজেকশনের হওয়া উচিত, যাতে আপনি বাস্তবায়নটি স্যুইচআউট করতে পারবেন। তবে আপনার কোডের মধ্যে ইতিমধ্যে যদি একটি এম্বেড থাকে তবে আপনি নিজের ইউনিট পরীক্ষায় সিঙ্গলটনের একটি বিভাগ যুক্ত করতে পারেন এবং ভাগ করা ইনস্ট্যান্স এবং কী কী পদ্ধতিগুলিকে ডামি অবজেক্টগুলিতে পরিণত করতে পারেন তা উপেক্ষা করতে পারেন।
বান্দেজপাটাইস

ধন্যবাদ @ সাইকোড্যাড। আমি লিঙ্কটি আপডেট করেছি এবং এই পোস্টের সাথে সম্পর্কিত ডকুমেন্টেশন থেকে একটি উদ্ধৃতি যুক্ত করেছি added
অস্থিরভাবে

ভাল লাগছে। অ্যাপল কি কোনও বিদ্যমান পদ্ধতির নাম সহ কোনও বিভাগ ব্যবহারের আচরণ সম্পর্কে ডকুমেন্টেশন সরবরাহ করে?
jjxtra

4
দুর্দান্ত, আমার যদি বিভাগ বা সাবক্লাসের সাথে যেতে হবে কিনা তা নিশ্চিত ছিল না :-)
কর্নিক্স

343

যদিও বিনীতভাবে বলা সমস্ত কিছু সঠিক, সতর্কতাটি কীভাবে দমন করা যায় তা আপনার প্রশ্নের উত্তর দেয় না।

যদি কোনও কারণে আপনার এই কোডটি রাখতে হয় (আমার ক্ষেত্রে আমার প্রকল্পে হকিকিট রয়েছে এবং তারা একটি ইউআইআইমেজ বিভাগে কোনও পদ্ধতিকে ওভাররাইড করে [সম্পাদনা করুন: এটি আর নেই)] এবং আপনার প্রকল্পটি সংকলনের জন্য আপনার দরকার , আপনি #pragmaসতর্কতাটিকে ব্লক করতে বিবৃতি ব্যবহার করতে পারেন :

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"

// do your override

#pragma clang diagnostic pop

আমি এখানে তথ্যটি পেয়েছি: http://www.cocoabuilder.com/archive/xcode/313767-disable-warning-for-override-in-category.html


অনেক ধন্যবাদ! সুতরাং, আমি দেখতে পাই প্রাগমাস সতর্কতাগুলিও দমন করতে পারে। :-p
কনস্টান্টিনো জারোহাস

হ্যাঁ, এবং এগুলি এলএলভিএম নির্দিষ্ট বিবৃতি হলেও জিসিসির জন্যও একই রকম রয়েছে।
বেন ব্যারন

4
আপনার পরীক্ষার প্রকল্পের সতর্কতা হ'ল লিঙ্কার সতর্কতা, কোনও এলএলভিএম সংকলক সতর্কতা নয়, সুতরাং llvm প্রগমা কিছুই করছে না। তবে, আপনি লক্ষ্য করবেন যে আপনার পরীক্ষার প্রকল্পটি এখনও "ত্রুটি হিসাবে সতর্কতাগুলি আচরণ করে" চালু করে কারণ এটি একটি লিঙ্কারের সতর্কতা।
বেন ব্যারন

12
এটি প্রকৃতপক্ষে গ্রহণযোগ্য উত্তর হওয়া উচিত, প্রদত্ত যে এটি আসলে প্রশ্নের উত্তর দেয়।
রব জোনস

4
এই উত্তরটি সঠিক হওয়া উচিত। যাইহোক, উত্তর হিসাবে নির্বাচিত ভোটার চেয়ে এটির বেশি ভোট রয়েছে।
জুয়ান কাতালান

20

একটি আরও ভাল বিকল্প (কেন এই সতর্কতা আপনাকে বিপর্যয় থেকে বাঁচাচ্ছে তার জন্য হাফির উত্তর দেখুন) পদ্ধতিটি সুইজলিং ব্যবহার করা। পদ্ধতি সুইজলিং ব্যবহার করে, আপনি কে "বিজয়ী", এবং পুরানো পদ্ধতিতে কল করার ক্ষমতা রক্ষা করার অনিশ্চয়তা ছাড়াই কোনও বিভাগ থেকে একটি বিদ্যমান পদ্ধতি প্রতিস্থাপন করতে পারেন। রহস্যটি হ'ল ওভাররাইডকে একটি ভিন্ন পদ্ধতির নাম দেওয়া, তারপরে রানটাইম ফাংশনগুলি ব্যবহার করে এগুলি অদলবদল করা।

#import <objc/runtime.h> 
#import <objc/message.h>

void MethodSwizzle(Class c, SEL orig, SEL new) {
    Method origMethod = class_getInstanceMethod(c, orig);
    Method newMethod = class_getInstanceMethod(c, new);
    if(class_addMethod(c, orig, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)))
        class_replaceMethod(c, new, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
    else
    method_exchangeImplementations(origMethod, newMethod);
}

তারপরে আপনার কাস্টম বাস্তবায়ন সংজ্ঞায়িত করুন:

+ (UIFont *)mySystemFontOfSize:(CGFloat)fontSize {
...
}

আপনার সাথে ডিফল্ট বাস্তবায়ন ওভাররাইড করুন:

MethodSwizzle([UIFont class], @selector(systemFontOfSize:), @selector(mySystemFontOfSize:));

10

আপনার কোড এ চেষ্টা করুন:

+(void)load{
    EXCHANGE_METHOD(Method1, Method1Impl);
}

আপডেট 2: এই ম্যাক্রো যুক্ত করুন

#import <Foundation/Foundation.h>
#define EXCHANGE_METHOD(a,b) [[self class]exchangeMethod:@selector(a) withNewMethod:@selector(b)]

@interface NSObject (MethodExchange)
+(void)exchangeMethod:(SEL)origSel withNewMethod:(SEL)newSel;
@end

#import <objc/runtime.h>

@implementation NSObject (MethodExchange)

+(void)exchangeMethod:(SEL)origSel withNewMethod:(SEL)newSel{
    Class class = [self class];

    Method origMethod = class_getInstanceMethod(class, origSel);
    if (!origMethod){
        origMethod = class_getClassMethod(class, origSel);
    }
    if (!origMethod)
        @throw [NSException exceptionWithName:@"Original method not found" reason:nil userInfo:nil];
    Method newMethod = class_getInstanceMethod(class, newSel);
    if (!newMethod){
        newMethod = class_getClassMethod(class, newSel);
    }
    if (!newMethod)
        @throw [NSException exceptionWithName:@"New method not found" reason:nil userInfo:nil];
    if (origMethod==newMethod)
        @throw [NSException exceptionWithName:@"Methods are the same" reason:nil userInfo:nil];
    method_exchangeImplementations(origMethod, newMethod);
}

@end

4
এটি সম্পূর্ণ উদাহরণ নয়। EXCHANGE_METHOD নামের কোনও ম্যাক্রো আসলে উদ্দেশ্য-সি রানটাইম দ্বারা সংজ্ঞায়িত করা হয়নি।
রিচার্ড জে রস তৃতীয়

পছন্দ করুন এই পদ্ধতিটি শ্রেণির ধরণের জন্য প্রয়োগ করা হয় না। আপনি কোন কাঠামো ব্যবহার করছেন?
রিচার্ড জে রস তৃতীয়

দুঃখিত, আবার চেষ্টা করে দেখুন আমি এনএসবজেক্ট + মেথড এক্সচেঞ্জ
ভিটাল্লি গার্ভাজুক

এনএসবজেক্টে বিভাগ সহ কেন ম্যাক্রো দিয়ে বিরক্ত করবেন? শুধু 'এক্সচেঞ্জমাথোড' দিয়ে কেন ঘুঘু নয়?
হাভানব্রুগ

5

আপনি এই সংকলক সতর্কতা দমন করতে পদ্ধতি সুইজলিং ব্যবহার করতে পারেন। আমরা যখন ইউআইটিেক্সটবারর্ডার স্টাইলননের সাথে একটি কাস্টম ব্যাকগ্রাউন্ড ব্যবহার করি তখন একটি ইউআইটিেক্সটফিল্ডে মার্জিন আঁকার জন্য পদ্ধতি সুইজলিংটি এখানে কীভাবে প্রয়োগ করেছি:

#import <UIKit/UIKit.h>

@interface UITextField (UITextFieldCatagory)

+(void)load;
- (CGRect)textRectForBoundsCustom:(CGRect)bounds;
- (CGRect)editingRectForBoundsCustom:(CGRect)bounds;
@end

#import "UITextField+UITextFieldCatagory.h"
#import <objc/objc-runtime.h>

@implementation UITextField (UITextFieldCatagory)

+(void)load
{
    Method textRectForBounds = class_getInstanceMethod(self, @selector(textRectForBounds:));
    Method textRectForBoundsCustom = class_getInstanceMethod(self, @selector(textRectForBoundsCustom:));

    Method editingRectForBounds = class_getInstanceMethod(self, @selector(editingRectForBounds:));
    Method editingRectForBoundsCustom = class_getInstanceMethod(self, @selector(editingRectForBoundsCustom:));


    method_exchangeImplementations(textRectForBounds, textRectForBoundsCustom);
    method_exchangeImplementations(editingRectForBounds, editingRectForBoundsCustom);

}


- (CGRect)textRectForBoundsCustom:(CGRect)bounds
{
    CGRect inset = CGRectMake(bounds.origin.x + 10, bounds.origin.y, bounds.size.width - 10, bounds.size.height);
    return inset;
}

- (CGRect)editingRectForBoundsCustom:(CGRect)bounds
{
    CGRect inset = CGRectMake(bounds.origin.x + 10, bounds.origin.y, bounds.size.width - 10, bounds.size.height);
    return inset;
}

@end

2

ওভার-রাইডিং বৈশিষ্ট্যগুলি একটি শ্রেণিবদ্ধকরণ (বেনামে বিভাগ) এর জন্য বৈধ, তবে নিয়মিত বিভাগের জন্য নয়।

ক্লাস এক্সটেনশন (অজ্ঞাতনামা বিভাগ) ব্যবহার করে অ্যাপল ডক্সের মতে আপনি একটি সার্বজনীন শ্রেণিতে একটি ব্যক্তিগত ইন্টারফেস তৈরি করতে পারেন, যেমন ব্যক্তিগত ইন্টারফেসটি প্রকাশ্যে প্রকাশিত বৈশিষ্ট্যগুলিকে ওভাররাইড করতে পারে। অর্থ্যাৎ আপনি রিডোনলি থেকে রিড রাইটারে কোনও সম্পত্তি পরিবর্তন করতে পারেন।

এর ব্যবহারের ক্ষেত্রে হ'ল আপনি যখন লাইব্রেরিগুলি লেখেন যা জনসাধারণের সম্পত্তিগুলিতে অ্যাক্সেসকে সীমাবদ্ধ করে, যখন একই সম্পত্তিটির লাইব্রেরির মধ্যে সম্পূর্ণ পাঠ্য লেখার অ্যাক্সেসের প্রয়োজন হয়।

অ্যাপল ডক্স লিঙ্ক: https://developer.apple.com/library/ios/docamentation/Cocoa/Concepual/ProgrammingWithObjectiveC/CustomizingExistingClass/CustomizingExistingClasses.html

" ব্যক্তিগত তথ্য গোপন করতে শ্রেণিবদ্ধকরণগুলি ব্যবহার করুন " অনুসন্ধান করুন

সুতরাং এই কৌশলটি শ্রেণিবদ্ধকরণের জন্য বৈধ, তবে কোনও বিভাগের জন্য নয়।


1

বিভাগগুলি একটি ভাল জিনিস, তবে তাদের অপব্যবহার করা যেতে পারে। বিভাগগুলি লেখার সময় নীতি হিসাবে আপনার হওয়া উচিত বহির্গমন পদ্ধতির পুনরায় প্রয়োগ করা উচিত নয়। এটি করার ফলে অদ্ভুত পার্শ্ব প্রতিক্রিয়া হতে পারে কারণ আপনি এখন কোডটি পুনরায় লিখছেন যে অন্য শ্রেণি একটি নির্ভর করে। আপনি একটি পরিচিত ক্লাসটি ভেঙে ফেলতে পারেন এবং আপনার ডিবাগারটিকে অভ্যন্তরে পরিণত করতে পারেন। এটি কেবল খারাপ প্রোগ্রামিং।

আপনার যদি এটি করতে প্রয়োজন হয় তবে আপনার এটি অবশ্যই সাবক্লাস করা উচিত।

তারপরে সাঁতার কাটার পরামর্শ, এটি আমার কাছে একটি বড় NO-NO-NO।

রানটাইম এ এটি সাঁতার কাটা একটি সম্পূর্ণ NO-NO-NO।

আপনি একটি কলা কমলার মতো দেখতে চান তবে কেবল রানটাইমে? আপনি যদি কমলা চান তবে কমলা লিখুন।

ডান কোনও কলা চেহারা তৈরি করে এবং কমলার মতো কাজ করবে না। আরও খারাপ: আপনার কলাটি কোনও গোপন এজেন্টে পরিণত করবেন না যিনি কমলাগুলির সমর্থনে চুপচাপ বিশ্বব্যাপী কলা নাশকতা করবেন।

হায়!


4
রানটাইমের সময় সাঁতার কাটা পরিবেশের পরীক্ষার ক্ষেত্রে বিদ্রূপমূলক আচরণের জন্য কার্যকর হতে পারে।
বেন জি

4
যদিও হাস্যকর, আপনার উত্তরটি সমস্ত সম্ভাব্য পদ্ধতিগুলি খারাপ বলার অপেক্ষা রাখে না। জন্তুটির প্রকৃতি হ'ল কখনও কখনও আপনি সত্যিই সাবক্লাস করতে পারবেন না, তাই আপনাকে একটি বিভাগ রেখে দেওয়া হয়েছে এবং বিশেষত আপনি যদি শ্রেণিভুক্ত করছেন এমন শ্রেণীর কোডটি নিজের হাতে না রাখেন, কখনও কখনও আপনাকে সুইজল করতে হবে এবং এটি একটি অনাকাঙ্ক্ষিত পদ্ধতি হওয়া প্রাসঙ্গিক নয়।
হাভানব্রুগ

1

মূল শ্রেণিটি (যদিও সেখানে কোনও প্রধান শ্রেণীর প্রয়োগ ছিল না) এর পরিবর্তে কোনও বিভাগে আমি একটি প্রতিনিধি পদ্ধতি প্রয়োগ করি তখন আমার এই সমস্যা হয়েছিল। আমার জন্য সমাধানটি ছিল প্রধান শ্রেণির শিরোনাম ফাইল থেকে বিভাগের শিরোনাম ফাইলটিতে স্থানান্তর করা যা এটি কাজ করে

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.