UITableViewCell'de iOS7'de otomatik düzen kısıtlamaları sorunu


104

Özel UITableView hücrelerimi düzenlemek için programlı olarak otomatik düzen kısıtlamaları kullanıyorum ve hücre boyutlarını doğru şekilde tanımlıyorum tableView:heightForRowAtIndexPath:

Bu iOS6 sadece para cezası çalışıyor ve öyle bakmak yanı -iOS7 içinde cezası

ANCAK uygulamayı iOS7'de çalıştırdığımda, konsolda gördüğüm türden bir mesaj:

Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2013-10-02 09:56:44.847 Vente-Exclusive[76306:a0b] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
        "<NSLayoutConstraint:0xac4c5f0 V:|-(15)-[UIImageView:0xac47f50]   (Names: '|':UITableViewCellContentView:0xd93e850 )>",
        "<NSLayoutConstraint:0xac43620 V:[UIImageView:0xac47f50(62)]>",
        "<NSLayoutConstraint:0xac43650 V:[UIImageView:0xac47f50]-(>=0)-[UIView:0xac4d0f0]>",
        "<NSLayoutConstraint:0xac43680 V:[UIView:0xac4d0f0(1)]>",
        "<NSLayoutConstraint:0xac436b0 V:[UIView:0xac4d0f0]-(0)-|   (Names: '|':UITableViewCellContentView:0xd93e850 )>",
        "<NSAutoresizingMaskLayoutConstraint:0xac6b120 h=--& v=--& V:[UITableViewCellContentView:0xd93e850(44)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0xac43650 V:[UIImageView:0xac47f50]-(>=0)-[UIView:0xac4d0f0]>

Ve gerçekten de bu listede istemediğim bir kısıtlama var:

"<NSAutoresizingMaskLayoutConstraint:0xac6b120 h=--& v=--& V:[UITableViewCellContentView:0xd93e850(44)]>"

ve translatesAutoresizingMaskIntoConstraintsözelliğini contentViewNO => olarak ayarlayamıyorum , tüm hücreyi bozar.

44 varsayılan hücre yüksekliğidir, ancak özel yüksekliklerimi tablo görünümü temsilcisinde tanımladım, öyleyse hücre contentView bu kısıtlamaya neden sahip? Buna ne sebep olabilir?

İOS6'da bu olmuyor ve her şey hem iOS6 hem de iOS7'de iyi görünüyor.

Kodum oldukça büyük, bu yüzden buraya göndermeyeceğim, ancak ihtiyacınız olursa bir pastebin istemekten çekinmeyin.

Nasıl yaptığımı belirtmek için, hücre ilkleştirmede:

  • Tüm etiketlerimi, düğmelerimi vb. Oluşturuyorum
  • translatesAutoresizingMaskIntoConstraintsMülklerini HAYIR olarak ayarladım
  • Bunları contentViewhücrenin alt görünümleri olarak ekliyorum
  • Kısıtlamaları eklerim contentView

Bunun neden yalnızca iOS7'de olduğunu anlamakla da derinden ilgileniyorum.


Özel hücre yüksekliğiniz neye ayarlandı?
Mike Pollard

özel hücre yüksekliğim 90 olarak ayarlandı
Alexis

Bir meslektaş dün de aynı sorunu yaşadı, ancak varsayılan genişlik 320 idi (bir iPad uygulaması için).
jrturton

Burada aynı sorunu gösteren örnek bir proje var: github.com/Alex311/TableCellWithAutoLayout İşte bu konudaki gözlemlerimden bazıları: github.com/Alex311/TableCellWithAutoLayout/commit/…
smileyborg

Aynı hatayla karşılaştım ama bunun nedeni, özel hücremin yüksekliğini bulmak için kullandığım ekstra prototip hücreyi hiçbir zaman başlatmamış olmamdı.
Steve Moser

Yanıtlar:


132

Ben de bu problemi yaşadım .. Görünüşe göre contentView çerçevesi çağrılıncaya kadar güncellenmiyor layoutSubviews, ancak hücrenin çerçevesi {0, 0, 320, 44}kısıtlamaların değerlendirildiği zaman ContentView çerçevesini bırakarak daha önce güncelleniyor .

ContentView'e daha ayrıntılı olarak baktıktan sonra, otomatik yeniden boyutlandırmaMasks'in artık ayarlanmadığı görülmektedir.

Görünümlerinizi kısıtlamadan önce otomatik yeniden boyutlandırma maskesini ayarlamak bu sorunu çözebilir:

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
    if (self)
    {
        self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
        [self loadViews];
        [self constrainViews];
    }
    return self;
}

Bu işi yapar, teşekkürler dostum. Düzenleme stillerini kullanırken ne olabilir?
Alexis

11
@ L14M333 Burada bu yorumda gönderdiğim koda bakın - temel olarak, self.contentView.bounds = CGRectMake(0, 0, 99999, 99999);sorunu çözmesi gereken kısıtlamalarınızı eklemeden önce ayarlayabilmelisiniz .
smileyborg

