NSInteger vs. int ne zaman kullanılır?


344

NSIntegerİOS için geliştirirken ne zaman int kullanmalıyım ? Apple örnek kodda bir işleve bağımsız değişken olarak bir değer iletirken veya bir işlevden bir değer döndürürken kullandıkları NSInteger(veya NSUInteger) bakın.

- (NSInteger)someFunc;...
- (void)someFuncWithInt:(NSInteger)value;...

Ancak bir işlev içinde sadece intbir değeri izlemek için kullanıyorlar

for (int i; i < something; i++)
...

int something;
something += somethingElseThatsAnInt;
...

NSInteger64-bit veya 32-bit ortamda tamsayıya başvurmanın güvenli bir yolu olduğunu okudum (söyledim), neden inthiç kullanmıyorsunuz ?

Yanıtlar:


322

NSIntegerKodunuzun ne tür bir işlemci mimarisi üzerinde çalışabileceğini bilmediğinizde genellikle kullanmak istersiniz , bu nedenle bir nedenden ötürü 32 bit sistemlerde int64 bit iken sadece bir olan mümkün olan en büyük tamsayı türünü isteyebilirsiniz. sistemi bir long.

Özellikle onlara ihtiyaç duymadıkça / NSIntegeryerine kullanmaya devam ediyorum .intlong

NSInteger/ şu türlerden birine NSUInteger* dinamik typedef* s olarak tanımlanır ve şu şekilde tanımlanır:

#if __LP64__ || TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif

Bu türlerin her biri için kullanmanız gereken doğru biçim belirteciyle ilgili olarak, Dizge Programlama Kılavuzu'nun Platform Bağımlılıkları hakkındaki bölümüne bakın.


4
Ayrıca, özellikle int veya long int gerektirmedikçe NSInteger kullanmanın en iyi yol olduğunu söyleyebilirim.
v01d

4
@Shizam Bir kullanmanın intbile a için daha uygun olması mümkündür long. Belki belirli bir aralığı aşmayacağını biliyorsunuz ve bu nedenle sadece kullanmanın bellek açısından daha verimli olacağını düşünüyorum int.
Jacob Relkin

58
Bu cevaba katılmıyorum. Kullanacağım tek şey NSInteger, onu belirten bir API'ye ve API'dan değerler iletmektir. Bunun dışında, bir int veya long'e göre avantajı yoktur. En azından bir int veya long ile, printf veya benzeri bir ifadede hangi format belirteçlerinin kullanılacağını bilirsiniz.
JeremyP

3
Uzun süre depolamanız gerekiyorsa ve 64b sistemde çalışırken NSInteger kullanıyorsanız, ancak diğer kullanıcı 32b sistem kullanıyorsa ne olur? Hatayı fark etmezsiniz ancak kullanıcı görür.
arielcamus

14
Bu geriye dönük. Aksi takdirde belirli bir nedeniniz yoksa daima int kullanın. Basit tamsayılar için platforma özgü tanımları kullanmak, kodunuzun okunmasını zorlaştırmaktan başka bir şey yapmaz.
Glenn Maynard

44

Neden inthiç kullanmıyorsunuz ?

Apple, intbir döngü kontrol değişkeni için (yalnızca döngü yinelemelerini kontrol etmek için kullanılır) intveri türünün hem veri tipi boyutunda hem de döngünüz için tutabileceği değerlerde iyi olduğundan kullanır. Burada platforma bağımlı veri tipine gerek yok. Bir döngü kontrol değişkeni için 16 bit bile intçoğu zaman yapar.

Apple NSIntegerbir işlev dönüş değeri için veya işlev bağımsız değişkeni için kullanır çünkü bu durumda veri türü [size] önemlidir , çünkü bir işlevle yaptığınız şey verileri başka programlarla veya diğer kod parçalarıyla iletmek / iletmektir; NSInteger vs int'i ne zaman kullanmalıyım? sorunun kendisinde ...

bunlar [elma] NSInteger (veya NSUInteger) kullanan bir değer geçerken bir işlev için bağımsız değişken olarak ya da bir değer iade bir fonksiyondan.


32

OS X "LP64" dür. Bunun anlamı şudur ki:

int her zaman 32 bittir.

long long her zaman 64 bittir.

NSIntegerve longher zaman işaretçi boyutundadır. Bu, 32 bit sistemlerde 32 bit ve 64 bit sistemlerde 64 bit oldukları anlamına gelir.

Birçok eski API'ler yanlış kullanıldığında çünkü NSInteger var olmasının nedeni budur intyerine longAPI'ler gelen değişikliğine anlamına geliyordu tutma işaretçi boyutlu değişkenler için intiçin longonların 64 bit sürümlerinde. Başka bir deyişle, bir API 32-bit veya 64-bit mimariler için derleme yapmanıza bağlı olarak farklı işlev imzalarına sahip olacaktır. NSIntegerbu sorunu bu eski API'larla maskelemek istiyor.

Yeni kodunuzda int32 bit değişkene long longihtiyacınız varsa , 64 bit tamsayıya ihtiyacınız varsa longveya NSIntegerişaretçi boyutunda bir değişkene ihtiyacınız varsa kullanın.


25
Tarih spot, ama tavsiye korkunç. 32-bit değişkene ihtiyacınız varsa kullanın int32_t. 64 bitlik bir tamsayı kullanmanız gerekiyorsa int64_t. İşaretçi büyüklüğünde bir değişkene ihtiyacınız varsa kullanın intptr_t.
Stephen Canon

5
Stephen, tavsiyen asla int, long veya NSInteger'ı kullanmamak mı?
Darren

7
Hayır, tavsiyem, bilinen sabit boyutlu bir tamsayı türüne ihtiyacınız varsa bunları asla kullanmamanızdır. Bu <stdint.h>amaçla türler vardır.
Stephen Canon

3
Stephen, cevabım, "32 bit tamsayının platformlar arası tip adı nedir" değil, "NSInteger vs int kullanıldığında" sorusuna yanıttı. Birisi NSInteger ve int arasında karar vermeye çalışıyorsa, destekledikleri platformlarda ne kadar büyük olduklarını da biliyor olabilir.
Darren

1
Bunun 64 bit LP64olduğunu garanti etmediğini de unutmayın long long. Bir LP64platform long long128 bit tam sayı olmasını seçebilir .
Stephen Canon

26

NSInteger uygulamasına girerseniz:

#if __LP64__
typedef long NSInteger;
#else
typedef int NSInteger;
#endif

Basitçe, NSInteger typedef sizin için bir adım yapar: mimari 32 bit intise, 64 bit ise kullanır long. NSInteger kullanarak, programın çalıştığı mimari hakkında endişelenmenize gerek yoktur.


14
Endişelenmeniz gerekiyor, çünkü NSInteger için doğru format tanımlayıcısı mimariye bağlı.
JeremyP

Apple kılavuzuna göre en basit yol, en büyük sayısal türe değer vermektir long long. Böylece tüm sayısal türler aynı tür belirtecini kullanır.
Eonil

6
Biçimlendirmenin en basit yolu sadece onları NSLog("%@", @(1123));
bokslamak

1
Ayrıca şunları da yapabilirsiniz:NSLog("%li", (long)theNSInteger);
Daniel

döküm beni üzüyor
tomalbrc

9

NSNotger'ları NSNotFound veya NSIntegerMax gibi sabit değerlerle karşılaştırmanız gerekirse kullanmalısınız, çünkü bu değerler 32 bit ve 64 bit sistemlerde farklılık gösterecektir, bu nedenle dizin değerleri, sayımlar ve benzeri: NSInteger veya NSUInteger kullanın.

NSInteger'ı çoğu durumda iki kat daha fazla bellek gerektirmesi dışında kullanmak zarar vermez. Bellek etkisi çok küçüktür, ancak herhangi bir zamanda çok fazla sayıda sayınız varsa, ints kullanmak bir fark yaratabilir.

NSInteger veya NSUInteger kullanırsanız, biçimlendirme dizelerini kullanırken bunları uzun tamsayılara veya işaretsiz uzun tamsayılara dönüştürmek isteyeceksiniz, çünkü yeni bir NSInteger'ı bilinen bir uzunluğa sahip gibi denerseniz ve oturumu kapatırsanız bir uyarı döndürür. Aynı şekilde bunları ints olarak yazılan değişkenlere veya bağımsız değişkenlere gönderirken de dikkatli olmalısınız, çünkü süreçte bir miktar hassasiyet kaybedebilirsiniz.

