не удается получить доступ к изменяемому массиву в одноэлементном

#objective-c

#objective-c

Вопрос:

singleton.h

 #import <Foundation/Foundation.h>
@interface CrestronControllerValues : NSObject {
NSString* ipAddress;
NSString* portNumber;
NSString* phoneAddress;
NSString* cameleonVersion;
NSString* systemName;
NSString* iPID;
NSString* systemFeedBackName;
NSString* dJoinConnectedFB;
NSString* dJoinLow;
NSString* dJoinHigh;
NSString* aJoinLow;
NSString* aJoinHigh;
NSString* sJoinLow;
NSString* sJoinHigh;
NSMutableArray *currentPhonebookEntriesTelepresence;
NSMutableArray *currentPhonebookEntriesVideoChat;
NSMutableArray *currentPhonebookEntriesAudioChat;

}
@property (nonatomic, retain)    NSString* ipAddress;

@property (nonatomic, retain)    NSString* portNumber;

@property (nonatomic, retain)    NSString* phoneAddress;

@property (nonatomic, retain)    NSString* cameleonVersion;

@property (nonatomic, retain)     NSMutableArray *currentPhonebookEntriesTelepresence;

@property (nonatomic, retain)     NSMutableArray *currentPhonebookEntriesVideoChat;

@property (nonatomic, retain)     NSMutableArray *currentPhonebookEntriesAudioChat;

@property (nonatomic, retain)    NSString* systemName;

@property (nonatomic, retain)    NSString* iPID;

@property (nonatomic, retain)    NSString* systemFeedBackName;

@property (nonatomic, retain)    NSString* dJoinConnectedFB;

@property (nonatomic, retain)    NSString* dJoinLow;

@property (nonatomic, retain)    NSString* dJoinHigh;

@property (nonatomic, retain)    NSString* aJoinLow;

@property (nonatomic, retain)    NSString* aJoinHigh;

@property (nonatomic, retain)    NSString* sJoinLow;

@property (nonatomic, retain)    NSString* sJoinHigh;

  (id)sharedManager;
    @end
  

