测试用例很容易复制:下载Apple的PhotoScroller示例应用程序,并尝试对其进行调整,以便平移(在缩放图像周围和每个图像之间)仅适用于两个手指.
将the 和the panGestureRecognizer两者设置为仅接受最小和最多2次触摸似乎是一个好的起点,但它不起作用.它允许你用两根手指滚动图像就好*,但是分页然后不起作用.pagingScrollViewimageScrollView
我已经尝试了很多设置组合和自定义手势识别器,我有点难过.自定义滚动视图子类是否有用,或者我可以以某种方式操纵滚动视图委托方法使其工作?
*编辑:实际上,在这种情况下它不会滚动.只需轻轻一按,视图就不再顺畅滑动......
更新:我还在努力解决这个问题.我会很感激来自UIGestureRecognizers和UIScrollViews 玩过的人的一些意见.
编辑:
将ImageScrollView类设置为仅接受两个触摸:
- (id)initWithFrame:(CGRect)frame
{
// ...
// Template code
// ...
[self.panGestureRecognizer setMinimumNumberOfTouches:2];
[self.panGestureRecognizer setMaximumNumberOfTouches:2];
}
Run Code Online (Sandbox Code Playgroud)
将PhotoViewController's 设置pagingScrollView为仅接受两次触摸:
- (void)loadView
{
// ...
// Template code
// ...
[pagingScrollView.panGestureRecognizer setMinimumNumberOfTouches:2];
[pagingScrollView.panGestureRecognizer setMaximumNumberOfTouches:2];
}
Run Code Online (Sandbox Code Playgroud)
这些修改直接在PhotoScroller示例应用程序之上进行.我希望这些简单的改变适用于双指互动,但副作用很奇怪(如上所述).
旋转设备时,我看到UICollectionView了自定义布局(子类UICollectionViewLayout)的一些神秘行为.
我有一个简单的水平滚动的单元格行.当设备从纵向旋转到横向时,之前看不到的其他单元格变得可见,并且那些出现的单元格的动画是错误的(它使用熟悉的重影效果,我认为这是集合视图的某种默认动画效果布局).请注意此动画中最左侧出现的单元格:

有关自定义布局设置的一些细节:
shouldInvalidateLayoutForBoundsChange:回报YES.layoutAttributesForItemAtIndexPath:缓存字典中的属性(如果尚未创建).layoutAttributesForElementsInRect:我计算哪些单元格应该是手工可见的,并且centre每次稍微调整它们的属性,然后返回它们的属性.然后我有以下代码来处理初始/最终布局属性:
- (void)prepareForAnimatedBoundsChange:(CGRect)oldBounds
{
[super prepareForAnimatedBoundsChange:oldBounds];
self.animatingBoundsChange = YES;
}
- (void)finalizeAnimatedBoundsChange
{
[super finalizeAnimatedBoundsChange];
self.animatingBoundsChange = NO;
}
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath
{
if (self.animatingBoundsChange) {
// If the view is rotating, appearing items should animate from their current attributes (specify `nil`).
// Both of these appear to do much the same thing:
//return [self layoutAttributesForItemAtIndexPath:itemIndexPath];
return nil;
}
return …Run Code Online (Sandbox Code Playgroud) 有一些关于UICollectionView隐藏细胞的错误的问题,但我不认为这个问题已被覆盖.大多数其他问题似乎特别关注UICollectionViewFlowLayout和部分插入,而我在完全自定义布局之间转换时看到了这个问题.
执行交互式布局转换时,UICollectionView似乎隐藏了不应隐藏的单元格:

(注意转换过程中左下角的单元格40和45消失)
它似乎发生在一个特定的地方:每当单元格的布局属性(从转换布局返回layoutAttributesForElementsInRect:)的框架的minX小于传入rect的minX和maxY大于rect's maxY.在代码中:
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray *layoutAttributes = [super layoutAttributesForElementsInRect:rect];
for (UICollectionViewLayoutAttributes *attr in layoutAttributes) {
if (CGRectGetMinX(attr.frame) < CGRectGetMinX(rect) &&
CGRectGetMaxY(attr.frame) > CGRectGetMaxY(rect)) {
NSLog("Element at index path %@ will disappear unexpectedly", attr.indexPath);
}
}
return layoutAttributes;
}
Run Code Online (Sandbox Code Playgroud)
过渡布局返回正确的布局属性,显示单元格的中心逐渐在屏幕外移动.但是,一旦它超过了上面提到的那一点,集合视图似乎决定它不再可见(它是!)并将单元格的hidden属性设置为yes,忽略它直到其框架进一步移动rect.
我已经整理了一个演示此问题的示例项目(上面的动画就是这个样本的实际应用).为简单起见,它使用了两个简单的流布局,但我在处理自定义UICollectionViewLayout子类之间的转换时首先注意到了它.大多数代码只是使用捏手势识别器管理交互式转换,我很确定那里没什么了不起的.
当使用简单的动画布局过渡(setCollectionViewLayout:animated:)时,似乎不会发生这个问题...尝试使用慢动画运行示例项目,然后点击一个单元格 - 所有单元格按预期动画.
这UICollectionView对我来说似乎是一个错误,但如果有人知道有效的解决方法,我真的很感激.
更新:
我已向Apple提交了错误报告,同时打开了技术支持事件,以查看是否可以找到解决方法.如果我从工程师那里学到任何有用的东西,我会添加一个答案.
更新:
Apple DTS回复确认这是一个错误,并且没有解决方法.对于我的情况,我最终只是强迫消失的细胞 …
我有一个类,StateMachine它是通用的,允许实现不同的状态集,例如,枚举.我想StateMachineDelegate在状态机进入新状态时使用协议通知委托.
但这不起作用,因为委托协议对于类型要求也是通用的.该错误显示了delegate声明属性的位置.
protocol StateType: Hashable {}
protocol StateMachineDelegate: class {
typealias S: StateType
func stateMachine(stateMachine: StateMachine<S>, didEnterState newState: S)
}
class StateMachine<S: StateType> {
typealias State = S
weak var delegate: StateMachineDelegate?
//~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
//Protocol 'StateMachineDelegate' can only be used as a generic constraint because it has Self or associated type requirements
var currentState: State {...}
init(initialState: State) {...}
func applyState(toState: State) -> Bool {
...
currentState = toState
delegate?.stateMachine(self, didEnterState: toState)
...
}
} …Run Code Online (Sandbox Code Playgroud) 我一直试图创建一个简单的UIManagedDocument库样式应用程序(保存到iCloud的单独文档)非常失败.
我对以下内容感到困惑:
难道我的子类UIManagedDocument,并成立了persistentStoreCoordinator,ManagedObjectModel与ManagedObjectContext这个子类中,或者这些应该是内部配置的AppDelegate(如果是的话,我怎么去刷新persistentStoreCoordinator看新的文件-看来,一旦已经读了persistentStore这我不能让它读取新的持久存储)?
我正在使用UIManagedDocuments来管理iCloud中的文件.设置之后NSMetadataQuery如此:
iCloudQuery = [[NSMetadataQuery alloc] init];
[iCloudQuery setSearchScopes:
[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
[iCloudQuery setPredicate:
[NSPredicate predicateWithFormat:@"%K like %@", NSMetadataItemFSNameKey, @"DocumentMetadata.plist"]];
Run Code Online (Sandbox Code Playgroud)
我遇到了一个奇怪的问题 - 当我的文档没有文件扩展名(例如@"NewDocument2")或公共扩展名时.txt,元数据查询正确地找到了DocumentMetadata.plist文件.但是,当使用我的自定义文件扩展名时,查询永远不会找到任何内容......不是在查询开始时,也不是在我添加新文档时.
在我看来,查询可能是看到我的文档及其自定义文件扩展名,并没有意识到它实际上是一个目录(无论如何都是文件包),因此不会查找内部查找DocumentMetadata.plist文件.但是,我在应用程序中声明了我的自定义UTI info.plist.
也许我已经错误地宣布了我的UTI?我遵循Apple的指导原则(在基于文档的iOS应用程序编程指南和统一类型标识符概述中)创建它,但似乎有些不对劲.
编辑:在"导出的UTI"中info.plist,我的类型设置为符合"com.apple.package".
编辑: 我仍然在努力解决这个问题.我现在正在通过不使用文件扩展名来解决它.
使用自定义文件扩展名时,我正在处理iCloud元数据查询结果,DocumentMetadata.plist文件肯定在文件包中,但元数据查询无法看到它.枚举查询结果时,以下内容将打印到日志中:
<iCloud Container URL>/Documents/
<iCloud Container URL>/Documents/New%20Document.spdoc/
<iCloud Container URL>/Documents/New%20Document.spdoc/DocumentMetadata.plist
<iCloud Container URL>/Documents/New%20Document.spdoc/StoreContent.nosync/
<iCloud Container URL>/Documents/New%20Document.spdoc/StoreContent.nosync/(A%20Document%20Being%20Saved%20By%20<AppName>%202)/
<iCloud Container URL>/Documents/New%20Document.spdoc/StoreContent.nosync/(A%20Document%20Being%20Saved%20By%20<AppName>)/
<iCloud Container URL>/Documents/New%20Document.spdoc/StoreContent.nosync/.persistentStore_SUPPORT/
<iCloud Container URL>/Documents/New%20Document.spdoc/StoreContent.nosync/.persistentStore_SUPPORT/_EXTERNAL_DATA/
<iCloud Container URL>/Documents/New%20Document.spdoc/StoreContent.nosync/persistentStore
Run Code Online (Sandbox Code Playgroud)
("CoreDataLogs"目录中还有一堆文件,但为了简洁起见,我没有在这里显示它们). …
我的应用程序使用iCloud.我的应用程序将其所有数据存储在1个文档中,并且永远不会超过这个1文档.但是,有时我的NSMetadataQuery返回2个文档:
0:Documents /(正在通过MyApp保存的文档)/MyDoc.ext
1:Documents/MyDoc.ext
这种情况主要发生在iOS设备重启后不久用户打开应用程序时.
在检查这两个文档时,文档0是具有最新更新的文档,因此这是我们想要的文档.
这个"文档被保存"的原因是什么,最后一个是什么?我如何正确处理这个问题,所以Documents/MyDoc.ext将是最新内容的文件.
谢谢,-r
我有一个UIDocument基于应用程序,使用NSFileWrappers来存储数据.'master'文件包装器包含许多其他目录文件包装器,每个包装器代表文档的不同页面.
每当我在UIDocument保存(in writeContents:andAttributes:safelyToURL:forSaveOperation:error:)时对文档进行更改时,应用程序崩溃.这是堆栈跟踪:

很明显,我正在修改UIDocument在后台枚举的文件包装器的同一个实例.实际上,我检查了当返回数据模型的快照时contentsForType:error:,返回的子文件包装器指向与数据模型中当前驻留(和正在编辑)的对象相同的对象,而不是副本.
- (id)contentsForType:(NSString *)typeName error:(NSError *__autoreleasing *)outError
{
if (!_fileWrapper) {
[self setupEmptyDocument];
}
return [[NSFileWrapper alloc] initDirectoryWithFileWrappers:[_fileWrapper fileWrappers]];
}
Run Code Online (Sandbox Code Playgroud)
这是实施此方法的认可方法(根据WWDC 2012会议218 - 使用带有UIDocument的iCloud).
所以我想问题是:这种方法如何是线程安全的?
当主文件包装器fileWrappers本身是目录文件包装器时,情况是否有所不同?如果受制裁的方法是错误的,应该怎么做?
考虑一个标准的垂直滚动流布局,其中填充了足够的单元格以进行滚动.当滚动到底部时,如果删除项目,使得集合视图的内容大小必须缩小以容纳新项目数(即删除底行上的最后一项),则从中滚动的单元格行顶部是隐藏的.在删除动画结束时,顶行显示没有动画 - 这是一个非常不愉快的效果.
慢动作:

重现真的很简单:
创建一个新的单个视图项目,并将默认值更改ViewController为其子类UICollectionViewController
添加UICollectionViewController到使用标准流布局的故事板,并将其类更改为ViewController.为单元格原型提供标识符"Cell",大小为200x200.
将以下代码添加到ViewController.m:
@interface ViewController ()
@property(nonatomic, assign) NSInteger numberOfItems;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.numberOfItems = 19;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.numberOfItems;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
return [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
self.numberOfItems--;
[collectionView deleteItemsAtIndexPaths:@[indexPath]];
}
@end
Run Code Online (Sandbox Code Playgroud)
在处理集合视图时,我已经看到了这个问题的其他表现形式,只是上面的例子似乎最简单地证明了这个问题.UICollectionView在默认动画期间似乎陷入某种瘫痪的恐慌状态,并且在动画完成之前拒绝取消隐藏某些单元格.它甚至可以防止cell.hidden = NO对隐藏单元的手动调用产生影响(hidden仍然是YES之后).hidden …
ios uicollectionview uicollectionviewcell uicollectionviewlayout
我正在使用Xcode 7.0 beta 4,最近将我的单个Main.storyboard拆分成一系列故事板引用连接的故事板(Xcode 7中新增了).
构建时,我收到以下"Interface Builder Storyboard Linker Error":
/* com.apple.ibtool.errors */
: error: The file “Info.plist” couldn’t be saved in the folder “Pages.storyboardc”.
Underlying Errors:
Description: The operation couldn’t be completed. Not a directory
Failure Reason: Not a directory
Run Code Online (Sandbox Code Playgroud)
我怎样才能理解这个错误?
故事板参考是通过选择原始故事板中的场景并选择编辑器>重构到故事板...来创建的.我遇到的上一个问题是故事板链接器抛出了不同类型的错误:
/* com.apple.ibtool.errors */
: error: Deploying Storyboard References to iOS 8.0 requires that your storyboards do not
share any view controller identifiers. Browser.storyboard and Pages.storyboard
both contain a view controller with identifier "PagesViewController".
Run Code Online (Sandbox Code Playgroud)
事实证明,使用"Refactor to …
ios ×8
icloud ×3
save ×2
core-data ×1
delegates ×1
document ×1
generics ×1
ibtool ×1
icloud-api ×1
iphone ×1
multi-touch ×1
nspredicate ×1
objective-c ×1
panning ×1
protocols ×1
storyboard ×1
swift ×1
transitions ×1
uidocument ×1
uiscrollview ×1
xcode ×1
zoom ×1