【发布时间】:2012-07-26 20:19:51
【问题描述】:
是否可以在 A 类中创建一个对象的实例并从 B 类访问该对象的同一个实例?我正在尝试开发一个使用 NSInputStream 和 NSOutputStream 创建 TCP Socket 的应用程序,并且需要多个类才能访问它。
谢谢你, 特拉维斯·埃利奥特
编辑
这是我正在使用的代码。它是一个处理套接字连接的程序。我基本上需要能够从我的 appDelegate 和 View 控制器与同一个套接字进行通信。这是我根据您的帮助获得的代码。我使用 appDelegate 作为控件(在您的示例中为 D),也许我不能这样做。 CommunicationHub 是我需要从 AppDelegate 和 ViewController 控制相同实例的类。
AppDelegate.h
#import <UIKit/UIKit.h>
#import "ViewController.h"
#import "CommunicationHub.h"
@interface AppDelegate : UIResponder <UIApplicationDelegate>{
ViewController *viewController;
CommunicationHub *cHub;
}
@property (strong, nonatomic) UIWindow *window;
@property (strong, retain) ViewController *viewController;
@property (strong, retain) CommunicationHub *cHub;
-(void)CreateInstances;
@end
AppDelegate.m
#import "AppDelegate.h"
#import "ViewController.h"
@implementation AppDelegate
@synthesize viewController;
@synthesize cHub;
@synthesize window = _window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self CreateInstances];
// Override point for customization after application launch.
return YES;
}
-(void)CreateInstances{
NSLog(@"Inside CreateInstances");
CommunicationHub *cHub = [[CommunicationHub alloc] init];
viewController = [[ViewController alloc] init];
[viewController initWithcHub:cHub];
NSLog(@"ID of cHub in AppDelegate is %i", cHub);
}
- (void)applicationWillResignActive:(UIApplication *)application
{
NSLog(@"Application Will Resign Active");
[cHub disconnect];
}
@end
ViewController.h
#import <UIKit/UIKit.h>
#import "CommunicationHub.h"
@interface ViewController : UIViewController
{
CommunicationHub *cHub;
}
@property (strong, nonatomic) IBOutlet UITextField *IPAddress;
@property (strong, nonatomic) IBOutlet UITextField *PortNumber;
- (IBAction)goAwayKeyBoard:(id)sender;
- (IBAction)touchBackground:(id)sender;
-(void) initWithcHub:(CommunicationHub *)ptr;
- (IBAction)connectSocket:(id)sender;
- (IBAction)disconnectSocket:(id)sender;
@end
ViewController.m
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
@synthesize IPAddress;
@synthesize PortNumber;
-(void) initWithcHub:(CommunicationHub *)ptr
{
cHub = [[ptr retain]init];
NSLog(@"id of cHub in ViewController is %i", cHub);
}
- (IBAction)connectSocket:(id)sender
{
//Called by button on UI.
int portNumber = [PortNumber.text intValue];
[cHub Connect:(int *)portNumber ipAddress:(IPAddress.text)];
}
- (IBAction)disconnectSocket:(id)sender
{
//Called by button on UI.
[cHub disconnect];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[self setIPAddress:nil];
[self setPortNumber:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
} else {
return YES;
}
}
-(IBAction)goAwayKeyBoard:(id)sender{
[self resignFirstResponder];
}
- (IBAction)touchBackground:(id)sender {
[IPAddress resignFirstResponder];
[PortNumber resignFirstResponder];
}
@end
CommunicationHub.h
#import <UIKit/UIKit.h>
NSInputStream *inputStream;
NSOutputStream *outputStream;
@interface CommunicationHub : NSObject <NSStreamDelegate>
- (void)Connect:(int *)port ipAddress:(NSString *)ipAddress;
- (void) disconnect;
@end
CommunicationHub.m
#import "CommunicationHub.h"
@implementation CommunicationHub
- (void)Connect:(int *)port ipAddress:(NSString *)ipAddress
{
NSLog(@"inside connect method");
if ([inputStream streamStatus] == 0 ||[inputStream streamStatus] == 5 ||[inputStream streamStatus] == 6 ||[inputStream streamStatus] == 7)
{
NSString *myString = ipAddress;
CFStringRef *myCFString = (__bridge CFStringRef)myString;
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, myCFString, port, &readStream, &writeStream);
inputStream = (__bridge NSInputStream *)readStream;
outputStream = (__bridge NSOutputStream *)writeStream;
[inputStream setDelegate:self];
[outputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
}
}
- (void) disconnect
{
NSLog(@"inside disconnect method");
if (inputStream != nil) {
if ([inputStream streamStatus] == 2) {
NSLog(@"Disconnecting Streams");
[inputStream close];
[outputStream close];
}else {
NSLog(@"Stream is not Open");
int status = [inputStream streamStatus];
NSLog(@"Stream Status is %i", status);
}
}else {
NSLog(@"Input Stream equals Nil");
}
}
@end
【问题讨论】:
-
简而言之:将实例的指针传递给需要使用它的类。
-
好的,我从哪里开始...首先:从“连接”中删除该 int * 强制转换。如果您不将其用作“int”参数,而是用作实际指针,这不仅是不必要的,而且还具有潜在的危险。下一篇:局部变量和实例变量不要使用同名,因为局部自然会隐藏实例变量,可能会导致泄漏。下一步:[[ViewController alloc] initWithCHub] -> 一个方法调用。不是初始化,然后再次“初始化”。 (或修改您的方法名称)。然而,抛开所有的设计缺陷……目前的问题到底是什么?
-
我会纠正这些。我的主要问题是当应用程序启动时,我的 appDelegate 在本地调用 CreateInstances,它创建了 CommunicationHub 类和 ViewController 类的实例,然后它调用了 ViewController 上的方法 initWithcHub,我猜想这是为 CommunicationHub 创建一个名为 cHub 的对象。这可行,我可以在应用程序委托和视图控制器上打印 cHub 对象的 ID,但是当我按下 UI 上的按钮以调用 cHub 上的连接方法时,cHub 对象为零。似乎当我调用 initWithcHub 时,它是一个新实例。
-
不,它不应该“创建对象”,而是“传递对已创建对象的引用”。请在保留后删除“init”,并告诉我它是否更好。
-
我实际上确实尝试过删除 init,因为这似乎不正确,但似乎也不起作用。目前我的代码是 cHub = [ptr retain];我相信问题是当我在 initWithcHub:(CommunicationHub *)ptr 方法中调用这一行时,appDelegate 创建了 viewController 的新实例,因此 cHub 对象由该实例创建,但仅在该特定实例中可用,所以如果我按下按钮调用 viewController 中 cHub 对象为 nil 的方法。这可能吗?
标签: instance nsobject nsinputstream