9 Notes Desember 2020

 1. Add Filter Parameters For Url String

var url = URLComponents(string: "http://myapi.com/api/customer")!
print(url)  // http://myapi.com/api/customer

url.queryItems = [
   URLQueryItem(name: "filter", value: "{\"where\":{\"name\":\"myName\"}}")
]

print(url) // http://myapi.com/api/customer?filter=%7B%22where%22:%7B%22name%22:%22myName%22%7D%7D


2. Navigation back to root (and Chnage  root)

- use normal change

self.view.window?.rootViewController = UINavigationController(rootViewController: ViewController())

- use route for navigation

protocol IRouter {
    var module: UIViewController? { get }
}

extension UIViewController {
    
    func navigate(module: IRouter, completion: ((_ module: UIViewController) -> Void)? = nil) {
        guard let _module = module.module else { fatalError() }

          if _module is UITabBarController {
              UIApplication.shared.delegate?.window??.setRootViewController(_module, options: .init(direction: .fade, style: .easeInOut))
          } else {
              UIApplication.shared.delegate?.window??.setRootViewController(
                  UINavigationController(rootViewController: _module),
                  options: .init(
                      direction: .fade,
                      style: .easeInOut
                  )
              )
          }
          completion?(_module)  
        
    }
   
}

public extension UIWindow {
    /// Transition Options
    struct TransitionOptions {
        /// Curve of animation
        ///
        /// - linear: linear
        /// - easeIn: ease in
        /// - easeOut: ease out
        /// - easeInOut: ease in - ease out
        public enum Curve {
            case linear
            case easeIn
            case easeOut
            case easeInOut
            
            /// Return the media timing function associated with curve
            internal var function: CAMediaTimingFunction {
                let key: String!
                switch self {
                case .linear: key = CAMediaTimingFunctionName.linear.rawValue
                case .easeIn: key = CAMediaTimingFunctionName.easeIn.rawValue
                case .easeOut: key = CAMediaTimingFunctionName.easeOut.rawValue
                case .easeInOut: key = CAMediaTimingFunctionName.easeInEaseOut.rawValue
                }
                return CAMediaTimingFunction(name: CAMediaTimingFunctionName(rawValue: key!))
            }
        }
        
        /// Direction of the animation
        ///
        /// - fade: fade to new controller
        /// - toTop: slide from bottom to top
        /// - toBottom: slide from top to bottom
        /// - toLeft: pop to left
        /// - toRight: push to right
        public enum Direction {
            case fade
            case toTop
            case toBottom
            case toLeft
            case toRight
            
            /// Return the associated transition
            ///
            /// - Returns: transition
            internal func transition() -> CATransition {
                let transition = CATransition()
                transition.type = CATransitionType.push
                switch self {
                case .fade:
                    transition.type = CATransitionType.fade
                    transition.subtype = nil
                case .toLeft:
                    transition.subtype = CATransitionSubtype.fromLeft
                case .toRight:
                    transition.subtype = CATransitionSubtype.fromRight
                case .toTop:
                    transition.subtype = CATransitionSubtype.fromTop
                case .toBottom:
                    transition.subtype = CATransitionSubtype.fromBottom
                }
                return transition
            }
        }
        
        /// Background of the transition
        ///
        /// - solidColor: solid color
        /// - customView: custom view
        public enum Background {
            case solidColor(_: UIColor)
            case customView(_: UIView)
        }
        
        /// Duration of the animation (default is 0.20s)
        public var duration: TimeInterval = 0.20
        
        /// Direction of the transition (default is `toRight`)
        public var direction: TransitionOptions.Direction = .toRight
        
        /// Style of the transition (default is `linear`)
        public var style: TransitionOptions.Curve = .linear
        
        /// Background of the transition (default is `nil`)
        public var background: TransitionOptions.Background?
        
        /// Initialize a new options object with given direction and curve
        ///
        /// - Parameters:
        ///   - direction: direction
        ///   - style: style
        public init(direction: TransitionOptions.Direction = .toRight, style: TransitionOptions.Curve = .linear) {
            self.direction = direction
            self.style = style
        }
        
        public init() {}
        
        /// Return the animation to perform for given options object
        internal var animation: CATransition {
            let transition = self.direction.transition()
            transition.duration = self.duration
            transition.timingFunction = self.style.function
            return transition
        }
    }
    
    /// Change the root view controller of the window
    ///
    /// - Parameters:
    ///   - controller: controller to set
    ///   - options: options of the transition
    func setRootViewController(_ controller: UIViewController, options: TransitionOptions = TransitionOptions()) {
        var transitionWnd: UIWindow?
        if let background = options.background {
            transitionWnd = UIWindow(frame: UIScreen.main.bounds)
            switch background {
            case .customView(let view):
                transitionWnd?.rootViewController = UIViewController.newController(withView: view, frame: transitionWnd!.bounds)
            case .solidColor(let color):
                transitionWnd?.backgroundColor = color
            }
            transitionWnd?.makeKeyAndVisible()
        }
        
        // Make animation
        self.layer.add(options.animation, forKey: kCATransition)
        self.rootViewController = controller
        self.makeKeyAndVisible()
        
        if let wnd = transitionWnd {
            DispatchQueue.main.asyncAfter(deadline: .now() + 1 + options.duration) {
                wnd.removeFromSuperview()
            }
        }
    }
}