у меня есть мой singleton.m:

         static CrestronControllerValues *sharedMyManager= nil;

    @implementation CrestronControllerValues
    @synthesize ipAddress, portNumber ,systemName, iPID, systemFeedBackName, dJoinConnectedFB, dJoinLow, dJoinHigh, aJoinLow, aJoinHigh, sJoinLow, sJoinHigh, cameleonVersion, currentPhonebookEntriesAudioChat, currentPhonebookEntriesTelepresence, currentPhonebookEntriesVideoChat, phoneAddress;


     (CrestronControllerValues*)sharedManager
{
        @synchronized(self) {
    if(!sharedMyManager) {
        sharedMyManager = [CrestronControllerValues alloc];
        sharedMyManager = [sharedMyManager init];

    }
}
}

 (id)alloc
{
    @synchronized(self)
    {
        NSAssert(sharedMyManager == nil, @"Attempted to allocate a second instance of a singleton.");
        sharedMyManager = [super alloc];
        return sharedMyManager;
    }

    return nil;
}

    -(id)init {
        self = [super init];
        if (self != nil) {
            // initialize stuff here
        self.ipAddress = @"10.8.40.64";
self.portNumber = 41794;
self.systemName = @"";
self.iPID = 3;
self.cameleonVersion = nil;
self.currentPhonebookEntriesAudioChat = [[NSMutableArray alloc]initWithObjects:nil];  
self.currentPhonebookEntriesTelepresence = [[NSMutableArray alloc]initWithObjects:nil];
self.currentPhonebookEntriesVideoChat = [[NSMutableArray alloc]initWithObjects:nil];
self.phoneAddress = nil;
self.systemFeedBackName = @"";
self.dJoinConnectedFB = 5000;
self.dJoinLow = 1;
self.dJoinHigh = 1000;
self.aJoinLow = 1;
self.aJoinHigh = 1000;
self.sJoinLow = 1;
self.sJoinHigh = 1000;

        }
        return self; 
    }
        return self; 
    }

    -(void)setPhoneAddress:(NSString *)phoneaddress
    {
        @synchronized(self) {
            if (phoneAddress != phoneaddress) 
            {
                [phoneAddress release];
                phoneAddress = [phoneaddress retain];
            }
        }
    }
    -(NSString*)getPhoneAddress
    {
        return phoneAddress;
    }
    -(void)setCurrentPhonebookEntriesAudioChat:(NSMutableArray *)entries
    {
        @synchronized(self) {
            if (currentPhonebookEntriesAudioChat != entries) 
            {
                [currentPhonebookEntriesAudioChat release];
                currentPhonebookEntriesAudioChat = [entries retain];
            }
        }
    }
    -(NSMutableArray*)getCurrentPhonebookEntriesAudioChat
    {
        return currentPhonebookEntriesAudioChat;
    }
    -(void)setCurrentPhonebookEntriesTelepresence:(NSMutableArray *)entries
    {
        @synchronized(self) {
            if (currentPhonebookEntriesTelepresence != entries) 
            {
                [currentPhonebookEntriesTelepresence release];
                currentPhonebookEntriesTelepresence = [entries retain];
            }
        }
    }
    -(NSMutableArray*)getCurrentPhonebookEntriesTelepresence
    {
        return currentPhonebookEntriesTelepresence;
    }
    -(void)setCurrentPhonebookEntriesVideoChat:(NSMutableArray *)entries
    {
        @synchronized(self) {
            if (currentPhonebookEntriesVideoChat != entries) 
            {
                [currentPhonebookEntriesVideoChat release];
                currentPhonebookEntriesVideoChat = [entries retain];
            }
        }
    }
    -(NSMutableArray*)getCurrentPhonebookEntriesVideoChatLocal
    {
        return currentPhonebookEntriesVideoChat;
    }
    -(void)setCameleonVersion:(NSString *)cameleonversion
    {
        cameleonVersion = cameleonversion;
    }
    -(NSString*)getCameleonVersion
    {
        return cameleonVersion;
    }
    -(void)setIPaddress:(NSString *)ipaddress
    {
        ipAddress = ipaddress;
    }
    -(NSString*)getIPaddress
    {
        return ipAddress;
    }
    -(void)setPortNumber:(NSString *)portnumber
    {
        portNumber = portnumber;
    }
    -(NSString*)getPortNumber
    {
        return portNumber;
    }
    -(void)setSystemName:(NSString *)systemname
    {
        systemName = systemname;
    }
    -(NSString*)getSystemName
    {
        return systemName;
    }

    -(void)setIPID:(NSString *)ipid 
    {
        iPID=ipid;
    }
    -(NSString*)getIpid
    {
        return iPID;
    }

    -(void)setSystemFeedBackName:(NSString *)systemfeedbackname
    {
        systemFeedBackName=systemfeedbackname;
    }
    -(NSString*)getSystemFeedBackName
    {
        return systemFeedBackName;
    }

    -(void)setDJoinConnectedFB:(NSString *)djoinconnectedfb
    {
        dJoinConnectedFB = djoinconnectedfb;
    }
    -(NSString*)getDJoinConnectedFB
    {
        return dJoinConnectedFB;
    }

    -(void)setDJoinLow:(NSString *)djoinlow
    {
        dJoinLow=djoinlow;
    }
    -(NSString*)getDJoinLow
    {
        return dJoinLow;
    }

    -(void)setDJoinHigh:(NSString *)djoinhigh
    {
        dJoinHigh = djoinhigh;
    }
    -(NSString*)getDJoinHigh
    {
        return dJoinHigh;
    }

    -(void)setAJoinLow:(NSString *)ajoinlow
    {
        aJoinLow = ajoinlow;
    }
    -(NSString*)getAJoinLow
    {
        return aJoinLow;
    }

    -(void)setAJoinHigh:(NSString *)ajoinhigh
    {
        aJoinHigh = ajoinhigh;
    }
    -(NSString*)getAJoinHigh
    {
        return aJoinHigh;
    }

    -(void)setSJoinLow:(NSString *)sjoinlow
    {
        sJoinLow = sjoinlow;
    }
    -(NSString*)getSJoinLow
    {
        return sJoinLow;
    }

    -(void)setSJoinHigh:(NSString *)sjoinhigh
    {
        sJoinHigh = sjoinhigh;
    }
    -(NSString*)getSJoinHigh
    {
        return sJoinHigh;
    }

    - (void)dealloc
    {
        [self.ipAddress release];
        [self.iPID release];
        [self.portNumber release];
        [self.currentPhonebookEntriesVideoChat release];
        [self.currentPhonebookEntriesTelepresence release];
        [self.currentPhonebookEntriesAudioChat release];
        [self.aJoinHigh release];
        [self.aJoinLow release];
        [self.cameleonVersion release];
        [self.sJoinHigh release];
        [self.sJoinLow release];
        [self.dJoinHigh release];
        [self.dJoinLow release];
        [self.dJoinConnectedFB release];
        [super dealloc];
    }

    @end
  

