2015-06-19 31 views
8

Şu anda bazı geçişler oluşturuyorum ve bir panning görünümü için CGAffineTransform aracılığıyla dönüşüm yapıyorum ve iOS 7 ve iPhone 4 altında dönüşüm performansı nedeniyle sorun yaşıyorum.CGAffineTransforms performansı gerçekten yavaştır iOS 7

Istruments'da yaşadım ve eşyaları kaydettim ve dönüşümlerimi görünüme uygularken ağır kaldırma işlemi yapıldı. iOS 7 için

Güncel Uygulama

func handlePan(recognizer : UIPanGestureRecognizer) { 

     let drawerLocation = recognizer.locationInView(drawerView!) 
     let locationInView = recognizer.locationInView(containerView!) 
     let progressMax = containerView!.frame.height - 40 - 20 

     if(recognizer.state == .Changed) { 

      let offsetDrag = dragStartPosition.y - locationInView.y 
      let progress = Float(offsetDrag/progressMax) 

      if(offsetDrag >= 0) { 

       let positionTransform = CGAffineTransformMakeTranslation(0, -((containerView!.bounds.height - 40 - 20) * CGFloat(normalizedProgress))) 
       viewWithTransform.transform = positionTransform // really bad performance here 
      } else { 
       // reset the transition 
      }  
    } 
} 

Geçici çözüm

func handlePan(recognizer : UIPanGestureRecognizer) { 

     let drawerLocation = recognizer.locationInView(drawerView!) 
     let locationInView = recognizer.locationInView(containerView!) 
     let progressMax = containerView!.frame.height - 40 - 20 

     if(recognizer.state == .Changed) { 

      let offsetDrag = dragStartPosition.y - locationInView.y 
      let progress = Float(offsetDrag/progressMax) 

      if(offsetDrag >= 0) { 
       if UIDevice.currentDevice().systemMajorVersion() > 7 { 
        let positionTransform = CGAffineTransformMakeTranslation(0, -((containerView!.bounds.height - 40 - 20) * CGFloat(progress))) 
        viewWithTransform.transform = positionTransform // really bad performance here 
       } else { 
        viewWithTransform.frame = CGRectMake(0, -((containerView!.bounds.height - 40 - 20) * CGFloat(progress)), drawerView!.frame.size.width, drawerView!.frame.size.height); // works like a charm on iOS 7 
       } 

      } else { 
       // reset the transition 
      }  
    } 
} 

Soru

neden iOS 7'de kadar kötü performans ve CGAffineTransforms ile benim iPhone 4 ? Çünkü ofset ile aynı şeyi yapıyor, sonra geçici çözümde çerçeve ayarını yapıyor. UIView.animateWithDuration()'u dönüşümle kullandığımda 60 fps performans gösteriyor. IOS 7 temelindeki tüm uygulamayı yeniden yazmam için ne yapabilirim?

GÜNCELLEME 28th Temmuz AutoLayout'ın bu sorunla ilgili olabileceğini öğrendik. İşte TimeProfiler Stack benim şimdiki aramalardan: Ben AutoLayout güvenmek çünkü Şimdi, benim şimdiki uygulamada büyük bir sorun bakan değilim

Time Profiler

. IOS 7'de bu sorunu çözmek için en kolay çözüm nedir?

+0

'viewWithTransform.translate =' özel bir şey mi yoksa 'viewWithTransform.transform =' olması mı gerekiyor? Otomatik Düzen'i kullanarak (kasıtlı veya istemeden) mısınız? Sürüm oluşturmalarını kullanarak profil mi yapıyorsunuz? –

cevap

4

Aynı şeyi yaptıklarında haklı olduğunuz halde, kaputun altında, o kadar kolay değil - her yere giden matris çarpanları var. More on that can be found here.

Sadece bunu yapıyorsanız, bu performansınızı etkiliyor garip bir durumdur - ama düzeninizin karmaşık ve sanırım yeniden oluşturma çok zaman alır; Eğer dönen zamanlarda nedense bu özel görünümünden Otomatik Düzen çıkarmadan

  • çerçeve ile manipülasyon kullanılmalıdır
  • bir sürü yardımcı olur: Aslında işte bana yardımcı budur, bir hafta önce aynı problem vardı/ölçekleme görünümü. Bunları kullanırken gerçekten ihtiyacı var.

Ayrıca kullanılan dönüşüm zaman birbirlerinin arkasına onlardan daha var özellikle gölgeler ve yarı saydam görüşlerini, çıkarma

  • , GERÇEKTEN o zaman uyumsuz çağrısında dönüşümü görmek atamak deneyebilirsiniz, FPS düşer

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), {() -> Void in 
         dispatch_async(dispatch_get_main_queue(), {() -> Void in 
          // Transform view 
         }) 
        }) 
    

    Ve gerçekten fantezi olmasını istiyorsanız, POP Framework from Facebook kullanın: Eğer yardımcı olur.

    // Create spring animation (there are more types, if you want) 
    let animation = POPSpringAnimation(propertyNamed: kPOPViewCenter) 
    
    // Configure it properly 
    animation.autoreverses = false 
    animation.removedOnCompletion = true 
    animation.fromValue = view.center 
    animation.toValue = finalPositionPoint 
    
    // Add new animation to your view - animation key can be whatever you like, serves as reference 
    view.pop_addAnimation(animation, forKey: "YourAnimationKey") 
    

    Düzenleme:: sadece etrafında görünümü taşıyacaksanız, kullanım Size istediğiniz şey için harika ve size sıçrama gibi bazı fantezi şeyler yapmak için izin verir, esneme vb Burada kullanabilirsiniz nasıl .merkez özellik değil çerçeve. Tekrar yükseklik/genişlik tanımlamanız ve niyetleriniz hakkında daha net bir fikir vermeniz gerektiğinden tasarruf etmenizi sağlar.

  • +0

    Ben dispatch_async şeyi deneyin. Bu gerçekten kolay. Ben main_queue'dayım ve dönüşümü ana sıradaki sonraki runloop'a gönderiyorum. Basit geliyor. Facebook'tan POP'u biliyorum, ancak bunu bir pan hareketi üzerinde kullanmak mümkün mü? Yani çok denir;) – mariusLAN

    +0

    Pan hareketi için, öğeniz için bir yay animasyon oluşturmanızı ve propertyOnCompletion = false özelliğini ayarlamanızı öneririm. Bu şekilde, "toValue" değerine ulaştıktan sonra bile, bağımsız olarak çalışır. Kaydettiğinizde, .toValue’yi değiştirin ve tekrar animasyon yapmaya başlayacaktır. –

    +0

    @mariusLAN Sorununuzu çözümüm kullanarak çözdünüz mü? –