3. Error Jenkins ITMS-90206

Xcode 8 and lastest

Looks like this has been renamed to Always Embed Swift Standard Libraries in Xcode So, for the app:

Always Embed Swift Standard Libraries: YES

and for the extension:

Always Embed Swift Standard Libraries: NO

source: https://stackoverflow.com/questions/25777958/validation-error-invalid-bundle-the-bundle-at-contains-disallowed-file-fr?lq=1


4. Reject Apple ITMS-90433

Set in Project  and Target  build option 

Always Embed Swift Standard Libraries: YES


Source: 
https://medium.com/@tomlarge/apple-itms-90424-invalid-swift-support-ios-d8fd0d446d6c

5. Crash while running scroll to bottom




In my case, I  fixing with remove (- 1)

 func scrollToBottom() {
        DispatchQueue.main.async {
            if self.showCount > 1 {
                let row = self.showCount - 1
                let indexPath = IndexPath(row: row, section: 1)
                self.commentListTableView.scrollToRow(at: indexPath, at: .bottom, animated: true)
            }
        }
    }

to like this

 func scrollToBottom() {
        DispatchQueue.main.async {
            if self.showCount > 1 {
                let row = self.showCount 
                let indexPath = IndexPath(row: row, section: 1)
                self.commentListTableView.scrollToRow(at: indexPath, at: .bottom, animated: true)
            }
        }
    }

6.  Firebase Crashlytic cannot connect with a project

- The problem always show this prosses in firebase crashlytic, while running app.




To test this you can force a crash..

- after set fatalError() where you want  run your app and click on that button.(You app will crash here so it will be close)

- Now open app again(Do not run app. Just open it by taping on app icon)

Note: for testing crash don't running app use xcode, must running just in simulator or running on IPhone


source: https://stackoverflow.com/a/64366045/8366535


7. Error FirebaseCrashlytic 



I try to migrate fabric to  Crashlytic and have some bugs, by following instruction firebase but didn't work  so I get an answer from StackOverflow

this my solution, follow a step in firebase to fixing if not working you can use this

- Set Crashlytic 


- set  DSYM




// after set that you must running interminal

$ /Users/uerry/Backup/MyApp/MyApp_ios/myappmeios/Pods/FirebaseCrashlytics/upload-symbols -gsp /Users/uerry/Backup/MyApp/MyApp_ios/myappmeios/MyApp/Firebase/folder/GoogleService-Info.plist -p ios /Users/uerry/Library/Developer/Xcode/DerivedData/MyApp-bcqxgotqjcqzvpgrbcuhkalogezi/Build/Products/Production-iphoneos/MyApp.app.dSYM 


// if I split looks like this

// part 1 path file pods firebase crashlytic

/Users/uerry/Backup/MyApp/MyApp_ios/myappmeios/Pods/FirebaseCrashlytics/upload-symbols -gsp 

// part 2 path file google service
/Users/uerry/Backup/MyApp/MyApp_ios/myappmeios/MyApp/Firebase/folder/GoogleService-Info.plist -p ios
// part 3 path file dSYM
/Users/uerry/Library/Developer/Xcode/DerivedData/MyApp-bcqxgotqjcqzvpgrbcuhkalogezi/Build/Products/Production-iphoneos/MyApp.app.dSYM



this a best answer  I found in stackoverflow

source: https://stackoverflow.com/a/62063145/8366535

8. Upload dSYM files automatically 

I have a bug again in firebase, dSYMs not auto upload to firebase still use terminal
so I add new run script 

/path/to/pods/directory/FirebaseCrashlytics/upload-symbols -gsp /path/to/GoogleService-Info.plist -p ios /path/to/dSYMs

In  my new script look like this, add "PATH_ENV" because I use multiple environments for firebase 
$PODS_ROOT/FirebaseCrashlytics/upload-symbols\" -gsp \"${SRCROOT}/myapp/Firebase/${PATH_ENV}/${FIREBASE}.plist\" -p ios \"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}\
source: https://medium.com/macoclock/get-started-with-firebase-crashlytics-2789b6ee2507


9. Round if after a comma is  just  "0"

   if you want after the comma there is only 0 for the round, look at this example below, this  was fixing my bug 😏  :

extension Double {
    func isInteger() -> Any {
        let check = floor(self) == self
        if check {
            return Int(self)
        } else {
            return self
        }
    }
}

let toInt: Double = 10.0
let stillDouble: Double = 9.12

print(toInt.isInteger) // 10
print(stillDouble.isInteger) // 9.12

my answer in stackOverflow : https://stackoverflow.com/a/65402900/8366535




No comments: