IOS 7 жүйесіндегі UINavigationController-дағы қаттылығын қайтадан өшіру

IOS 7-де Apple жаңа навигациялық мінез-құлыққа қосылды. Навигация бумасына қайта оралу үшін экранның сол жақ жиегінен сырғытуға болады. Бірақ менің қолданымдағы бұл мінез-құлық менің сол жақ мәзіріммен қақтығысады. Мәселен, UINavigationController-дағы бұл жаңа әрекетті өшіру мүмкін бе?

284
Мен navigationItem.hidesBackButton = true параметрін орнатсаңыз, бұл қимыл да ажыратылады. Менің жағдайым бойынша мен артқы бэкапты енгізіп, leftBarButtonItem ретінде қосылдым
қосылды автор Umair, көзі

15 жауаптар

Мен шешім таптым:

Objective-C:

if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
    self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}

Swift 3:
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false

539
қосылды
Мен navigationItem.hidesBackButton = true параметрін орнатсаңыз, бұл қимыл да ажыратылады. Менің жағдайым бойынша мен артқы бэкапты енгізіп, leftBarButtonItem ретінде қосылдым
қосылды автор Umair, көзі
Бұл неге iOS8-де жұмыс істемеуі керек?
қосылды автор ArtFeel, көзі
viewDidAppear: / viewDidDisappear мекенжайындағы қосу/өшіру танғышын пайдалануға болады. Немесе сіз күрделі логикамен UIGestureRecognizerDelegate протоколын қолдана аласыз және оны recognizer.delegate сипаты ретінде орнатасыз.
қосылды автор ArtFeel, көзі
Әрине, iOS-дың ескі нұсқаларын қолдайтын болсаңыз, жаңа әдістердің болуын тексеру керек.
қосылды автор ArtFeel, көзі
IOS 8 жүйесімен жұмыс істейтіндер менің жаңартылған жауапты төменде қараңыз. Бұл мен үшін жұмыс істеді - бұл сен үшін де жұмыс істейтініне сенемін.
қосылды автор Charlie Seligman, көзі
Оны көзқарасқа қосып тастауға мүмкіндік бар ма?
қосылды автор Marc, көзі
Бұл әлі де маған iOS 8 жүйесінде жұмыс істейтінін растаймын.
қосылды автор Myxtic, көзі
Бұл iOS6 жүйесінде іске қосылған кезде жарамсыз дәлелді алып тастауды тудырады.
қосылды автор Ant, көзі
Ол iOS 8 жүйесінде әлі де жұмыс істейді.
қосылды автор Ben, көзі
Yer оны ViewWillLayoutSubviews-да ұстайды - дегенмен бірнеше рет қоңырау шалады деп ойлаймын
қосылды автор Rambatino, көзі
Бұл iOS9-да жұмыс істемейді. Төмендегі жауап Антуаннан (делегатты белгілеп) жұмыс істейді. Оның біраз шатасуы, себебі сіз оны мысалы, мысалы, КөрінетінDidAppear кейде жұмыс істейді, бірақ бұл шын мәнінде, сіз бірінші рет шетінен сырғытып, төменгі vc-ні көріп, одан кейін қайырып-сырғыту шынымен өшірілгеннен кейін viewDidAppear-ді қайтадан шақырады. Дегенмен, экран бастапқыда ұсынылған кезде ол мүгедек емес!
қосылды автор HixField, көзі
IOS8 параметрінде self.navigationController.interactivePopGestureRecognizer.en & zwnj; abled сипатын орнату келесі көріністің әдістерінде жұмыс істемейді: viewDidLoad , viewWillAppear , viewDidAppear , viewDidDisappear , бірақ viewWillDisappear әдісінде жұмыс істейді. IOS7-де аталған барлық әдістерде жұмыс істейді. Сондықтан, viewController жұмыс істеген кезде оны кез-келген басқа әдістермен қолдануға тырысыңыз, мен оны iOS8-де көрініс ішіндегі кейбір түймешіктерді басқан кезде жұмыс істейтінін растаймын.
қосылды автор Sihad Begovic, көзі
Мұны жасайтын телефонға арналған плагин бар ма?
қосылды автор Seth Caldwell, көзі
Бұл iOS 8-де жұмыс істемейтініне сенемін
қосылды автор Jamie, көзі
IOS8 ішіндегі бұл көріністе viewDidLoad және viewWillAppear жұмыс істемейтінін растауға болады
қосылды автор tonytastic, көзі
UISplitViewController сияқты detailViewController үшін болса, self.navigationController.navigationController.interactivePo & zwnj; pGestureRecognizer.e & zwnj; nabled = NO;
қосылды автор SFF, көзі

Мен мүгедектерге қимыл жасауды әрдайым істемейтінін білдім. Бұл жұмыс істейді, бірақ мен үшін бұл тек бір рет қолданғаннан кейін жасалды. Екіншіден, ол артта қалмайды.

Мені түзетіп, қимылды тапсырып, NO-ға қайтару әдісін енгізу қажет болды:

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

   //Disable iOS 7 back gesture
    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
        self.navigationController.interactivePopGestureRecognizer.enabled = NO;
        self.navigationController.interactivePopGestureRecognizer.delegate = self;
    }
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

   //Enable iOS 7 back gesture
    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
        self.navigationController.interactivePopGestureRecognizer.enabled = YES;
        self.navigationController.interactivePopGestureRecognizer.delegate = nil;
    }
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    return NO;
}
44
қосылды
Егер мен сізді бұл сияқты ұстап қойған болсаңыз, егер сіз мұны бөлшектелген көрініс контроллерінде мастер-бөлшекті көрініс үшін жасасаңыз, онда self.navigationController.navigationController үшін де солай істеуіңіз керек. stackoverflow.com/a/50012503/5605365 бөлімін қараңыз.
қосылды автор Matt D, көзі
Егер if операторы, делегат ретінде өзін тағайындайтын кодтың екінші жолы мен үшін қате жасайды: 'VCPrivateData * const __strong' үйлесімсіз түрінен 'id _Nullable' тағайындау. Бірақ, бірінші сызықты өшіріп тастап, оны өшіргенін түсіндіріп тастаңыз. Мен jestRecognizerShouldBegin-ді де іске асырудың қажеті болмады.
қосылды автор Alyoshak, көзі
Рахмет! Бұл жан-жағын қайыруды толық өшіру үшін қажет. Ол әлі күнге дейін iOS 8-де бар және Apple қатесі сияқты иіс.
қосылды автор Eric Chen, көзі
@AhsanEbrahim, кері қимыл басталғанда, viewWillAppear ағымдағы көріністің артында көрінеді. Бұл кодының қисынына қасақана әкелуі мүмкін, себебі ағымдағы көрініс әлі де белсенді болып табылады. Сіздің апатыңыздың себебі болуы мүмкін.
қосылды автор phatmann, көзі
Мен неге екенін білмеймін, бірақ менің қолданбамдағы кейбір көрінбейтін себептер бойынша бақылау контроллері осы кері қимылда құлап кетті .. бұл мені осыдан бұрын сақтауға мүмкіндік бермегендіктен, осы кодты пайдаланып өшірдім. +1
қосылды автор Ahsan Ebrahim, көзі
enabled yes/no жолдары қажет емес пе? gestureRecognizerShouldBegin дегеннен NO сөзін қайтарасыз, ол жеткілікті емес пе?
қосылды автор ToolmakerSteve, көзі
Рахмет, жұмыс істеген жалғыз нәрсе.
қосылды автор Ben, көзі
Бұл iOS9-да (жылдам) жұмыс істейтінін растаймын.
қосылды автор HixField, көзі

Just remove gesture recognizer from NavigationController. Work in iOS 8.

if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)])
    [self.navigationController.view removeGestureRecognizer:self.navigationController.interactivePopGestureRecognizer];
26
қосылды
Сондай-ақ, iOS 10-да жұмыс істейді, бұл жауапты қабылдауы керек. Айтпақшы, оны қайта қосқыңыз келсе, [self.navigationController.view addGestureRecognizer: self.navigationController.interactivePo & zwnj; pGestureRecognizer] бір жерде жасаңыз.
қосылды автор ooops, көзі
iOS 8 және 9-да жұмыс істейтін жалғыз шешім
қосылды автор Kappe, көзі

IOS 8 нұсқасы бойынша қабылданған жауап енді жұмыс істемейді. Мен негізгі ойын экранынан қимылдан бас тарту үшін скриптті тоқтатуға тура келді, осылайша оны іске асырдым:

