ইউআইএনএভিগেশন কন্ট্রোলার প্রোগ্রামে ইউআইএনএভিগেশন বারের একটি কাস্টম সাবক্লাস সেট করুন


92

কেউ কি জানেন UINavigationBarযে আমি UINavigationControllerপ্রোগ্রামটিমে (আইবি ছাড়াই) ইনস্ট্যান্টেশন দিলে আমি কীভাবে আমার কাস্টম সাবক্লাস ব্যবহার করতে পারি ?

আইবিতে একটি টেনে আনুন UINavigationControllerআমাকে নেভিগেশন বারের নীচে দেখান এবং আইডেন্টিটি ইন্সপেক্টরি ব্যবহার করে আমি ক্লাসের ধরণটি পরিবর্তন করতে পারি এবং নিজস্ব সাবক্লাস সেট UINavigationBarকরতে পারি তবে প্রোগ্রামিকভাবে আমি পারি না, navigationBarনেভিগেশন কন্ট্রোলারের সম্পত্তি কেবল পাঠযোগ্য ...

প্রোগ্রামিং হিসাবে নেভিগেশন বারটি কাস্টমাইজ করতে আমার কী করা উচিত? আইবি "কোড" এর চেয়ে বেশি "শক্তিশালী"? আমি বিশ্বাস করি যে আইবিতে যা করা যায় তা প্রোগ্রামগতভাবেও করা যেতে পারে।


আপনার ভাগ্য কি অন্য কোথাও সমাধান খুঁজে পেয়েছেন?
prendio2

আপনি এটি সম্পর্কে কোন উত্তর পেতে পারি?
হৃশিকেশ বেতাই

উত্তর:


89

আপনার কেবলমাত্র এক্সভিবি দিয়ে কেভিসি ব্যবহার করা উচিত নয়।

[self.navigationController setValue:[[[CustomNavBar alloc]init] autorelease] forKeyPath:@"navigationBar"];

এই সমাধানটি কবজির মতো কাজ করে (কমপক্ষে আইওএস 5.1 এ)। অন্য সমস্ত সমাধানগুলি আরও বেশি কাজ করার মতো বলে মনে হচ্ছে। তবুও ডাউনসাইড খুঁজছে।
ড্যানিয়েল

6
আপনি কীভাবে নেভিগেশন নিয়ামকের জন্য এই কী পথটি "" নেভিগেশনবার "খুঁজে পেয়েছেন? আপনি কি এটি ভাগ করে নিতে পারেন
ইকবাল খান

আপনি কি নিশ্চিত যে এর ফলে অ্যাপ্লিকেশন প্রত্যাখ্যান হবে না? আমি এই নথিটি বাস্তবে কোথাও দেখিনি।
বনি উৎপল

ধন্যবাদ! আইওএস 6 বিটা 3 এ দুর্দান্ত কাজ করে! @ বনিউপাল কেভিসি অবশ্যই নথিবদ্ধ, আমরা কেবল এটি একটি কী দিয়ে ব্যবহার করছি যা খুঁজে পাওয়া কিছুটা কঠিন। আমি মনে করি এটিই মূল বিষয়।
জোহানেস লন্ড

9
এটি হ্যাকি এএফ
ম্যাটসভেন

66

আইওএস 5 থেকে, আপেল সরাসরি এটি করার জন্য একটি পদ্ধতি সরবরাহ করে। রেফারেন্স

UINavigationController *navigationController= [[UINavigationController alloc]initWithNavigationBarClass:[CustomNavBar class] toolbarClass:nil];
[navigationController setViewControllers:[NSArray arrayWithObject:yourRootViewController]];

@ ননামেলাইভ আসলে নয়, আইওএস in-তে যুক্ত হয়েছে: বিকাশকারী.অ্যাপল.
com

7
হ্যাঁ, এটি আইওএস 6 এ যুক্ত হয়েছে, তবে এটি আইওএস 5 এও সমর্থিত An একটি অ্যাপল ইঞ্জিনিয়ার উল্লেখ করেছেন যে
ডাব্লুডাব্লুডিসি

37

