Используя переменные экземпляра с современным Временем выполнения

Используйте массив значений, с которыми вы хотите сравнить, и проверьте, чтобы возвращаемый индекс был больше -1. Это указывает на то, что оцененное значение было найдено в коллекции.

_.remove( fruits, function ( fruit ) {
  return _.indexOf( [ "Apple", "Banana", "Orange" ], fruit ) >= 0;
});

В качестве альтернативы вы можете использовать метод lo-dash _.contains для получения логического ответа.

Проблема с вашим подходом заключалась в том, что вы не сравнивали fruit с каждой из этих строк; вместо этого было выполнено единственное сравнение fruit с "Apple", после чего вы заставляли все строки самостоятельно.

Непустые строки приводят к true (!!"Banana"), и как таковые истинны . Следовательно, следующее условие всегда будет коротким замыканием в «Банане» (если fruit строго не равно "Apple"), возвращая true:

return fruit === "Apple" || 'Banana' || "Orange";

9
задан Scott Little 18 June 2009 в 00:44
поделиться

5 ответов

В текущем компиляторе (OS X 10.5 / GCC 4.0.1) вы не можете напрямую обращаться к ivars, синтезированным во время выполнения. Грег Паркер, один из инженеров среды исполнения OS X, поместил это следующим образом в список cocoa-dev (12 марта 2009 г.):

Вы не можете использовать текущий компилятор. А будущий компилятор должен это исправить. Использовать явный @private ivars в тем временем. @Private ivar не должен считаться частью контракта - вот что означает @private, принудительно предупреждениями компилятора и компоновщиком ошибок.

И почему нет способа явно объявить переменные экземпляра в файле .m для новой среды выполнения?

Три причины: (1) есть некоторые нетривиальные детали дизайна для работы out, (2) часы-компилятор-инженер ограничены, и (3) @private ivars являются в целом достаточно хорошо.

Итак, пока вы должны использовать точечную нотацию для доступа к свойствам, даже в init и dealloc . Это идет вразрез с передовой практикой использования ivars напрямую в таких случаях, но нет никакого способа обойти это. Я считаю, что простота использования ivars, синтезированных во время выполнения (и преимущества в производительности) перевешивают это в большинстве случаев. Если вам действительно нужен прямой доступ к ivar, вы можете использовать @private ivar, как предлагает Грег Паркер (ничто не мешает вам смешивать явно объявленные и синтезированные во время выполнения ivar).

Обновление В OS X 10.6, 64-битная среда выполнения позволяет прямой доступ к синтезированным ivars через self-> ivar .

10
ответ дан 3 November 2019 в 01:03
поделиться

Since instance variables themselves can only be synthesized in the modern runtime (and must be declared in the @interface under 32-bit or pre-Leopard), it's safest / most portable to also declare the ivar

  • Should we use property accessors in init* and dealloc with Modern Runtime?

My rule of thumb is "possibly" for -init*, and "usually not" for -dealloc.

When initializing an object, you want to make sure to properly copy/retain values for ivars. Unless the property's setter has some side effect that makes it inappropriate for initialization, definitely reuse the abstraction the property provides.

When deallocating an object, you want to release any ivar objects, but not store new ones. An easy way to do this is to set the property to nil (myObject.myIvar = nil), which basically calls [myObject setMyIvar:nil]. Since messages to nil are ignored, there is no danger in this. However, it's overkill when [myIvar release]; is usually all you need. In general, don't use the property (or directly, the setter) in situations where deallocation should behave differently than setting the variable.

I can understand eJames' argument against using property accessors in init/dealloc at all, but the flipside is that if you change the property behavior (for example, change from retain to copy, or just assign without retaining) and don't use it in init, or vice versa, the behavior can get out of sync too. If initializing and modifying an ivar should act the same, use the property accessor for both.

  • If so, why is this different? Is it just because the compiler can't see the ivar?