- (void)viewDidAppear:(BOOL)animated
{
     [super viewDidAppear:animated];

if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
    self.navigationController.interactivePopGestureRecognizer.delegate = self;
    }
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
    self.navigationController.interactivePopGestureRecognizer.delegate = nil;
    }

}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
     return NO;
}
21
қосылды
Бұл iOS8-мен жұмыс істеп тұрса да, * .delegate = self; көрсетілім: id > үйлесімді емес түрдегі 'ViewController * const __strong' түріндегі тағайындау
қосылды автор David Douglas, көзі
Қабылданған жауапты CallWillLayoutSubviews түрінде қоңырау шалу арқылы жартылай жұмыс істеуге қол жеткізді. Дегенмен, айналдыру бет қайтадан 'viewDidLoad' деп шақырды, сондықтан жоғарыда айтылған жауапыма қайта оралды
қосылды автор Charlie Seligman, көзі
@DavidDouglas: ескертуден құтылу үшін интерфейске қосуыңыз керек
қосылды автор primehalo, көзі
lookWillDisappear viewDidAppear viewDidAppear ішіндегі nil ішіндегі тазарту орнына Джек жауапына сәйкес, қауіпсіз болуы мүмкін (көп жағдайларда дұрыс) > Сақталған мәнге қалпына келтіріңіз.
қосылды автор ToolmakerSteve, көзі
IOS8 бойынша қабылданған жауап әлі де күткендей жұмыс істейді. Сіз басқа бір нәрсе істеп жатырсыз.
қосылды автор Alexandre G, көзі
@DavidDouglas: ескертуді осы кодпен жоюға болады: __weak __typeof (self) theSafeSelf = self? Содан кейін өкілетті СafeSelf-ге қойыңыз.
қосылды автор lifjoy, көзі
Бұл дұрыс жауап! Рахмет!
қосылды автор juancazalla, көзі

Мен Twan-тің жауаптарын аздап тазарттым, өйткені:

  1. көрініс контроллері басқа қимылдарды тану үшін делегат ретінде орнатылуы мүмкін
  2. nil делегесін орнату түбірлік көрініс контроллеріне оралғанда және басқа жерде шарлаудан бұрын жүгіртпе қимыл жасау кезінде асып кететін мәселелерге әкеледі.

Келесі мысал iOS 7 нұсқасын қабылдайды:

{
    id savedGestureRecognizerDelegate;
}

- (void)viewWillAppear:(BOOL)animated
{
    savedGestureRecognizerDelegate = self.navigationController.interactivePopGestureRecognizer.delegate;
    self.navigationController.interactivePopGestureRecognizer.delegate = self;
}

- (void)viewWillDisappear:(BOOL)animated
{
    self.navigationController.interactivePopGestureRecognizer.delegate = savedGestureRecognizerDelegate;
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    if (gestureRecognizer == self.navigationController.interactivePopGestureRecognizer) {
        return NO;
    }
   //add whatever logic you would otherwise have
    return YES;
}
17
қосылды

EDIT

Арнайы шарлау реттеушілері үшін таңбалау функциясын басқарғыңыз келсе SwipeBack пайдалануды қарастырыңыз.

Бұл жағдайда navigationController.swipeBackEnabled = NO параметрін орната аласыз.

Мысалға:

#import 

- (void)viewWillAppear:(BOOL)animated
{
    navigationController.swipeBackEnabled = NO;
}

Ол CocoaPods арқылы орнатуға болады.

pod 'SwipeBack', '~> 1.0'

Түсіндірмегендігіме көңіл бөлемін.

6
қосылды
Бұдан артық рұқсат етілмеген свитерді қолдануға болады. iOS8?
қосылды автор Matt, көзі
@devxoul Кешіріңіз! Менің ойымша, біраз уақыттан бұрын оқығанымның арқасында, су тасқынынан рұқсат етілмеді деп ойладым. Алайда, мен бұл туралы айтқан ештеңе таба алмаймын. Мен дұрыс емес деп ойлаймын.
қосылды автор Matt, көзі
Мен бұл липті қолдандым және ол кейбір қателіктермен бірге келеді. FB-тің істегісі сияқты!
қосылды автор João Nunes, көзі
Мен қысқа жауап үшін кешірім сұраймын, мен жауапты тек қосымша ақпаратпен редакцияладым: «арнайы навигациялық реттегіштер үшін пайдалы». Рахмет!
қосылды автор devxoul, көзі
@Матт, Өкінішке орай, сіз айтып отырған нәрсені түсінбеймін. Сіз маған «~ рұқсат етілмеген, iOS 8» деп түсіндіре аласыз ба? « білдіреді? Рахмет!
қосылды автор devxoul, көзі
@ André, SwipeBack жергілікті (жүйелік) қимыл танғышпен ойнайды. Өзіңіздің ішкі свипедкалық қаңылтырды онымен қоса басқара аласыз :)
қосылды автор devxoul, көзі
Оның үстіне, сіздің жобаңыздың жалғыз мақсаты - әдепкі жүйе жұмыс істемей тұрған кезде, қимылдың қимылын қолмен қосу, сол кезде жүйе қалыңдығын өшіруді сұрайды, сондықтан да self.navigationController.swipeBackEnabled = NO Мен бұл кітапхананың сауытын кері қотаруды өшіретініне сенімдімін, бірақ жүйенің біреуі әлі де қосылады.
қосылды автор user2629998, көзі
Сізбен байланысқан жобаны насихаттаған кезде, сіз онымен адалдығыңызды жариялауыңыз керек.
қосылды автор user2629998, көзі