и затем я использую его в 3 классах, всего
в одном я устанавливаю значения:
если я считываю значения из CCV (sharedobject), я получаю правильные значения. но это относится к тому же классу, из которого они заданы

 CCV = [CrestronControllerValues sharedManager];
CCV.currentPhonebookEntriesAudioChat = currentPhonebookEntriesAudioChat;
  

и еще я прочитал значения:
(они отображаются / читаются как nil)

 switch (viewOptions) {
    case 1:
        [self setTableArray:CCV.currentPhonebookEntriesVideoChat];
        break;
    case 2:
        [self setTableArray:CCV.currentPhonebookEntriesVideoChat];
        break;
    case 3:
        [self setTableArray:CCV.currentPhonebookEntriesTelepresence];
        break;
    case 4:
        [self setTableArray:CCV.currentPhonebookEntriesAudioChat];
        break;
    default:
        [self setTableArray:CCV.currentPhonebookEntriesVideoChat];
        break;
}
  

но помимо класса, в котором я фактически устанавливаю значения, я не получаю заполненный массив, когда обращаюсь к нему из другого класса
, который я выполнил NSLOG (@»% @», CCV), и из того, что я вижу, все три класса имеют один и тот же указатель, поэтому общий экземпляр, похоже, работает

Комментарии:

1. я пробовал это с shareinstance и без него. перед моими переменными, которые я инициализирую, а также переопределяю установщики

2. Если вы не получите заполненный массив, что вы получите? Это пустой массив? Можете ли вы также показать свой файл .h, в котором вы объявляете свойства?

3. правильно, я получаю пустой или нулевой массив (файл add .h)

4. Справедливо ли спрашивать, почему вы используете такой неясный и сложный шаблон для реализации одноэлементного?

5. я пробовал несколько шаблонов, дайте мне более простой, чтобы попробовать, и я попробую. иногда я теряюсь в разных способах, которые я пробовал. но все же я не понимаю, почему работают nsstrings, но не массивы

Ответ №1:

Вот более простой одноэлементный шаблон, чем меньше кода, тем больше:

 @implementation MySingleton
static MySingleton* _sharedMySingleton = nil;

 (MySingleton*)sharedMySingleton
{
    @synchronized([MySingleton class])
    {
        if (!_sharedMySingleton)
            _sharedSingleton = [[MySingleton alloc] init];
    }

    return _sharedMySingleton;
}
  

Ответ №2:

sharedMyManager не был установлен во время инициализации ivars.

В инициализации лучше всего устанавливать ivar напрямую, то есть не использовать установщики, такие как created by @synthesize , класс не полностью установлен, поэтому вызывать методы для него не очень хорошая идея.

Singleton — это просто класс, как и любой другой класс, за одним исключением, есть только один. Кроме того, все дополнительные методы, гарантирующие одноэлементность, на самом деле являются просто шумом, которого лучше не представлять, но это дело вкуса.

Комментарии:

1. не уверен, в каком направлении вы хотите, чтобы я выбрал. у меня была куча геттеров и сеттеров, но я удалил их после дальнейших исследований (однако в оригинальном руководстве и других, которые я нашел, показано, как они создают свойство). насколько я понимаю, свойство заключается в том, что оно автоматически создает геттеры и сеттеры. у меня все мои ивары инициализируются в методе init? если я не синтезирую, я получаю ошибки при настройке этих переменных.

