恢复IPHONE时显示未能恢复IPHONE发生错误21,是啥原因?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了恢复IPHONE时显示未能恢复IPHONE发生错误21,是啥原因?相关的知识,希望对你有一定的参考价值。

问题表现:在使用iTunes恢复iPhone固件时,可能会出现未知错误21,此时iTunes会提示“发生未知错误21”,没法降级成功。
造成原因:没有真正进入DFU模式(黑屏状态)。
解决办法:正确进入DFU模式。
1.把设备连接到PC;
2.关闭设备;
3.同时按住Home键和电源键十秒(要精确计时哦)
4.松开电源键,继续按住Home键,直到在电脑上看到识别到DFU状态下的USB设备时就进入到DFU模式了;
5.在经过数秒之后iTunes就可以检测并识别到处于DFU模式下的设备了;

如果在设备上出现的是“usb连接iTunes”的画面,那么设备是处于恢复模式下,而不是DFU模式。安装电源键10秒,退出恢复模式,再次进行上述操作。
参考技术A 固件下错了。你把你手机型号和model号告诉我,我给你固件连接追问

MODE号是什么?

追答

机身后面,model A1xxx

追问

4 A1332

追答

型号呢?

追问

IPHONE4

追答

我擦,型号。设置,通用,关于手机。

追问

手机不能开机还有别的地方可以看到型号吗?

追答

手机盒

追问

早就不知道扔哪个角落落里去了o(╯□╰)o

追答

那是国行还是?

参考技术B 你是不是恢复的不是最新版本。要下载最新版本恢复才可以追问

是最新版本的

追答

那就在刷一次

我ipad前几天也是这种问题,现在开不了机么?能开机的话恢复设置再刷

iPhone 6+ 状态恢复与主拆分视图中的标签栏

【中文标题】iPhone 6+ 状态恢复与主拆分视图中的标签栏【英文标题】:iPhone 6+ state restoration with tab bar in master split view 【发布时间】:2015-02-24 13:00:32 【问题描述】:

我在 iPhone 6+ 中支持状态恢复时遇到问题。

这是我的层次结构:

问题是当状态恢复发生在纵向时,然后在稍后点,在横向时进行状态解码尝试。

说明: 在竖屏模式下,主视图只有TabBar(实际上不存在详细视图),所以它被推入TabBar导航的控制器中。

然后,稍后,当应用程序尝试执行横向状态恢复时,我的详细信息视图被推送到主导航控制器上(当它应该是详细信息时)。

由于自定义层次结构,我已经相应地实现了 UISplitViewControllerDelegate 方法,并且它们工作正常。 UISplitViewControllerDelegate 方法还确保状态恢复在以下情况下有效:

Landscape -> Landscape
Landscape -> Portrait
 Portrait -> Portrait

不起作用的是:纵向 -> 横向,因为正如我所说,在未折叠状态时不会调用委托方法,因此视图层次结构不知道如何从主视图中拆分细节并将其嵌入到细节中导航控制器。

【问题讨论】:

UISplitViewController state restoration in iOS 8的可能重复 【参考方案1】:

到目前为止,我已经解决了这个问题:在 viewWillAppear 中,所有细节控制器都是从标签栏的导航控制器中删除的。 存储状态时,会保存设备方向和 SplitViewController.viewControllers(对我来说,它不会像在 iOS7 上那样自动存储它们)。

- (void) encodeRestorableStateWithCoder:(NSCoder*)coder

    [super encodeRestorableStateWithCoder:coder];
    [coder encodeObject:self.viewControllers forKey:@"viewControllers"];
    [coder encodeInteger:[UIApplication sharedApplication].statusBarOrientation forKey:@"orientation"];


- (void) decodeRestorableStateWithCoder:(NSCoder*)coder

    [super decodeRestorableStateWithCoder:coder];
    NSArray* viewControllers = [coder decodeObjectForKey:@"viewControllers"];
    if (viewControllers.count > 0)
    
        self.viewControllers = viewControllers;
    
    restoredOrientation = (UIInterfaceOrientation) [coder decodeIntegerForKey:@"orientation"];

