aromajoin / material-showcase-ios

✨ An elegant way to guide your beloved users in iOS apps - Material Showcase.
https://aromajoin.com/
Other
363 stars 128 forks source link

Found Nil #132

Closed kozmotronik closed 4 years ago

kozmotronik commented 4 years ago

This is the implementation code:

func showCaseDidDismiss(showcase: MaterialShowcase, didTapTarget: Bool) {
    print("showCaseDidDismiss")
    asamaIzleyici.sonrakiAsama()
    if !araclar.asistanTamamlandi, let asama = araclar.asistanAsamasi {
        if asama.elementsEqual("BölgeEkle") {
            DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(700), execute: {
                print("Bölge ekleme aşaması gösterilecek...")
                let asbe = MaterialShowcase()
                asbe.setTargetView(barButtonItem: self.tEkle)
                asbe.primaryText = "Bir bölge ekleyin"
                asbe.secondaryText = "Yeni bölgelerinizi bu tuşa basarak ekleyin"
                asbe.backgroundViewType = .circle
                asbe.delegate = self
                asbe.show(animated: true, hasShadow: false, hasSkipButton: false, completion: nil)
            })
        }
    }
}

When it executes I get this error:

Bölge ekleme aşaması gösterilecek... Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file /Users/teknimer/Desktop/himTEC_Kontrol/himTEC Kontrol/himTEC Kontrol/Asistan/MaterialShowcase.swift, line 381 2020-09-01 11:13:42.582497+0300 himTEC Kontrol[3630:73790] Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file /Users/teknimer/Desktop/himTEC_Kontrol/himTEC Kontrol/himTEC Kontrol/Asistan/MaterialShowcase.swift, line 381 (lldb)

It refers to this function in MaterialShowcase.swift file:

private func getDefaultBackgroundRadius() -> CGFloat {
    var radius: CGFloat = 0.0
    if UIDevice.current.userInterfaceIdiom == .pad {
      radius = 300.0
    } else {
      // In the line below it gives the error.
      radius = getOuterCircleRadius(center: center, textBounds: instructionView.frame, targetBounds: targetRippleView.frame)
    }
    return radius
  }
kozmotronik commented 4 years ago

I have been trying the implementation code by changing the asbe.backgroundViewType = .circle to asbe.backgroundViewType = .full. It works in full mode but crashes in circle mode.

kozmotronik commented 4 years ago

After a little debugging process I have found a bug guys. I don't know if anyone has implemented this version and get the same error. But in my case I added the MaterialShowcase library manually not thorough any library manager like cocoapods. So I detected that when getDefaultBackgroundRadius() method is called the instructionView hasn't been initialized. I don't know if it is the best solution but I modified the related methods as followings:

  func initViews() {
    let center = calculateCenter(at: targetView, to: containerView)
    addTargetRipple(at: center)
    addTargetHolder(at: center)
    // if color is not UIColor.clear, then add the target snapshot
    if targetHolderColor != .clear {
      addTarget(at: center)
    }
    // ***Here I instantiated the instructionView which is the cause of this bug, before calling the addBackground().***
    instructionView = MaterialShowcaseInstructionView()

    //In iPad version InstructionView was add to backgroundView and in iPhone version InstructionView was add to self view
    addBackground()

    addInstructionView(at: center)
    instructionView.layoutIfNeeded()

    // Disable subview interaction to let users click to general view only
    subviews.forEach({$0.isUserInteractionEnabled = false})

    if isTapRecognizerForTargetView {
      //Add gesture recognizer for targetCopyView
      hiddenTargetHolderView.addGestureRecognizer(tapGestureRecoganizer())
      hiddenTargetHolderView.isUserInteractionEnabled = true
    } else {
      // Add gesture recognizer for both container and its subview
      addGestureRecognizer(tapGestureRecoganizer())
      hiddenTargetHolderView.addGestureRecognizer(tapGestureRecoganizer())
      hiddenTargetHolderView.isUserInteractionEnabled = true
    }

  }