2. Во что бы то ни стало создавайте @properties и используйте установщики / получатели всегда — за исключением init случаев, когда и dealloc где может быть лучше напрямую назначить / освободить. Используйте @synthesize для создания сеттеров / геттеров, если в них нет ничего особенного — обычный случай.

3. я понимаю, что вы не должны использовать установщик из инициализации. но я думал, что использование установщика будет [foo setbar:foobar] или даже foo.bar = foobar но как я использую установщик, когда я просто говорю bar= foobar. из другого ответа я понимаю, что это должно быть self, и я могу понять это, поскольку они устанавливают IVAR, но что я использовал до этого, используя сеттеры?

4. sharedMyManager.ipAddress = @"10.8.40.64"; использует установщик, если IPAddress является свойством. Это эквивалентно [sharedMyManager setIpAddress:@"10.8.40.64] .

5. я действительно думаю, что важная часть, которую мне не хватает, — это то, как должен выглядеть мой сеттер? и является self . исправьте для ivars. в какой-то момент у меня так и было, но затем я начал думать, что мне следует загрузить объект sharedMyManager со значениями.

Ответ №3:

Рассмотрим:

 sharedMyManager = [[super allocWithZone:NULL] init];
  

Перепишите его как:

 id x = [super allocWithZone:NULL];
id y = [x init];
sharedMyManager = y;
  

При init выполнении присваивание sharedMyManager еще не было оценено. Таким образом, sharedMyManager is nil и все ваши назначения не являются операциями в вашем init методе.

В вашем init методе вы всегда должны ссылаться на переменные вашего экземпляра через self ; либо путем прямого присвоения им (что на самом деле является ссылкой на self), либо с использованием методов setter напрямую (т. Е. self.foo = 442; ).

(Это то, что сказал @CocoaFu, но уточнил)


При более внимательном рассмотрении кода с ним связано множество проблем.

  • NSString свойства должны быть copy , а не retain .

  • вы пропускаете все currentPhonebookEntries* изменяемые массивы.

  • Методы получения не должны иметь префикс get*

  • при использовании нет необходимости реализовывать какой-либо из этих методов получения / установки @synthesize (и вы фактически создаете два метода получения для каждого; один с и один без get префикса).

  • dealloc метод должен либо напрямую освобождать переменные экземпляра, либо устанавливать свойства на nil ; [self.ivar release] не рекомендуется.

Код, который я показал выше, является просто иллюстративным. Если вы init все еще назначаете through sharedMyManager , вы не устранили проблему.

Комментарии:

1. я внес изменения в вашу публикацию, но все еще сталкиваюсь с той же проблемой. собираюсь опубликовать код и добавить еще немного. но у меня есть побочный вопрос. вы почти всегда видите foo * bar = [[foo alloc]init] . для инициализации я понимаю ваш пост и вижу, что вы говорите, но тогда почему этот метод инициализации настолько распространен (чего мне не хватает)

2. я не понимаю, другие значения работают, но не мои массивы. есть еще идеи?

Ответ №4:

итак, в конце концов, все, что я могу сделать, это извиниться. ни у кого из вас не было кода, который вам понадобился бы, чтобы увидеть, что происходит.
вот сохраняемый массив (приведенный выше был сокращен (плохая идея))

             if ([phonebookEntriesAudioChat count] >=8) {                

                [CCV setCurrentPhonebookEntriesAudioChat:phonebookEntriesAudioChat];
                [phonebookEntriesAudioChat removeAllObjects];

            }
  

по сути, я пытался добавить элемент в массив из возврата сокета. получение одного адреса до 8 для каждого возврата / сообщения. итак, я заполнил временный массив (phonebookEntriesAudioChat) и добавил к нему по одному для каждого сообщения, и как только он дошел до 8, сохранил его в моем одноэлементном (CCV). но каким-то образом (и я все еще пытаюсь это выяснить) он достигнет 8, будет сохранен, временный массив очищен, а затем повторно сохранен массив (пустой) в одноэлементный.

спасибо за всю помощь и указания, я знаю, что не получаю баллов за свой собственный ответ, если кто-то из вас хочет получить несколько простых баллов, просто повторите ответ с таким же описанием, как это, и я дам вам чек. в противном случае я просто собираюсь проголосовать за ваши комментарии и пометить это как ответ через день или два.