iOS 10 және одан кейінгі нұсқаларында жұмыс істейді:

- (void)viewWillAppear:(BOOL)animated {
    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
        self.navigationController.interactivePopGestureRecognizer.enabled = NO;
    }

}

ол viewDidLoad() әдісі бойынша жұмыс істемейді.

5
қосылды

Swift үшін:

navigationController!.interactivePopGestureRecognizer!.enabled = false
4
қосылды
Бұл жұмыс күшінің қайта ашылуының орнына қосымша тізбекті пайдалануды ұсынамын. мысалы, self.navigationController? interactivePopGestureRecognizer? & zwnj; isEnabled = false
қосылды автор Womble, көзі

Оны root vc ішінде орнатыңыз:

-(void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:YES];
    self.navigationController.interactivePopGestureRecognizer.enabled = NO;

}

-(void)viewDidDisappear:(BOOL)animated{
    [super viewDidDisappear:YES];
    self.navigationController.interactivePopGestureRecognizer.enabled = YES;
}
4
қосылды

Осы шешімдердің бәрі Apple-дің қимылын тану құралын ұсынбайтын тәсілмен басқарады. Мен жақында досымның жақсы шешімі бар екенін айттым:

[navigationController.interactivePopGestureRecognizer requireGestureRecognizerToFail: myPanGestureRecognizer];

онда myPanGestureRecognizer - сіз қолданатын қимыл тану құралы, мысалы: мәзірін көрсетіңіз. Осылайша, Apple компаниясының қаңылтыр тану құралы сізге жаңа навигациялық контроллерді жібергеннен кейін қайта оралмайды және сіздің телефоныңыз ұйқыға немесе ауыр жүктеме астына түссе, ерте түсуі мүмкін шапшаң кешігулерге сенуге болмайды.

Міне, осында қалдым, өйткені білемін, келесі жолы бұл туралы есіме түсірмеймін, содан кейін мұнда мәселе шешіледі.

2
қосылды
Бұл қабылданған жауап болуы керек!
қосылды автор Klaas, көзі

Бұл iOS 8 үшін viewDidLoad: ішінде жұмыс істейді:

  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
      self.navigationController.interactivePopGestureRecognizer.enabled = false;
  });

Көптеген мәселелерді dispatch_after арқылы жақсы шешуге болады.

Қарама, бұл шешімнің ықтимал қауіпті екенін ескеріңіз, бірақ өзіңіздің ақыл-ойыңызды пайдаланыңыз.

Жаңарту

IOS 8.1 кідірту уақыты 0,5 секунд болуы керек

IOS 9.3 жүйесінде ешқандай кідіріс қажет емес, бұл оны viewDidLoad ішіне орналастыру арқылы ғана жұмыс істейді:
(iOS 9.0-9.3-де жұмыс істейтін болса, TBD)

