2016-08-03 31 views
11

Meine Ansicht ist, ist diesWie UIScrollView contensize zu setzen, wenn Inhalt Last Hierarchie asynchron

PhotoDetailViewController.swift 

    View 
     UIScrollView 
     UIImageView 

ich dies oben mit Storyboard festgelegt und vier Einschränkungen hinzufügen (top = 0, unten = 0, was = 0, Tailing = 0) zu UIScrollView, vier Bedingungen (oben = 0, unten = 0, was = 0, rückstand = 0) UIImageView, aber es gibt zwei Fehler, sagt

"ScrollView has ambiguous scrollable content width" 
"ScrollView has ambiguous scrollable content height" 

ich verstehe, dass dies, weil ich haven ist‘ t set UIScrollView contentSize, aber was ich versuche, ist das Laden von Fotos aus PHAsset asynchron, so kann ich nur die Fotogröße erhalten zur Laufzeit. Also die Frage ist:

1: Angesichts, dass Fotogröße kann nur zur Laufzeit bekommen, wie den Fehler "mehrdeutigen scrollbaren Inhalt" zu lösen?

2: In welcher Life Cycle-Methode von View sollte ich PHImageManager.requestImageForAsset aufrufen? weil ich denke, ich sollte UIScrollView contentSize programmgesteuert einstellen, aber wann?

Update mit PhotoDetailViewController.swift

import UIKit 
import Photos 

class PhotoDetailViewController : UIViewController { 

@IBOutlet weak var scrollView: UIScrollView! 
@IBOutlet weak var imageViewBottomConstraint: NSLayoutConstraint! 
@IBOutlet weak var imageViewLeadingConstraint: NSLayoutConstraint! 
@IBOutlet weak var imageViewTopConstraint: NSLayoutConstraint! 
@IBOutlet weak var imageViewTrailingConstraint: NSLayoutConstraint! 

var devicePhotosAsset : PHFetchResult! 
var index = 0 
var photo : UIImage! 
var imgManager:PHImageManager! 

@IBOutlet weak var imageView : UIImageView! 

override func viewWillAppear(animated: Bool) { 
    super.viewWillAppear(animated) 
} 

override func awakeFromNib() { 
    self.imgManager = PHImageManager() 
} 

override func viewDidLoad() { 
    super.viewDidLoad() 
    self.displayPhoto() 
} 

override func viewWillLayoutSubviews() { 
    super.viewDidLayoutSubviews() 
    updateMinZoomScaleForSize() 
    updateConstraintsForSize() 
} 

func displayPhoto() { 
    _ = self.imgManager.requestImageForAsset(self.devicePhotosAsset[self.index] as! PHAsset, targetSize: PHImageManagerMaximumSize, contentMode: .AspectFit, options: nil, resultHandler: {(result, info) -> Void in 
      NSOperationQueue.mainQueue().addOperationWithBlock(){ 
       self.imageView.image = result 
      } 

     }) 
} 

private func targetSize() -> CGSize { 
    let scale = UIScreen.mainScreen().scale 
    let targetSize = CGSizeMake(CGRectGetWidth(self.imageView.bounds)*scale, CGRectGetHeight(self.imageView.bounds)*scale) 

    return targetSize 
} 

private func updateMinZoomScaleForSize() { 
    let size = scrollView.bounds.size 
    let widthScale = size.width/imageView.bounds.width 
    let heightScale = size.height/imageView.bounds.height 
    let minScale = min(widthScale, heightScale) 

    scrollView.minimumZoomScale = minScale 

    scrollView.zoomScale = minScale 
} 

func recenterImage(){ 
    let scrollViewSize = scrollView.bounds.size 
    let imageSize = imageView.frame.size 

    let horizontalSpace = imageSize.width < scrollViewSize.width ? (scrollViewSize.width - imageSize.width)/2 : 0 
    let verticalSpace = imageSize.height < scrollViewSize.height ? (scrollViewSize.height - imageSize.height)/2 : 0 
    scrollView.contentInset = UIEdgeInsets(top: verticalSpace, left: horizontalSpace, bottom: verticalSpace, right: horizontalSpace) 
} 

private func updateConstraintsForSize() { 
    let size = scrollView.bounds.size 
    let yOffset = max(0, (size.height - imageView.frame.height)/2) 
    imageViewTopConstraint.constant = yOffset 
    imageViewBottomConstraint.constant = yOffset 

    let xOffset = max(0, (size.width - imageView.frame.width)/2) 
    imageViewLeadingConstraint.constant = xOffset 
    imageViewTrailingConstraint.constant = xOffset 

    view.layoutIfNeeded() 
} 
} 

