0

クラスAにオブジェクトのインスタンスを作成し、クラスBからオブジェクトの同じインスタンスにアクセスすることは可能ですか?NSInputStreamとNSOutputStreamを使用してTCPソケットを作成するアプリを開発しようとしていますが、それにアクセスするには複数のクラスが必要です。

ありがとう、トラビスエリオット

編集

これが私が使っているコードです。そのソケット接続を扱うプログラム。基本的に、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
4

1 に答える 1

0

長くするには:クラスA、B、Cがあると仮定します。

AとBの両方からCにアクセスできる必要があります。ここで、AとBの両方をインスタンス化するコントローラーDがあるとします。Dが最初にCをインスタンス化し、それを変数に格納します。

C *C_Class = [[[C alloc] init] autorelease];

次に、AとBをCでインスタンス化します(ここでは「プロパティを保持する」と想定しています)

self.A_Class = [[[A alloc] initWithC:C_Class] autorelease];
self.B_Class = [[[B alloc] initWithC:C_Class] autorelease];

どちらのクラスでも、インスタンスメソッドが必要です。

- (id)initWithC:(C *)C_Class;

および.mファイル内:

- (id)initWithC:(C *)C_Class {
    C_C = [C_Class retain]; //Assuming a regular instance variable
}

- (void) dealloc {
    [C_C release];  //All that is retained, must be released.
}

この時点から、「C_C」という名前で、クラスAおよびBのクラスCのその1つのインスタンスにアクセスできます。

さて、これは私の頭の後ろから書かれているだけで、エラーが発生しやすいことを覚えておいてください。しかし、それは大丈夫なはずです。

お役に立てば幸いです:)

編集:OPはこれらのコードフラグメントに問題があるように思われるので、より完全なコードを追加します。

コントロールクラス「D」から始めましょう。

Dh:

#import "A.h"
#import "B.h"

@interface D : NSObject

-(void)CreateInstances;

@property (strong, retain) A *A_Class;
@property (strong, retain) B *B_Class;

@end

Dm:

#import "D.h"
#import "C.h"

@implementation D

-(void)CreateInstances {
    C *C_Class = [[C alloc] init] autorelease];
    self.A_Class = [[[A alloc] initWithC:C_Class] autorelease];
    self.B_Class = [[[B alloc] initWithC:C_Class] autorelease];
}

@end

ああ(Bhはこの動作を反映しているので、両方にスーパークラスを使用することを検討してください)

#import "C.h"

@interface A : NSObject {
    C *C_Class;           //Class Reference to the C-Object
}

-(id) initWithC:(C *)ptr; //Initialization method, which takes a 'C'-Object.

@end;

午前

#import "A.h"

@implementation A

- (id) initWithC:(C *)ptr {
    C_Class = [ptr retain]; //So the object doesn't get released prematurely.
}

- (void) dealloc {
    [C_Class release];      //To avoid memory leaks.
}

@end

さて、私はこれを頭のてっぺんから書き、コンパイラを介して実行しなかったことを覚えておいてください。しかし、それは機能し、タイプミスなどを保存する必要があります。

別の編集:OPが独自のコードを追加した後、「修正された」コードの関連ビットをここに投稿します。

AppDelegate.m

-(void)CreateInstances{
    NSLog(@"Inside CreateInstances");
    cHub = [[CommunicationHub alloc] init]; //We're using the instance variable. Not the local one.
    viewController = [[ViewController alloc] initWithcHub:cHub];
    //[viewController initWithcHub:cHub];  //You may want to rethink your function names.
    NSLog(@"ID of cHub in AppDelegate is %i", cHub);
}

ViewController.m

//If a method names STARTS with 'init', it SHOULD initialize the object.
-(id) initWithcHub:(CommunicationHub *)ptr
{
    self = [super init];     //Calls the 'init' from the parent class.
    if(self) {
        cHub = [ptr retain]; //Just retain. After all, the object IS initialized already.
        NSLog(@"id of cHub in ViewController is %i", cHub);
    }
    return self;
}

- (void) dealloc {
    [cHub release]; //Basic rule of memory management: ALL that is retained, must be released. In dealloc, at latest.
}

- (IBAction)connectSocket:(id)sender 
{
    //Called by button on UI.
    //Do not pass a pointer to anything, unless you mean to use a pointer.
    [cHub Connect:[PortNumber.text intValue] ipAddress:(IPAddress.text)];
}

残りはある程度正しいか、少なくともこの質問の対象ではないはずです。

于 2012-07-26T20:28:20.070 に答える