navigationController?.interactivePopGestureRecognizer?.enabled = false
2
қосылды
Құжаттарда көрсетілген UIKit инженерлері Бұл сипатты қимыл танғышын шығарып, оны басқа пайдаланушы әрекеттерінің интерфейсінің әрекеттерінің әрекеттеріне байланыстыру үшін пайдалана аласыз. Бұл осы қимылды ажырату туралы ештеңе айтпайды, сондықтан техникалық түрде бұл қате емес, әлі орындалмаған сұраныс сұрау.
қосылды автор Dannie P, көзі
@ToolmakerSteve бұл кешіктіруді пайдаланудың барлық нүктесі мынада: viewDidAppear секілді iOS 8 арқылы қоңырауларда жұмыс істемейді, бұл UIKit қатесіне ұқсайды. Бұл мәселені gif көрсетеді. Әрекет жұмысында viewWillAppear сөзін қолданыңыз. Біреудің кешігуін көргенде, бұл мүмкін қауіпті екенін біледі, сондықтан жеке ойлауды қолдану керек. Дегенмен бұл iOS 8-дегі жақсы және жылдам шешім.
қосылды автор Dannie P, көзі
@iChirag шын. 8.1 үшін сізге 0,5 секундтық кідіріс қажет екенін айттым
қосылды автор Dannie P, көзі
@kalperin жұмыс істеуге кепілдік бермейді, бірақ бұл біраз уақыт өте ыңғайлы шешім. Өз ойыңызды пайдаланыңыз.
қосылды автор Dannie P, көзі
Ол маған iOS 8.1 нұсқасынан үлкен нұсқасы бар жұмыс істейді :)
қосылды автор iChirag, көзі
Қимыл тану құралы көріністе қашан орнатылғанын білмейінше, оны өшіру үшін ерікті уақытты күту мүмкін немесе жұмыс істемеуі мүмкін.
қосылды автор kalperin, көзі
viewDidLoad және кешіктіру - қауіпті бағдарламалау тәжірибесі. Басталудың жаман әдеті. Кешіктіріп шыққан қоңыраулар басталмас бұрын пайдаланушы сканерлеуді бастаса не болады? Ұзақ уақытқа жеткілікті емес ұзақ уақытқа кепілдік берілетін қауіпсіз уақыт жоқ. Міне, сондықтан сіздің жауаптарыңыз бұрыннан бері берілген басқа жауаптар кодты viewDidAppear ішінде орналастыруды ұсынады. Бұл барлық нәрсе орнатылғанын қамтамасыз етеді. Еркін кідірістерді ойлап таппаңыз; Apple компаниясының қоңыраулар тізбегін жоспарланғандай қолданыңыз.
қосылды автор ToolmakerSteve, көзі

Берілген жауаптардың ешқайсысы бұл мәселені шешуге көмектесті. Жауапты мына жерде жариялау; біреу үшін пайдалы болуы мүмкін

Viewcontroller сіздің жаһандық айнымалы ретінде private var popGesture: UIGestureRecognizer? . Содан кейін viewDidAppear және viewWillDisappear әдістерін қолданыңыз

override func viewDidAppear(animated: Bool) {

    super.viewDidAppear(animated)

    if self.navigationController!.respondsToSelector(Selector("interactivePopGestureRecognizer")) {

        self.popGesture = navigationController!.interactivePopGestureRecognizer
        self.navigationController!.view.removeGestureRecognizer(navigationController!.interactivePopGestureRecognizer!)
    }
}


override func viewWillDisappear(animated: Bool) {

    super.viewWillDisappear(animated)

    if self.popGesture != nil {
        navigationController!.view.addGestureRecognizer(self.popGesture!)
    }
}

Бұл iOS v8.x тармағынан артқа айналдыруды өшіреді

2
қосылды
Екінші жағынан, бұл Джекке қарағанда қарапайым көрінеді, сондықтан оның маңызды емес болуы мүмкін. Менің шешімімді ұнатамын, өйткені сыныпты делегат деп жариялауға және кодты интерактивтіPopGestureRecognizer.delegate -қа айналдыруға тура келмейді.
қосылды автор ToolmakerSteve, көзі
Мен бұл жағдайдың қандай жағдайда жұмыс істейтінін елестетуге тырысамын, бірақ Джек болмайды. Басқа жауаптардың барлығын қолданып көрдіңіз дейді: Джек-ді сынап көргенде не болды?
қосылды автор ToolmakerSteve, көзі
BTW, кодты жеңілдетуге болады. if (.. respondsToSelector .. ) келесі жолда popGesture функциясын танушыге немесе нөлге орнатады, содан кейін оның мәнін пайдаланыңыз: if (self.popGesture! = Nil) self.navigationController. removeGestureRecognizer (self.popGesture) .
қосылды автор ToolmakerSteve, көзі

Менің әдісім. Барлығын басқаратын бір қимыл танушы:

class DisabledGestureViewController: UIViewController: UIGestureRecognizerDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()
        navigationController!.interactivePopGestureRecognizer!.delegate = self
    }

    func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
       //Prevent going back to the previous view
        return !(navigationController!.topViewController is DisabledGestureViewController)
    }
}

Important: don't reset the delegate anywhere in the navigation stack: navigationController!.interactivePopGestureRecognizer!.delegate = nil

2
қосылды

Бұл Swift 3 жолында

Мен үшін жұмыс істейді

    self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
2
қосылды

Swift 4 үшін бұл жұмыс істейді:

class MyViewController: UIViewController, UIGestureRecognizerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        self.navigationController!.interactivePopGestureRecognizer!.gesture.delegate = self
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(true)

        self.navigationController!.interactivePopGestureRecognizer!.gesture.isEnabled = true
    }

}
1
қосылды
Құжатталмаған мінез-құлыққа әкелетін интерактивті поп-қимыл туралы делегатты елемеуіңіз керек
қосылды автор Josh Bernfeld, көзі