আইওএস 4 হিসাবে, আপনি UINibএই সমস্যাটি সমাধানে সহায়তা করতে ক্লাসটি ব্যবহার করতে পারেন ।

  1. আপনার কাস্টম UINavigationBarসাবক্লাস তৈরি করুন ।
  2. একটি খালি xib তৈরি করুন, UINavigationControllerএকক বস্তু হিসাবে একটি যুক্ত করুন ।
  3. UINavigationControllerএর UINavigationBarজন্য আপনার কাস্টম সাবক্লাসে শ্রেণি সেট করুন ।
  4. এই পদ্ধতির একটির মাধ্যমে আপনার রুট ভিউ নিয়ন্ত্রকটি সেট করুন:
    • [navController setViewcontrollers[NSArray arrayWithObject:myRootVC]];
    • [navController pushViewController:myRootVC];

কোডে:

UINib *nib = [UINib nibWithNibName:@"YourCustomXib" bundle:nil];
UINavigationController *navController = 
             [[nib instantiateWithOwner:nil options:nil] objectAtIndex:0];


এখন আপনি UINavigationControllerআপনার কাস্টম সঙ্গে একটি পেয়েছেন UINavigationBar


তারপরে আপনি কীভাবে রুটভিউ কনট্রোলার সেট করবেন?
স্মরণে

আপনি [নবকন্ট্রোলার সেটভিউ কনট্রোলারগুলি ব্যবহার করেন: [এনএসআর অ্যারেউইট অবজেক্ট: <YOUR_ROOT_CONTROLLER>]]

দুঃখিত, আপনি [নব্যকন্ট্রোলার পুশভিউ কনট্রোলার ব্যবহার করেন: <YOUR_ROOT_CONTROLLER> অ্যানিমেটেড: কোনও]
কনফেয়ার

4
আইএমএইচও এটি কখনও কখনও অপরিবর্তনীয় হ্যাক করার সর্বনিম্ন "হ্যাকিশ" উপায়।
ডেভিড পিসনি

4
আসলে, একটি বিজোড় সমস্যা। আমি যখন এটি করি ন্যাভিগেশন কন্ট্রোলারের আইটেমটি নেভিগেশন-তে সেট করা হচ্ছে না এমন ভিউকন্ট্রোলারের জন্য বরাদ্দ করা আইটেম সম্পত্তি যা আমি (খালি) স্ট্যাকের উপর চাপ দিচ্ছি।
ডেভিড পিসোনি

26

আমি যতদূর বলতে পারি, কখনও কখনও ইউআইএনএভিগেশনবারকে সাবক্লাস করা দরকার হয়, কিছু অমানুষিক স্ট্যান্ডার্ড রিসাইলিং করা। বিভাগগুলি ব্যবহার করে এটি করা থেকে বিরত হওয়া কখনও কখনও সম্ভব তবে সবসময় নয়।

বর্তমানে, আমি যতদূর জানি, ইউআইভিউকন্ট্রোলারের মধ্যে কাস্টম ইউআইএনএভিগেশন বার সেট করার একমাত্র উপায় আইবি (যা কোনও সংরক্ষণাগার মাধ্যমে) হয় - এটি সম্ভবত সেভাবে হওয়া উচিত নয়, তবে আপাতত, আমরা এটির সাথেই বেঁচে থাকব।

এটি প্রায়শই সূক্ষ্ম হয় তবে কখনও কখনও আইবি ব্যবহার করা সত্যিই সম্ভব হয় না।

সুতরাং, আমি তিনটি বিকল্প দেখেছি:

  1. সাবক্লাস ইউআইএনএভিগেশন বার এবং এটি সমস্ত আইবিতে জড়িয়ে রাখুন, তারপরে যতবারই আমি ইউআইএনএভিগেশন কন্ট্রোলার চাইতাম তখনই নিব লোড করা নিয়ে ব্যঙ্গ করে,
  2. সাবক্লাসিংয়ের পরিবর্তে, ইউআইএনএভিগেশনবারের আচরণ পরিবর্তন করতে একটি বিভাগের মধ্যে পদ্ধতি প্রতিস্থাপন ব্যবহার করুন বা
  3. সাবক্লাস ইউআইএনএভিগেশন বার এবং ইউআইএনএভিগেশন কন্ট্রোলার সংরক্ষণাগারভুক্ত / সংরক্ষণাগারবদ্ধ করার বিষয়ে কিছুটা মাকিং কর।