extension PhotoDetailViewController: UIScrollViewDelegate { 
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? { 
    return imageView 
} 

func scrollViewDidZoom(scrollView: UIScrollView) { 
    updateConstraintsForSize() 
} 
} 

Antwort

2

Wenn Sie die Daten erhalten, fügen Sie einfach diese Zeilen

float sizeOfContent = 0; 
UIView *lLast = [yourscrollview.subviews lastObject]; 
NSInteger wd = lLast.frame.origin.y; 
NSInteger ht = lLast.frame.size.height; 
sizeOfContent = wd+ht; 
yourscrollview.contentSize = CGSizeMake(yourscrollview.frame.size.width, sizeOfContent); 

this helps

+0

Wie über die Storyboard-Fehler? lass es einfach da? – paynestrike

+0

Sie verwenden automatisches Layout? – gurmandeep

+0

ja Ich verwende Autolayout – paynestrike

3

Sie zwei weitere Einschränkung auf Ihre imageView setzen soll.

  1. horizontal in Container (oder Sie können es Mitte X sagen)
  2. Feste Höhe

zweite, was Sie UIView auf Scrollview mit Einschränkungen wie setzen, Top,leading,trailing,bottom,Horizontally in container(center x),fixed height).

Dann fügen Sie Ihre Bildansicht zu dieser Ansicht. Und kann die Einschränkung ändern, nachdem das Bild seine Größe und Höhe geändert hat.

Sie können outlet von jeder Einschränkung verbinden und können sie programmgesteuert ändern.

+0

Sie meinst hinzufügen ImageView programmgesteuert? – paynestrike

+0

Sie können programmgesteuert oder über den Schnittstellen-Builder hinzufügen. Wenn Sie es aus dem Interface Builder hinzufügen, sollten Sie die erforderlichen Einschränkungen, die Sie ändern möchten, ändern, um die Größe zu ändern, nachdem Sie das Image aus der Bibliothek oder Datenbank abgerufen haben. – Lion

+0

der Grund, warum ich Scroll-Ansicht verwende, ist, weil ich Foto-Zoom-Effekt erreichen möchte, so dass ich jede Bildansicht Constrains zu Controller verbinden und den Constrain-Wert aktualisieren, wenn Foto geladen, bu scheint nicht funktioniert, überprüfen Sie bitte das Update – paynestrike

7

Ihre vorhandenen Einschränkungen reichen aus, um die Inhaltsgröße festzulegen, es basiert nur auf der tatsächlichen Größe des Bildansichtsinhalts und ist nicht wirklich vorhanden, bis die Bildansicht ein Bild enthält.

Sie können der Bildansicht eine Breiten- und Höhenbeschränkung mit Standardwerten hinzufügen und diese Einschränkungen deaktivieren, wenn das Bild auf die Ansicht eingestellt ist. Oder Sie können ein Platzhalterbild verwenden und diese zusätzlichen Einschränkungen vermeiden, da Sie immer eine eigene Inhaltsgröße für die Bildansicht haben.

3

Xcode UI-Builder verfügt über einen speziellen Constraint-Typ für solche Fälle (wenn Sie Constraint nur in Runtime einrichten können). Es ist eine so genannte "Platzhaltereinschränkung", die zum Zeitpunkt der Erstellung entfernt wird, aber hilft, Constraint-Fehler für die Entwicklung zu entfernen.

Placeholder constraint

So Lösung ist

  1. einige Beispiel Einschränkungen IB hinzufügen und markieren sie als Platzhalter
  2. Add benötigt Einschränkungen im laufenden Betrieb