这里是 viewWillAppear 的实现:

- (void) viewWillAppear:(BOOL)animated

    [super viewWillAppear:animated];

    // iPhone6+: if state restoration happened while in portrait orientation and app is launched while in landscape,
    // then all detail views should be cut from master view and split details view is set appropriately
    if (firstLoad &&
            [UIScreen mainScreen].scale > 2.9 && // assure it's iPhone 6+
            UIInterfaceOrientationIsPortrait(restoredOrientation) &&
            UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication.statusBarOrientation))
    
        UITabBarController* tbc = self.viewControllers[0];
        NSArray* detachedControllers = [tbc cutControllersFrom:DocumentViewController.class];
        if (detachedControllers.count > 0)
        
            UINavigationController* documentNavigation = [self.storyboard
                    instantiateViewControllerWithIdentifier:@"NavigationController"];
            documentNavigation.viewControllers = detachedControllers;
            self.viewControllers = @[ self.viewControllers[0], documentNavigation ];
        
        else // place some default no-selection controller in detail
        
            UINavigationController* noSelectionNavigation = [self.storyboard
                    instantiateViewControllerWithIdentifier:@"NoSelectionSID"];
            self.viewControllers = @[ self.viewControllers.firstObject, noSelectionNavigation ];
        
    
    firstLoad = NO;

其中 cutControllersFrom 方法是 UITabBarController 上的一个类别:

- (NSArray*) cutControllersFrom:(Class)controllerClass

    NSArray* ret;
    for (UIViewController* vc in self.viewControllers)
    
        if (![vc isKindOfClass:UINavigationController.class])
        
            continue;
        

        UINavigationController* nc = (UINavigationController*) vc;
        NSArray* removed = [nc cutFrom:controllerClass];
        if (vc == self.selectedViewController)
        
            ret = removed;
        
    

    return ret;

调用 cutFrom: 方法,该方法是 UINavigationController 上的一个类别:

- (NSArray*) cutFrom:(Class)controllerClass

    NSMutableArray* toRemove = [NSMutableArray array];
    BOOL startRemoving = NO;
    UIViewController* endingViewController;

    for (NSUInteger i = 0; i < self.viewControllers.count; i++)
    
        UIViewController* vc = self.viewControllers[i];
        if ([vc isKindOfClass:controllerClass])
        
            startRemoving = YES;
            endingViewController = self.viewControllers[i - 1];
        

        if (startRemoving)
        
            [toRemove addObject:vc];
        
    
    if (endingViewController)
    
        [self popToViewController:endingViewController animated:NO];
    

    return toRemove;

【讨论】:

似乎您别无选择,并且在弄清楚这一切方面做得很好。如果您准备改变方法,一个选择是不使用标签栏并移至侧边栏。我在我当前的应用程序中执行此操作,其中一个侧面菜单允许我在多个拆分视图控制器之间切换。好消息是每个拆分视图都是独立的,并且具有用于主视图和详细信息的导航控制器,因此更简单。所以你的标签栏可以变成侧边栏菜单,它可以让你在 4 个拆分视图控制器之间切换:每个 ControllerX 一个。只是一个想法。 啊,是的,侧边菜单是个不错的主意。目前,我必须坚持使用 TabBar,但为了将来参考,记住它会非常好。【参考方案2】:

不确定我是否完全理解您的问题,因为在 iPhone 6+ 上从纵向到横向应该从折叠状态变为拆分状态,所以应该调用这个委托:

- (UIViewController *)splitViewController:(UISplitViewController *)splitViewController separateSecondaryViewControllerFromPrimaryViewController:(UIViewController *)primaryViewController

但是您似乎暗示这没有被调用,并且在 Portrait 中它处于非折叠状态?