এই ক্ষেত্রে বিকল্পটি আমার জন্য অপরিবর্তনীয় (বা কমপক্ষে খুব বিরক্তিকর) ছিল, যেমন আমি ইউআইএনএভিগেশন কন্ট্রোলার প্রোগ্রামগতভাবে তৈরি করার দরকার ছিল, 2 আমার মতে কিছুটা বিপজ্জনক এবং শেষ-রিসর্ট বিকল্প হিসাবে আরও বেশি, তাই আমি বিকল্প 3 বেছে নিয়েছি।

আমার দৃষ্টিভঙ্গি ছিল একটি ইউআইএনএভিগেশন কন্ট্রোলারের একটি 'টেম্পলেট' সংরক্ষণাগার তৈরি করা এবং এটি সংরক্ষণ করে সংরক্ষণাগার ফিরিয়ে দেওয়া initWithRootViewController

এখানে কীভাবে:

আইবিতে, আমি ইউআইএনএভিগেশনবারের জন্য উপযুক্ত শ্রেণীর সেট সহ একটি ইউআইএনএভিগেশন কন্ট্রোলার তৈরি করেছি।

তারপরে, আমি বিদ্যমান নিয়ামকটি নিয়েছিলাম এবং এটির একটি সংরক্ষণাগারভুক্ত কপি ব্যবহার করে সংরক্ষণ করেছি +[NSKeyedArchiver archiveRootObject:toFile:]। আমি সিমুলেটারে সবেমাত্র অ্যাপের প্রতিনিধিটির মধ্যে এটি করেছি।

তারপরে আমি আমার সাবক্লাসে সংরক্ষণাগারিত সংস্করণটি এম্বেড করতে, সংরক্ষিত ফাইল থেকে সি কোড তৈরি করতে -i পতাকা সহ 'xxd' ইউটিলিটিটি ব্যবহার করেছি xxd -i path/to/file

মধ্যে initWithRootViewControllerআমি আর্কাইভ মুক্ত যে টেমপ্লেট, এবং আর্কাইভ মুক্ত ফলাফলের সাথে প্রাসঙ্গিক সেট স্ব:

// This is the data from [NSKeyedArchiver archivedDataWithRootObject:controller], where
// controller is a CTNavigationController with navigation bar class set to CTNavigationBar,
// from IB.  This c code was created using 'xxd -i'
static unsigned char archived_controller[] = {
    0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30, 0xd4, 0x01, 0x02, 0x03,
    ...
};
static unsigned int archived_controller_len = 682;

...

- (id)initWithRootViewController:(UIViewController *)rootViewController {
     // Replace with unarchived view controller, necessary for the custom navigation bar
     [self release];
     self = (CTNavigationController*)[NSKeyedUnarchiver unarchiveObjectWithData:[NSData dataWithBytes:archived_controller length:archived_controller_len]];
     [self setViewControllers:[NSArray arrayWithObject:rootViewController]];
     return [self retain];
}

তারপরে, আমি কেবলমাত্র আমার ইউআইভিউকন্ট্রোলার সাবক্লাসের একটি নতুন উদাহরণ দখল করতে পারি যার কাস্টম নেভিগেশন বার সেট রয়েছে:

UIViewController *modalViewController = [[[CTNavigationController alloc] initWithRootViewController:myTableViewController] autorelease];
[self.navigationController presentModalViewController:modalViewController animated:YES];

এটি আমাকে একটি নেভিগেশন বার এবং সরঞ্জামদণ্ডের সাথে সেট আপ করা এবং কাস্টম নেভিগেশন বারের স্থানে ক্লাস সহ একটি মডেল ইউআইটিএবলভিউ কনট্রোলার দেয়। আমার কোনও সামান্য-ন্যক্কারজনক পদ্ধতি প্রতিস্থাপন করার দরকার পড়েনি, এবং যখন আমি সত্যিই প্রোগ্রামালিকভাবে কাজ করতে চাই তখন আমাকে নিবসের সাথে বিদ্রূপ করতে হবে না।

আমি +layerClassইউআইএনএভিগেশন কন্ট্রোলারের মধ্যে সমতুল্য দেখতে চাই - +navigationBarClass- তবে আপাতত, এটি কাজ করে।


5

আমি "বিকল্প 1" ব্যবহার করি

এতে কেবল ইউআইএনএভিগেশন কন্ট্রোলার দিয়ে একটি নিব-ফাইল তৈরি করুন। এবং ইউআইএনএভিগেশন বার ক্লাসটি আমার কাস্টম ক্লাসে সেট করুন।