and then:

  /// Configures and adds primary label view
  private func addInstructionView(at center: CGPoint) {
// *** Commented out the instantiation below ***
//    instructionView = MaterialShowcaseInstructionView()

    instructionView.primaryTextAlignment = primaryTextAlignment
    instructionView.primaryTextFont = primaryTextFont
    instructionView.primaryTextSize = primaryTextSize
    instructionView.primaryTextColor = primaryTextColor
    instructionView.primaryText = primaryText

    instructionView.secondaryTextAlignment = secondaryTextAlignment
    instructionView.secondaryTextFont = secondaryTextFont
    instructionView.secondaryTextSize = secondaryTextSize
    instructionView.secondaryTextColor = secondaryTextColor
    instructionView.secondaryText = secondaryText

    // Calculate x position
    var xPosition = LABEL_MARGIN

    // Calculate y position
    var yPosition: CGFloat!

    // Calculate instructionView width
    var width : CGFloat

    if UIDevice.current.userInterfaceIdiom == .pad {
      backgroundView.addSubview(instructionView)
    } else {
      addSubview(instructionView)
    }

    instructionView.layoutIfNeeded()

    if UIDevice.current.userInterfaceIdiom == .pad {
      width = backgroundView.frame.width - 2 * xPosition

      if backgroundView.frame.origin.x < 0 {
        xPosition = abs(backgroundView.frame.origin.x) + xPosition
      } else if (backgroundView.frame.origin.x + backgroundView.frame.size.width >
        UIScreen.main.bounds.width) {
        xPosition = 2 * LABEL_MARGIN
        width = backgroundView.frame.size.width - (backgroundView.frame.maxX - UIScreen.main.bounds.width) - xPosition - LABEL_MARGIN
      }
      if xPosition + width > backgroundView.frame.size.width {
        width = width - CGFloat(xPosition/2)
      }

      //Updates horizontal parameters
      instructionView.frame = CGRect(x: xPosition,
                                   y: instructionView.frame.origin.y,
                                   width: width,
                                   height: 0)
      instructionView.layoutIfNeeded()

      if getTargetPosition(target: targetView, container: containerView) == .above {
        yPosition = (backgroundView.frame.size.height/2) + TEXT_CENTER_OFFSET
      } else {
        yPosition = (backgroundView.frame.size.height/2) - TEXT_CENTER_OFFSET - instructionView.frame.height
      }
    } else {
      width = containerView.frame.size.width - (xPosition*2)
      if backgroundView.frame.center.x - targetHolderRadius < 0 {
        width = width - abs(backgroundView.frame.origin.x)
      } else if (backgroundView.frame.center.x + targetHolderRadius >
        UIScreen.main.bounds.width) {
        width = width - abs(backgroundView.frame.origin.x)
        xPosition = xPosition + abs(backgroundView.frame.origin.x)
      }

      //Updates horizontal parameters
      instructionView.frame = CGRect(x: xPosition,
                                   y: instructionView.frame.origin.y,
                                   width: width ,
                                   height: 0)
      instructionView.layoutIfNeeded()

      if getTargetPosition(target: targetView, container: containerView) == .above {
        yPosition = center.y + TARGET_PADDING +  (targetView.bounds.height / 2 > targetHolderRadius ? targetView.bounds.height / 2 : targetHolderRadius)
      } else {
        yPosition = center.y - TEXT_CENTER_OFFSET - max(instructionView.frame.height,LABEL_DEFAULT_HEIGHT * 2)
      }

    }

    instructionView.frame = CGRect(x: xPosition,
                                   y: yPosition,
                                   width: width ,
                                   height: 0)
  }

After this modification I got it worked.

quangctkm9207 commented 4 years ago

I am sorry for my late response. Please update to latest version 0.7.2 which has a hot fix for this. About the UI, if the text is not in the correct position, please set the "showcase.backgroundRadius".

zeusent commented 4 years ago

Version 0.7.2 installed via SPM still has the same bug in it. Is it maybe a problem with the tag pointing to the wrong commit?