在我使用的拆分视图控制器上,我发现最好让控制器自己解决问题。如果您将 showDetail segues 用于详细视图,它应该为您处理拆分。您是否确保使用 showDetail segues 从 Controller1->4 推送 DetailController 而不是 show segues?

因此假设您对细节使用了正确的 segues,只需在代表中返回 nil 以让拆分视图控制器自行排序?

【讨论】:

如果master是UINavigationController,SplitViewController可以解决问题,但在我的情况下,它是UITabBarController,它有自己的UINavigationControllers,这是UISplitViewController不知道如何解决的问题,所以我不得不这样做通过实现 UISplitViewControllerDelegate 方法手动实现。 好的。也许您需要在拆分视图控制器中实现- splitViewController:showDetailViewController:sender: 以让您将细节放在正确的位置? 我已经在实现该方法,但在状态恢复时并未调用该方法。【参考方案3】:

当状态保留为纵向时,恢复标识符路径将不同于预期的横向,这是使用拆分视图控制器时的默认初始状态。即细节在主要而不是次要中。因此,当应用程序重新启动时,它将无法重新创建以前的层次结构,并将诉诸于在单独的配置中重新创建这些控制器(About the UI Restoration Process 中的第 4 步),这意味着不会调用 separateSecondaryViewControllerFromPrimaryViewController,因为这些控件已经分开了。您可能会注意到在启动时创建了两个细节控制器,第一个可能设置了默认属性的控制器被丢弃了,或者您甚至可能会看到两个细节控制器被推送到导航堆栈上。我不确定你为什么设法让 Portrait->Portrait 工作,因为它应该遇到同样的问题。

要解决这些问题,您可以实现application:viewControllerWithRestorationIdentifierPath:coder,它(在 Portrait->Landscape 场景中)将使用纵向层次结构调用,您可以通过在从故事板。在它恢复视图控制器后,它将检测到从保留的纵向到当前横向的方向发生了变化,并且将调用separateSecondaryViewControllerFromPrimaryViewController。但是,我还不确定这是正确的方法,因为拆分控制器中有一些未保存的状态,例如_preservedDetailController(这就是拆分视图控制器如何在一个之前的崩溃)所以如果在方向更改后重新启动,我们有可能只是丢弃状态,我还不是 100% 确定。

这是我的测试应用程序中的一个示例:

- (UIViewController *)application:(UIApplication *)application viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder
    if([identifierComponents.lastObject isEqualToString:@"DetailViewController"])
        UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
        UINavigationController *secondaryNavigationController = splitViewController.viewControllers.lastObject;;
        DetailViewController *detail = (DetailViewController *)secondaryNavigationController.viewControllers.firstObject;
        NSURL *objectURI = [coder decodeObjectForKey:@"object"];
        if(objectURI)
            NSManagedObjectContext *moc = self.persistentContainer.viewContext;
            NSManagedObjectID *objectID = [moc.persistentStoreCoordinator managedObjectIDForURIRepresentation:objectURI];
            NSManagedObject *object = [moc objectWithID:objectID];
            detail.object = object;
        
        // attempt to workaround a bug for _preservedDetailController not being restored.
        [splitViewController _willShowCollapsedDetailViewController:secondaryNavigationController inTargetController:nil];
        return detail;
    
    else if([identifierComponents.lastObject isEqualToString:@"DetailNavigationController"])
        UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
        UINavigationController *secondaryNavigationController = splitViewController.viewControllers.lastObject;
        return secondaryNavigationController;
    
    return nil;

【讨论】:

以上是关于恢复IPHONE时显示未能恢复IPHONE发生错误21,是啥原因?的主要内容,如果未能解决你的问题,请参考以下文章

当 iPhone 从备份中恢复时,钥匙串会发生啥?

iPhone 在连接到 Mac 时显示问号(代替其图标)

在触摸时显示 iphone 视频控件

恢复应用程序状态时显示不确定的活动指示器?

在 iPhone 上隐藏 UITabBar 时显示黑条

iPhone 6+ 状态恢复与主拆分视图中的标签栏