self.navigationController = [[[NSBundle mainBundle] loadNibNamed:@"navigationbar" owner:self options:nil] lastObject];

[navigationController pushViewController:rootViewController animated:YES];

সুতরাং নিব-ফাইলের উপযুক্ত নামটি লোডনিব নামড: @ "নেভিগেশন কনট্রোলার? আপনি আসলে নিব থেকে পুরো নেভিগেশন নিয়ন্ত্রকটি পাচ্ছেন এবং কেবল
বারই নয়,

এটি আমার পক্ষে কাজ করে তবে আমি যখন আমার টেবিলভিউতে যে কোনও বিকল্পে ক্লিক করি তখন আমি পিছনের বোতামটি হারাব।
jfisk

5

মাইকেল এর সমাধান কাজ করে তবে আপনি এনএসকিডআর্চিভার এবং 'এক্সএক্সডিডি' ইউটিলিটি এড়াতে পারবেন। কেবলমাত্র সাবক্লাস ইউআইএনএভিগেশন নিয়ন্ত্রক এবং ওভাররাইড initWithRootViewController, আপনার কাস্টম নেভিগেশন নিয়ন্ত্রক এনআইবি সরাসরি লোড করছে:

- (id) initWithRootViewController:(UIViewController *)rootViewController
{
    [self release];
    self = [[[[NSBundle mainBundle] loadNibNamed:@"CTNavigationController" owner:nil options:nil] objectAtIndex:0] retain];  
    [self setViewControllers:[NSArray arrayWithObject:rootViewController]];
    return self;
}

4

আপডেট:object_SetClass() আইওএস 5 জিএম ব্যবহার করে আর কাজ করে না। নীচে একটি বিকল্প সমাধান যুক্ত করা হয়েছে।

এনএভি-বার্ডের জন্য সংরক্ষণাগারহীন শ্রেণিটি ম্যানুয়ালি সেট করতে NSKeyedUnarchiver ব্যবহার করুন।

   MyViewController *controller = [[[MyViewController alloc] init] autorelease];
   NSKeyedUnarchiver *unarchiver = [[[NSKeyedUnarchiver alloc] initForReadingWithData:[NSKeyedArchiver archivedDataWithRootObject:controller]] autorelease];
   [unarchiver setClass:[MyNavigationBar class] forClassName:@"UINavigationBar"];
   controller = [unarchiver decodeObjectForKey:@"root"];




দ্রষ্টব্য: এই আসল সমাধানটি কেবল প্রাক-আইওএস 5-এর কাজ করে:

একটি দুর্দান্ত সমাধান রয়েছে, যা আমি এখানে পোস্ট করেছি - সরাসরি আপনার ভিউতে নেভবার সাবক্লাসটি ইনজেক্ট করুন UINavigationController:

#import <objc/runtime.h>

- (void)viewDidLoad {
    [super viewDidLoad];

    object_setClass(self.navigationController.navigationBar, [MyNavBar class]);
    // the rest of your viewDidLoad code
}

পূর্ববর্তী উত্তরে আমি যেমনটি ইঙ্গিত করেছি আপনি এটি পোস্ট করেছেন - আইওএস 5 এর সোনার মাস্টার এটি ভেঙেছে। যদিও অন্যান্য বিকল্প উপলব্ধ আছে, তাই আমি একটি বিকল্প পদ্ধতি দিয়ে সম্পাদনা করব।
স্মারক

1

একটি দৃশ্যে আমি দেখতে পেয়েছি যে বিভাগের পরিবর্তে আমাদের সাবক্লাস ব্যবহার করা দরকার প্যাটার্ন চিত্র সহ নেভিগেশনবারের ব্যাকগ্রাউন্ড কালার সেট করা, কারণ আইওএস 5-তে ওভাররাইটিং অঙ্কন বিভাগ ব্যবহার করে আর কাজ করে না। আপনি যদি ios3.1-5-0.0 সমর্থন করতে চান তবে আপনি কেবলমাত্র সাবক্লাস নেভিগেশনবারটিই করতে পারেন।


1