The modern runtime deals with class size and layout more intelligently, which is why you can change the layout of ivars without having to recompile subclasses. It is also able to infer the name and type of the ivar you want from the name and type of the corresponding property. The Objective-C 2.0 Runtime Programming Guide has more info, but again, I don't know how deeply the details explained there.

  • If I need to override an accessor, can I still access that iVar that will be defined at runtime or do I have to define an actual iVar that the runtime will then use?

I haven't tested this, but I believe you're allowed to access the named ivar in code, since it actually does have to be created. I'm not sure whether the compiler will complain, but I would guess that since it will let you synthesize the ivar without complaining, it is also smart enough to know about the synthesized ivar and let you refer to it by name.

  • Again, if I can access the synthesized iVar, why can't I continue to do this for the init* and dealloc methods?

You should be able to access the property and/or ivar anytime after the instance has been allocated.

1
ответ дан 3 November 2019 в 01:03
поделиться

Есть еще один вопрос SO с аналогичной информацией, но это не совсем дубликат.

Итог из документации Objective-C 2.0 и цитата из Ответ Марка Бесси выглядит следующим образом:

Там - это различия в поведении, зависящие от среды выполнения (см. также «Различия во время выполнения»):

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

Для современных сред выполнения переменные экземпляра синтезируются по мере необходимости. Если переменная экземпляра с таким же именем уже существует, она используется.

0
ответ дан 3 November 2019 в 01:03
поделиться

I am running into the same problem. The way I am working around not being able to access the synthesized instance variables is the following:

public header

@interface MyObject:NSObject {
}
@property (retain) id instanceVar;
@property (retain) id customizedVar;
@end

private header / implementation

@interface MyObject()
@property (retain) id storedCustomizedVar;
@end

@implementation MyObject
@synthesize instanceVar, storedCustomizedVar;
@dynamic customizedVar;

- customizedVar {
  if(!self.storedCustomizedVar) {
    id newCustomizedVar;
    //... do something
    self.storedCustomizedVar= newCustomizedVar;
  }
  return self.storedCustomizedVar;
}

- (void) setCustomizedVar:aVar {
  self.storedCustomizedVar=aVar;
}

@end

It's not that elegant, but at least it keeps my public header file clean.

If you use KVO you need to define customizedVar as dependent key of storedCustomizedVar.

0
ответ дан 3 November 2019 в 01:03
поделиться

Я относительно новичок в Obj-C (но не в программировании), и меня тоже смутила эта тема.

Меня беспокоит то, что относительно легко случайно использовать iVar вместо свойства. Например, напишите:

myProp = someObject;

вместо

self.myProp = someObject;

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

В идеале я бы предпочел, чтобы среда выполнения применяла некоторый шаблон к имени свойства при генерации любой iVar. Например. всегда ставьте перед ними префикс "_".

На практике в настоящий момент я делаю это вручную - явно объявляю свои ivars и намеренно даю им имена, отличные от свойств. Я использую префикс «m» в старом стиле, поэтому, если мое свойство - «myProp», моим iVar будет «mMyProp». Затем я использую @synthesize myProp = mMyProp, чтобы связать их.

Я признаю, что это немного неуклюже и требует дополнительной печати, но мне кажется, что это того стоит, чтобы иметь возможность более четко устранять неоднозначность в коде. Конечно, я все еще могу ошибиться и набрать mMyProp = someObject, но я надеюсь, что префикс «m» предупредит меня о моей ошибке.

Было бы намного приятнее, если бы я мог просто объявить свойство и позволить компилятору / среде выполнения сделать все остальное, но когда у меня много кода, мой инстинкт подсказывает мне, что я буду делать ошибки таким образом, если мне все еще придется следуйте ручным правилам для инициализации / освобождения.

Конечно, есть еще много вещей, которые я могу сделать неправильно ...

0
ответ дан 3 November 2019 в 01:03
поделиться