Обычно каждая единица перевода генерирует объектный файл, содержащий определения символов, определенных в этой единицы перевода. Чтобы использовать эти символы, вам необходимо связать эти объектные файлы.
В разделе gcc вы должны указать все объектные файлы, которые должны быть связаны вместе в командной строке, или скомпилировать файлы реализации вместе.
g++ -o test objectFile1.o objectFile2.o -lLibraryName
Здесь libraryName
- это просто имя библиотеки, без добавления к платформе. Так, например, в файлах библиотеки Linux обычно называют libfoo.so
, но вы должны писать только -lfoo
. В Windows этот же файл можно назвать foo.lib
, но вы будете использовать тот же аргумент. Возможно, вам придется добавить каталог, в котором эти файлы можно найти, используя -L‹directory›
. Обязательно не записывайте пробел после -l
или -L
.
Для XCode: добавьте пути поиска заголовка пользователя -> добавьте путь поиска библиотеки -> перетащите фактическую ссылку библиотеки в
В MSVS файлы, добавленные в проект, автоматически связывают их объектные файлы, и будет создан файл lib
(в общем использовании). Чтобы использовать символы в отдельном проекте, вам нужно будет добавить файлы lib
в параметры проекта. Это делается в разделе Linker свойств проекта в Input -> Additional Dependencies
. (путь к файлу lib
должен быть добавлен в Linker -> General -> Additional Library Directories
). При использовании сторонней библиотеки, которая предоставляется с файлом lib
, отказ в этом обычно приводит к ошибке.
Также может случиться так, что вы забудете добавить файл в компиляцию, и в этом случае объектный файл не будет сгенерирован. В gcc вы должны добавить файлы в командную строку. В MSVS добавление файла в проект заставит его скомпилировать его автоматически (хотя файлы могут, вручную, быть отдельно исключены из сборки).
В программировании Windows контрольный знак, который вы не связывали необходимая библиотека состоит в том, что имя неразрешенного символа начинается с __imp_
. Посмотрите имя функции в документации, и она должна сказать, какую библиотеку вам нужно использовать. Например, MSDN помещает информацию в поле внизу каждой функции в разделе «Библиотека».
<UIScrollViewDelegate>
в ваш заголовок UIPageViewController viewDidLoad
: for (UIView *view in self.view.subviews) {
if ([view isKindOfClass:[UIScrollView class]]) {
((UIScrollView *)view).delegate = self;
break;
}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (_currentPage == 0 && scrollView.contentOffset.x < scrollView.bounds.size.width) {
scrollView.contentOffset = CGPointMake(scrollView.bounds.size.width, 0);
} else if (_currentPage == totalViewControllersInPageController-1 && scrollView.contentOffset.x > scrollView.bounds.size.width) {
scrollView.contentOffset = CGPointMake(scrollView.bounds.size.width, 0);
}
}
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
if (_currentPage == 0 && scrollView.contentOffset.x <= scrollView.bounds.size.width) {
*targetContentOffset = CGPointMake(scrollView.bounds.size.width, 0);
} else if (_currentPage == totalViewControllersInPageController-1 && scrollView.contentOffset.x >= scrollView.bounds.size.width) {
*targetContentOffset = CGPointMake(scrollView.bounds.size.width, 0);
}
}
Код для ввода в viewDidLoad
:
for subview in self.view.subviews {
if let scrollView = subview as? UIScrollView {
scrollView.delegate = self
break;
}
}
Реализация для scrollViewDidScroll:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if (currentPage == 0 && scrollView.contentOffset.x < scrollView.bounds.size.width) {
scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0);
} else if (currentPage == totalViewControllersInPageController - 1 && scrollView.contentOffset.x > scrollView.bounds.size.width) {
scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0);
}
}
Реализация для scrollViewWillEndDragging:
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
if (currentPage == 0 && scrollView.contentOffset.x <= scrollView.bounds.size.width) {
targetContentOffset.pointee = CGPoint(x: scrollView.bounds.size.width, y: 0);
} else if (currentPage == totalViewControllersInPageController - 1 && scrollView.contentOffset.x >= scrollView.bounds.size.width) {
targetContentOffset.pointee = CGPoint(x: scrollView.bounds.size.width, y: 0);
}
}
UIPageViewController на самом деле мало что делает для вас. Вы можете использовать UIScrollView с контроллерами представлений довольно легко и отключить отскок на этом.
Просто сделайте что-то вроде
int x=0;
for (NSString *storyboardID in storyboardIDs){
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:storyboardID];
[self addChildViewController:vc];
vc.view.frame = CGRectMake(x++*vc.view.frame.size.width, 0, vc.view.frame.size.width, vc.view.frame.size.height);
[self.scrollView addSubview:vc.view];
[vc didMoveToParentViewController:self];
self.scrollView.contentSize = CGSizeMake(storyboardIDs.count*vc.view.frame.size.width, vc.view.frame.size.height);
}
Я не знал, как правильно управлять currentIndex
, но в итоге сделал
extension Main: UIPageViewControllerDelegate {
func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if completed {
guard let viewController = pageViewController.viewControllers?.first,
index = viewControllerDatasource.indexOf(viewController) else {
fatalError("Can't prevent bounce if there's not an index")
}
currentIndex = index
}
}
}
Другой параметр - установить ScrollView.bounce = false. Он решил мою проблему с прокруткой прокрутки pageViewController (конечно, не про ScrollView). Откат отключен, и вся страница может прокручиваться без отскоков.
Отключить отладку UIPageViewController
Swift 2.2
1) Добавить UIScrollViewDelegate в UIPageViewController
extension PageViewController: UIScrollViewDelegate
2) Добавить в viewDidLoad
for view in self.view.subviews {
if let scrollView = view as? UIScrollView {
scrollView.delegate = self
}
}
3) Добавить методы UIScrollViewDelegate
func scrollViewDidScroll(scrollView: UIScrollView) {
if currentIndex == 0 && scrollView.contentOffset.x < scrollView.bounds.size.width {
scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0)
} else if currentIndex == totalViewControllers - 1 && scrollView.contentOffset.x > scrollView.bounds.size.width {
scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0)
}
}
func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
if currentIndex == 0 && scrollView.contentOffset.x < scrollView.bounds.size.width {
scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0)
} else if currentIndex == totalViewControllers - 1 && scrollView.contentOffset.x > scrollView.bounds.size.width {
scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0)
}
}
Изменить: не использовать это решение. После этого я узнал, что это вводит ошибку, где около 5% времени пользователь не может показывать страницу в одном направлении. Они должны вернуться на страницу, а затем переслать снова, чтобы продолжить.
Если вы используете UIPageViewControllerDataSource
, относительно простой обходной путь (и немного взломанный) - отключить переключение при каждом вызове метода делегата pageViewController:viewControllerBeforeViewController:
. Вот пример реализации:
@interface YourDataSourceObject ()
@property (strong, nonatomic) UIScrollView *scrollView;
@end
@implementation
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
if (!self.scrollView) {
for (UIView *view in pageViewController.view.subviews) {
if ([view isKindOfClass:[UIScrollView class]]) {
self.scrollView = (UIScrollView *)view;
}
}
}
self.scrollView.bounces = NO;
// Your other logic to return the correct view controller.
}
@end
Если вы попытаетесь отключить отскок для UIPageViewController.scrollView
, вы обязательно получите сломанный pageViewController
: салфетка не сработает. Итак, не делайте этого:
self.theScrollView.alwaysBounceHorizontal = NO;
self.theScrollView.bounces = NO;
Используйте решение с помощью поиска scrollView
в [sub] только для полного отключения прокрутки:
@interface MyPageViewController : UIPageViewController
@property (nonatomic, assign) BOOL scrollEnabled;
@end
@interface MyPageViewController ()
@property (nonatomic, weak) UIScrollView *theScrollView;
@end
@implementation MyPageViewController
- (void)viewDidLoad
{
[super viewDidLoad];
for (UIView *view in self.view.subviews) {
if ([view isKindOfClass:UIScrollView.class]) {
self.theScrollView = (UIScrollView *)view;
break;
}
}
}
- (void)setScrollEnabled:(BOOL)scrollEnabled
{
_scrollEnabled = scrollEnabled;
self.theScrollView.scrollEnabled = scrollEnabled;
}
@end
UIScrollView
(например, CustomScrolling). UIScrollView
уже является делегатом своего распознавателя жестов. UIViewController
(ака baseVC
с UIPageViewController
внутри) делится через AppDelegate
. В противном случае вы можете использовать run-time (#import <objc/runtime.h>
) и добавить свойство reference (к вашему контроллеру baseVC
) в категорию. @interface UIScrollView (CustomScrolling) <UIGestureRecognizerDelegate>
@end
@implementation UIScrollView (CustomScrolling)
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
UIViewController * baseVC = [(AppDelegate *)[[UIApplication sharedApplication] delegate] baseVC];
if (gestureRecognizer.view == baseVC.pageViewController.theScrollView) {
NSInteger page = [baseVC selectedIndex];
NSInteger total = [baseVC viewControllers].count;
UIPanGestureRecognizer *recognizer = (UIPanGestureRecognizer *)gestureRecognizer;
CGPoint velocity = [recognizer velocityInView:self];
BOOL horizontalSwipe = fabs(velocity.x) > fabs(velocity.y);
if (!horizontalSwipe) {
return YES;
}
BOOL scrollingFromLeftToRight = velocity.x > 0;
if ((scrollingFromLeftToRight && page > 0) || (!scrollingFromLeftToRight && page < (total - 1))) {
return YES;
}
return NO;
}
return YES;
}
@end
#import "UIScrollView+CustomScrolling.h"
в вашем baseVC
, который использует UIPageViewController.