এই বিভাগের পদ্ধতি বিপজ্জনক এবং novices জন্য নয়। এছাড়াও আইওএস 4 এবং আইওএস 5 এর জটিলতা পৃথক হওয়ার কারণে এটি এমন একটি অঞ্চল তৈরি করে যা বহু লোকের জন্য বাগ তৈরি করতে পারে। এখানে আমি একটি সহজ সাবক্লাস ব্যবহার করি যা আমি iOS4.0 ~ iOS6.0 সমর্থন করে এবং খুব সহজ।

.হ

@interface XXXNavigatioNBar : UINavigationBar
@end

.ম

#import "XXXNavigationBar.h"

#import <objc/runtime.h>

@implementation XXXNavigationBar

- (void) didMoveToSuperview {
    if( [self respondsToSelector: @selector(setBackgroundImage:forBarMetrics:)]) {
        //iOS5.0 and above has a system defined method -> use it
        [self setBackgroundImage: [UIImage imageNamed: @"nav-bar"]
                   forBarMetrics: UIBarMetricsDefault];
    }
    else {
        //iOS4.0 requires us to override drawRect:. BUT!!
        //If you override drawRect: on iOS5.0 the system default will break,
        //so we dynamically add this method if required
        IMP implementation = class_getMethodImplementation([self class], @selector(iOS4drawRect:));
        class_addMethod([self class], @selector(drawRect:), implementation, "v@:{name=CGRect}");
    }
}

- (void)iOS4drawRect: (CGRect) rect {
    UIImage* bg = [UIImage imageNamed:@"nav-bar-blue"];
    [bg drawInRect: rect];
}

@end

0

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

আপনি কী করার চেষ্টা করছেন যে সাবক্লাসিংয়ের প্রয়োজন?

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


4
হাই বেন, ধন্যবাদ আমি জানি ইউআইএনএভিগেশনবার সাবক্লাস করার সর্বোত্তম উপায় নয় তবে আমি ব্যাকগ্রাউন্ড চিত্রটি ওভাররাইডিং ড্রইরেক্ট: পদ্ধতিটি সেটআপ করতে চাই। সমস্যাটি হ'ল আইবি আমি ব্যবহার করে একটি ইউআইএনএভিগেশন কন্ট্রোলার নেভিগেশন বারের শ্রেণি পরিবর্তন করতে পারি তবে প্রোগ্রাম্যালি আমি তা পারি না। এবং হ্যাঁ, আইবি প্রকৃতপক্ষে নেভিগেশন বারটি প্রতিস্থাপন করছে: এনএসলগ (@ "% @", স্ব.নিভিশনকন্ট্রোলআরনভিশন বার); <কাস্টমনাভিশনবার: 0x1806160; বেসক্লাস = ইউআইএনএভিগেশনবার; ফ্রেম = (0 20; 320 44); ক্লিপসটোবাউন্ডস = হ্যাঁ; অস্বচ্ছ = NO; autoresize = ডাব্লু; স্তর = <CALayer: 0x1806da0 >>
Duccio

আমিও এই একই কৌশলটি ব্যবহার করছি, এবং এটি আইওএস 5-এ কাজ চালিয়ে যাচ্ছে (ইউআইএনএভিগেশন বার বিভাগের কৌশলটির মত নয়)
ডেভিড পিসনি

0

যদি আপনি কেবল পটভূমি চিত্র পরিবর্তন করতে নাভবার সাবক্লাস করতে চান - আইওএসে 5 করার দরকার নেই There এখানে একটি সেটব্যাকগ্রাউন্ড ইমেজির মতো পদ্ধতি থাকবে


4
আপনি setBackgroundImage:forBarMetrics:এখানে বর্ণিত হিসাবে ব্যবহার করতে হবে : বিকাশকারী.অ্যাপল.
com

0

Obb64 এর মন্তব্যের উপরন্তু, আমি তার কৌতুক ব্যবহার শেষ পর্যন্ত setViewControllers:animated:যেমন নিয়ামক সেট করতে rootControllerজন্য navigationControllerনিব থেকে লোড। আমি যে কোডটি ব্যবহার করছি তা এখানে:

- (void) presentModalViewControllerForClass: (Class) a_class {
  UINavigationController *navController = [[[NSBundle mainBundle] loadNibNamed: @"CustomNavBar" owner:self options:nil] lastObject];

  LoginSignupBaseViewController *controller = [[a_class alloc] initWithNibName: nil bundle: nil];
  controller.navigationController = navController;
  [navController setViewControllers: A(controller) animated: NO];

  [self presentModalViewController: navController animated: YES];

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