2
autoresizingMask benim için çalışmıyor: ilk kısıtlama gitti ancak 3 yeni eklendi "<NSAutoresizingMaskLayoutConstraint: 0x8b79740 h = - & - v = - & - UITableViewCellContentView: 0x8b44010.height == UITableViewCellScrollView: 0x8b4a130" "<NSAutoresizingMaskLayoutConstraint: 0x8b7b9f0 h = - & - v = - & - UITableViewCellScrollView: 0x8b4a130.height == LibraryCell: 0x8ac19d0.height>", "<NSAutoresizingMaskLayoutConstraint: 0x8b7c590 0x8ac19d0 (0)]> "
catamphetamine

1
Benim için de çalışıyor, bir saattir bununla mücadele ediyorum! Teşekkürler! <3
mokagio

2
Diğer otomatik düzen sorunlarından kurtulduktan sonra (iOS 7 / iOS 8), kullanmanın kullanmak self.contentView.bounds = CGRectMake(0, 0, 99999, 99999);kadar iyi çalıştığını öğrendim self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;. Bunu, updateConstraintsiçerik görünümüme kısıtlamaları eklemeden önce koydum .
test

35

Görünüşe göre iOS 8 SDK kullanan iOS 7'de UITableViewCell ve UICollectionViewCell'de bir sorun var.

Hücre şu şekilde yeniden kullanıldığında hücrenin contentView öğesini güncelleyebilirsiniz:

Statik UITableViewController için:

#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];

    if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1)
    {
        cell.contentView.frame = cell.bounds;
        cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
    }

    //your code goes here

    return cell;
}

#endif
#endif

Statik Tablo Görünümü Denetleyicileri kırılgan olduğundan ve bazı veri kaynağı veya delege yöntemlerini uygularsanız kolayca kırılabileceğinden - bu kodun yalnızca iOS 7'de derlenip çalıştırılacağını garanti edecek kontroller vardır.

Standart dinamik UITableViewController için benzerdir:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellID = @"CellID";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];

    if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1)
    {
        cell.contentView.frame = cell.bounds;
        cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
    }
    //your code goes here       
    return cell;
}

Bu durumda, bu yöntemin uygulanması gerektiğinden derleme fazladan kontrolüne ihtiyacımız yoktur.

Fikir her iki durum için ve UICollectionViewCell için aynıdır, bu konu başlığında yorumlandığı gibi: UICollectionViewCell contentView çerçevesinin Storyboard prototip hücresindeki (Xcode 6, iOS 8 SDK) otomatik yeniden boyutlandırma sorunu yalnızca iOS 7'de çalışırken gerçekleşir


1
Bu en iyi cevap veya en azından benim için en iyi çözüm. My Cell (Otomatik Düzen kuralları) iOS8'de XCode6 ile harika çalıştı ve XCode 5 ile iOS7 ve 6 ile harika çalıştı. XCode'u XCode6'ya güncelliyorum ve artık iOS6 ve 7'de çalışmıyor. Öyleyse teşekkürler !!!!
xarly

Bu artık Xcode 6.1 ile bir sorun değil. Ayrıca, NSFoundationVersionNumber'ı kullanmayın, lütfen nshipster.com/swift-system-version-checking
onmyway133

1
@ onmyway133: Bu neden Xcode 6.1'de artık sorun değil? Xcode 6.1 ve iOS 8.1 SDK kullansam bile hala sorun yaşıyorum. Sorun yalnızca iOS 7'de ortaya çıkıyor. Sınırları değiştirmek veya otomatik yeniden boyutlandırma maskesi ayarlamak sorunu çözer. Ancak en çok oylanan cevapta veya yorumlarda belirtilen yaklaşımı kullandım.
test

Evet, bu 3 saatlik googling'ime dayanan en iyi cevap. Diğer benzer "çözümler", cell.contentView.autoresizingMask'ın tam listesini sağlamaz. Yalnızca bu, Xcode 6'da oluşturulan iPad 7.1 projem için çalışıyor.
Golden Thumb

13

Hücreler yeniden kullanıldığından ve içeriğe bağlı olarak yükseklik değişebildiğinden, genel olarak boşlukların önceliğini gerekenden daha az ayarlamanın daha iyi olacağını düşünüyorum.

Sizin durumunuzda, UIImageView üste 15 ve alt görünümde 0'dan aşağıya kadar bir aralığa sahiptir. Bu kısıtlamaların önceliğini 999 (1000 yerine) olarak ayarlarsanız, kısıtlamalar gerekli olmadığından uygulama çökmez.

LayoutSubviews yöntemi çağrıldıktan sonra, hücre doğru yüksekliğe sahip olur ve kısıtlamalar normal şekilde karşılanabilir.


Sen bir dahisin! güzel ve temiz bir çözüm teşekkür ederim :)
Blacky

9

Film şeridi için hala iyi bir çözüm bulamadım ... Burada da bazı bilgiler: https://github.com/Alex311/TableCellWithAutoLayout/commit/bde387b27e33605eeac3465475d2f2ff9775f163#commitcomment-4633188