Genel olarak, bir kerede yüz binlerce kişinin bellekte olmasını beklemiyorsanız, NSInteger'i kullanmak, ikisi arasındaki fark hakkında sürekli endişelenmekten daha kolaydır.


9

Şu anda (Eylül 2014) NSInteger/CGFloat, arm64 için de uygulamanızı oluşturuyorsanız iOS API'leriyle vb. Bunun nedeni float, longve inttürlerini kullandığınızda beklenmedik sonuçlar almanızdır.

ÖRNEK: FLOAT / ÇİFT VE CGFLOAT

Örnek olarak UITableView delegate yöntemini kullanıyoruz tableView:heightForRowAtIndexPath:.

Sadece 32 bitlik bir uygulamada şöyle yazılırsa iyi çalışır:

-(float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 44;
}

float32 bitlik bir değerdir ve döndürdüğünüz 44 değeri 32 bitlik bir değerdir. Ancak, aynı kod parçasını 64 bit arm64 mimarisinde derlersek / çalıştırırsak, 44, 64 bit değer olacaktır. 32 bitlik bir değer bekleniyorsa 64 bitlik bir değer döndürüldüğünde beklenmeyen bir satır yüksekliği elde edilir.

Bu sorunu CGFloattürünü kullanarak çözebilirsiniz.

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 44;
}

Bu tür, 32 floatbit ortamda 32 bit ve 64 bit ortamda 64 bit temsil eder double. Bu nedenle, bu tür kullanılırken yöntem, derleme / çalışma zamanı ortamından bağımsız olarak her zaman beklenen türü alır.

Tamsayı bekleyen yöntemler için de aynı şey geçerlidir. Bu yöntemler, int32 bit bir ortamda 32 bit ve 64 bit bir ortamda 64 bit bir değer bekler long. Bu durumu , derleme / çalışma zamanı ortamına dayalı NSIntegerolarak intveya olarak hizmet eden türü kullanarak çözebilirsiniz long.


Ya bu belirli değişkenin değeri büyük sayı değerleri içeremez biliyorum ve bu nedenle int kullanmak istiyorum. Hem 64 bit ortamda iyi çalışır mı? Böyle bir döngü için görmedim gibi ben de, gerektiğini düşünüyorum: (int i = 0; i <10; i ++) içinde çalıştığı ortam ne olursa olsun herhangi bir yanlış davranış yapmak için.
Chanchal Raj

@Chanchal Raj Başka türlere döküm veya dönüşüm olmadığı veya üçüncü taraf sınıflarının ve bu değişkeni içeren yöntemlerin kullanım / geçersiz kılma olmadığı sürece, NSInteger yerine int kullanmak iyi olacaktır.
Leon Lucardie

9

İOS'ta şu anda intveya kullanmanız önemli değil NSInteger. İOS 64 bite geçip geçmediği / ne zaman olacağı daha önemli olacaktır.

Basitçe söylemek gerekirse, NSIntegers'ler int32 bit kodda (ve bu nedenle 32 bit uzunluğunda) ve long64 bit kodda longs (64 bit kodda s 64 bit genişliğinde, ancak 32 bit kodda 32 bit). Bunun NSIntegeryerine kullanmanın en olası nedeni, longmevcut 32 bit kodu ( ints kullanan ) kırmamaktır .

CGFloataynı sorunu yaşıyor: 32 bit (en azından OS X'te) float; 64-bit üzerinde double.

Güncelleme: iPhone 5s, iPad Air, Retina özellikli iPad Mini ve iOS 7 ile iOS'ta 64 bit kod oluşturabilirsiniz.

Güncelleme 2: Ayrıca, NSIntegers kullanarak Swift kodunun birlikte çalışabilirliğine yardımcı olur.


0

int = 4 bayt (mimarın sabit bağımsız boyutu) NSInteger = mimarın boyutuna bağlıdır (örneğin 4 bayt mimar için = 4 bayt NSInteger boyutu)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.