我的视图层次结构就是这个
PhotoDetailViewController.swift
View
UIScrollView
UIImageView
我使用storyboard设置它,并向UIScrollView添加四个约束(top = 0,bottom = 0,leading = 0,tailing = 0),四个约束(top = 0,bottom = 0,leading = 0,tailing = 0)到UIImageView,但有两个错误说
"ScrollView has ambiguous scrollable content width"
"ScrollView has ambiguous scrollable content height"
我知道这是因为我还没有设置UIScrollView contentSize,但我想要做的是异步加载PHAsset中的照片,所以我只能在运行时获取照片大小。所以问题是:
1:鉴于照片大小只能在运行时获得,如何解决"模糊的可滚动内容"错误?
2:我应该在哪个View生命周期方法中调用PHImageManager.requestImageForAsset?因为我认为我应该以编程方式设置UIScrollView contentSize,但什么时候?
使用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()
}
}
答案 0 :(得分:7)
您现有的约束足以设置内容大小,只是它基于图像视图的内在内容大小,并且在图像视图有图像之前不存在。
您可以使用默认值向图像视图添加宽度和高度约束,并在图像设置为视图时停用这些约束。或者您可以使用占位符图像并避免这些额外的约束,因为您始终拥有图像视图的内在内容大小。
答案 1 :(得分:3)
您应该为imageView
再设置两个约束。
第二件事你可以将UIView
放在Scrollview
上,约束如,
Top,leading,trailing,bottom,Horizontally in container(center x),fixed height).
然后将您的imageview添加到该视图。并且可以在获取图像以调整其高度和宽度后更改它的约束。
您可以连接任何约束的outlet
,并可以通过编程方式更改它。
答案 2 :(得分:3)
Xcode UI构建器对此类情况具有特殊类型的约束(当您只能在运行时设置约束时)。它被称为“占位符约束”,它将在构建时删除,但有助于消除开发中的约束错误。
所以解决方案是
答案 3 :(得分:2)
获取数据后,只需添加以下行
即可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);
希望这有帮助