如何从 class 本身中初始化自定义视图控制器?
How do I initialize a custom view controller from within the class itself?
我正在尝试使用第三方库 MBPullDownController 制作类似 Google 地图应用中的向上滑动面板的东西。
这是库中的示例代码:
UITableViewController *front = [[UITableViewController new];
UIViewController *back = [[UIViewController new];
MBPullDownController *pullDownController = [[MBPullDownController alloc] initWithFrontController:front backController:back];
[self.navigationController pushViewController:pullDownController animated:NO];
从不同的视图控制器导航到它时工作正常。但是我的地图控制器有四五个其他视图控制器直接指向它,所以我尝试从地图控制器本身进行初始化。
我试过使我的视图控制器成为 MBPullDownController 的子类,并尝试在 initUsingCoder:
方法中初始化它,如下所示:
MapViewController.h
#import <UIKit/UIKit.h>
#import <GoogleMaps/GoogleMaps.h>
#import "MBPullDownController.h"
....
@interface MapViewController : MBPullDownController<GMSMapViewDelegate>
....
@end
MapViewController.m
#import "MapViewController.h"
#import <GoogleMaps/GoogleMaps.h>
#import "LocationUtility.h"
#import "MBPullDownController.h"
...
@interface MapViewController () <CLLocationManagerDelegate>
@property (strong, nonatomic) CLLocationManager *locationManager;
@end
@implementation MapViewController {
GMSMapView *mapView;
NSMutableDictionary *markers;
}
@implementation MapViewController {
GMSMapView *mapView;
NSMutableDictionary *markers;
UITableViewController *front;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
front = [UITableViewController new];
self = (MapViewController *)[[MBPullDownController alloc]initWithFrontController:front backController:self ];
}
return self;
}
....
我收到警告 'This coder requires that replaced objects be returned from initWithCoder:'
,显然是因为 self = [super initWithCoder:aDecoder]
被 self = (MapViewController *)[[MBPullDownController alloc]initWithFrontController:front backController:self ];
取代了
如何正确地将视图控制器初始化为 MBPullDownController 本身?
实际上我在写问题的过程中找到了解决方案,但我想我会坚持下去以帮助其他遇到同样问题的人,因为答案并不容易找到。
解决方法是使用-(id)awakeAfterUsingCoder:(NSCoder *)aDecoder
方法,即"allows you to substitute another object in place of the object that was decoded" (source).
- (id)awakeAfterUsingCoder:(NSCoder *)aDecoder
{
if (self) {
front = [UITableViewController new];
self = (MapViewController *)[[MBPullDownController alloc]initWithFrontController:front backController:self ];
}
return self;
}
问题是您正在尝试使用初始化器 initWithFrontController.. 而不是 initWithCoder 来初始化 MBPullDownController 的实例,这是 iOS 在从 nib 实例化对象时强制您调用的那个。
该库应该有另一个名为 initWithCoder: andFrontController: andBackController 的方法,负责调用 super 并正确设置子控制器。
但是,由于没有提供,创建者似乎同时设置了 frontController 和 backController public。这通常(如果他做得好)意味着您可以在调用 initializr 后随意设置这些属性。所以我会尝试:
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
self.frontController = [UITableViewController new];
self.backController = self;
}
return self;
}
如果这不起作用,您应该在 github 中创建一个问题并告诉创建者添加 initWithCoder 初始值设定项,并使用 awakeAfterUsingCoder
保持您的解决方案
我正在尝试使用第三方库 MBPullDownController 制作类似 Google 地图应用中的向上滑动面板的东西。
这是库中的示例代码:
UITableViewController *front = [[UITableViewController new];
UIViewController *back = [[UIViewController new];
MBPullDownController *pullDownController = [[MBPullDownController alloc] initWithFrontController:front backController:back];
[self.navigationController pushViewController:pullDownController animated:NO];
从不同的视图控制器导航到它时工作正常。但是我的地图控制器有四五个其他视图控制器直接指向它,所以我尝试从地图控制器本身进行初始化。
我试过使我的视图控制器成为 MBPullDownController 的子类,并尝试在 initUsingCoder:
方法中初始化它,如下所示:
MapViewController.h
#import <UIKit/UIKit.h>
#import <GoogleMaps/GoogleMaps.h>
#import "MBPullDownController.h"
....
@interface MapViewController : MBPullDownController<GMSMapViewDelegate>
....
@end
MapViewController.m
#import "MapViewController.h"
#import <GoogleMaps/GoogleMaps.h>
#import "LocationUtility.h"
#import "MBPullDownController.h"
...
@interface MapViewController () <CLLocationManagerDelegate>
@property (strong, nonatomic) CLLocationManager *locationManager;
@end
@implementation MapViewController {
GMSMapView *mapView;
NSMutableDictionary *markers;
}
@implementation MapViewController {
GMSMapView *mapView;
NSMutableDictionary *markers;
UITableViewController *front;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
front = [UITableViewController new];
self = (MapViewController *)[[MBPullDownController alloc]initWithFrontController:front backController:self ];
}
return self;
}
....
我收到警告 'This coder requires that replaced objects be returned from initWithCoder:'
,显然是因为 self = [super initWithCoder:aDecoder]
被 self = (MapViewController *)[[MBPullDownController alloc]initWithFrontController:front backController:self ];
如何正确地将视图控制器初始化为 MBPullDownController 本身?
实际上我在写问题的过程中找到了解决方案,但我想我会坚持下去以帮助其他遇到同样问题的人,因为答案并不容易找到。
解决方法是使用-(id)awakeAfterUsingCoder:(NSCoder *)aDecoder
方法,即"allows you to substitute another object in place of the object that was decoded" (source).
- (id)awakeAfterUsingCoder:(NSCoder *)aDecoder
{
if (self) {
front = [UITableViewController new];
self = (MapViewController *)[[MBPullDownController alloc]initWithFrontController:front backController:self ];
}
return self;
}
问题是您正在尝试使用初始化器 initWithFrontController.. 而不是 initWithCoder 来初始化 MBPullDownController 的实例,这是 iOS 在从 nib 实例化对象时强制您调用的那个。
该库应该有另一个名为 initWithCoder: andFrontController: andBackController 的方法,负责调用 super 并正确设置子控制器。
但是,由于没有提供,创建者似乎同时设置了 frontController 和 backController public。这通常(如果他做得好)意味着您可以在调用 initializr 后随意设置这些属性。所以我会尝试:
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
self.frontController = [UITableViewController new];
self.backController = self;
}
return self;
}
如果这不起作用,您应该在 github 中创建一个问题并告诉创建者添加 initWithCoder 初始值设定项,并使用 awakeAfterUsingCoder
保持您的解决方案