Orada tavsiye ettiklerinden:

self.contentView.bounds = CGRectMake(0, 0, 99999, 99999);

Çözümümü başlattım:

  • film şeridini sağ tıklayın
  • Farklı Aç -> Kaynak Kodu
  • orada "44" dizesini ara
  • gibi olacak

.

<tableView hidden="YES" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" allowsSelection="NO" rowHeight="44" ...
    <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="ChatMessageCell" id="bCG-aU-ivE" customClass="ChatMessageCell">
        <rect key="frame" x="0.0" y="22" width="320" height="44"/>

.

  • rowHeight = "44" yerine rowHeight = "9999" ve height = "44" yerine height = "9999" yazın
  • film şeridini sağ tıklayın
  • Farklı Aç -> Arayüz Oluşturucu
  • uygulamanızı çalıştırın ve çıktıyı kontrol edin

Bu benim için çalıştı. Film şeridinde, bazı hücrelerin prototipten ve diğerlerinin tamamen bir sınıf oluşturarak kodda oluşturulduğu bir UITableViewController oluşturmuştum.
Atharva

3

Varsayılan hücre yüksekliğini artırmanız yeterlidir. Görünüşe göre sorun, hücrenin içeriğinin varsayılan (ilk) hücre boyutundan daha büyük olması ve hücre gerçek boyutuna yeniden boyutlandırılıncaya kadar bazı olumsuz olmayan kısıtlamaları ihlal etmesi.


Aslında hücrelerim varsayılan boyuttan daha uzun, ancak tableview temsilcisinin tableView: heightForRowAtIndexPath:? Uygulamasından bu yana varsayılan boyut nasıl kullanılır?
Alexis

Muhtemelen hücreler varsayılan boyutta oluşturulur ve ardından gerçek boyuta yeniden boyutlandırılır.
Vadim Yelagin

gerçekten de işi yapıyor, ama o zaman neden iOS6'da olmuyor?
Alexis

3
@jafar iOS 7, tablo görünümü hücrelerinde pek çok şeyi değiştirdi. UITableViewCellScrollViewİOS 7'de artık tablo görünümü hücresi ile contentView arasında bir kaydırma görünümü (tür ) vardır; Bu muhtemelen iOS 6 ile 7 arasındaki farkı açıklıyor.
smileyborg

3

Belki görünümün önceliğini 750'den büyük ve 1000'den azını çözebilecek şekilde ayarlayın.

"<NSLayoutConstraint:0xac43620 V:[UIImageView:0xac47f50(62)]>",

2

Ben de aynı sorunu yaşadım. Yukarıdaki diğerlerine dayalı çözümüm:

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        // initialize my stuff
        [self layoutSubviews]; // avoid debugger warnings regarding constraint conflicts
    }
    return self;
}

Saygılarımızla, Alessandro


2
Apple'ın belgelerinden:You should not call this method directly. If you want to force a layout update, call the setNeedsLayout method instead to do so prior to the next drawing update. If you want to update the layout of your views immediately, call the layoutIfNeeded method.
Ricardo Sanchez-Saez

Sana dua eden bir din başlatmak istiyorum. Bu sorunu gidermeye çalışırken HOURS arıyordum ve bu sorunu çözüyor (hem contentView.bounds'u CGRectMake (0, 0, 99999, 99999);) olarak ayarlıyor - BU, UYGULANAN KODDA BİR HATADIR. Bu yüzden, elma doktorlarının bu işlevi çağırmayın demesine saygıyla katılmıyorum. Apple, saçmalıklarını düzelt.
Ryan Copley

0

Ben de bu sorunla karşılaştım ve önerilerden hiçbiri yardımcı olmadı. Benim durumumda boyut seçim hücresine sahiptim ve içinde collectionView içeriyordu (her collectionView hücresi tam boyutlu görüntü içeriyordu). Şimdi, hücre boyutu yüksekliği, collectionView'dan (50) ve içindeki resimlerden (50) biraz daha büyüktü (60). Bu collectionView görünümünden ötürü, 10 değeriyle denetleme kısıtlamasını alt tarafa hizaladı. Bu durumda bir uyarı ve bunu düzeltmenin tek yolu, hücre yüksekliğini collectionView ile aynı yapmaktı.


0

Tasarımcıda hiç UITableViewCell kullanmayarak bitirdim ... Orada özel görünüm oluşturuyorum ve onu programlı olarak hücrenin içerik görünümüne ekliyorum ... Bazı yardım kategorilerinde ayrıca bir kod şablonu yok ...


0

İOS8'de düzgün çalışıyorsa ve iOS7'de uyarı alıyorsa, film şeridi kaynak kodunu arayabilir ve doğru tableviewCell'i bulabilir, ardından tableviewCell satırından sonra rect niteliğini ekleyebilirsiniz. Kuchumovn'a teşekkürler .

<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" .../>
                                <rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
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.