美文网首页
swift 有趣的swift

swift 有趣的swift

作者: 青椒辣不辣 | 来源:发表于2021-01-22 18:12 被阅读0次



    如果要初始化很多的子控件,这些控件的类别相同,正常的做法是创建一个命名一个,需要搞各种名字,复制来复制去,为避免这种麻烦,我们可以用下边的方式,就可以避免啦

    //方式一:不需要拿到对象
    ({
                let image = UIImage(named: "lg_circle_erweima")
                let imageView = UIImageView.init(image: image)
                addSubview(imageView)
                imageView.snp.makeConstraints { (make) in
                    make.centerX.equalToSuperview().offset(-50)
                    make.top.equalTo(actionImageView.snp.bottom).offset(15)
                    make.width.equalTo(18)
                    make.height.equalTo(18)
                }
    })()
    //方式二:需要拿到对象
    let actionImageView = ({ () -> UIImageView in
                let image = UIImage(named: "lg_circle_yaoqing")
                let imageView = UIImageView.init(image: image)
                addSubview(imageView)
                imageView.snp.makeConstraints { (make) in
                    make.centerX.equalToSuperview()
                    make.top.equalTo(bgView).offset(130)
                    make.width.equalTo(gl_kScreenWidth - 80)
                    make.height.equalTo(image!.gl_imageCalculationHeight(gl_kScreenWidth - 80))
                }
                return imageView
    })()
    
    //在OC中的写法
    UIImageView *myImageView = ({
            UIImageView *imageView = [[UIImageView alloc]init];
            imageView.image = [UIImage imageNamed:@"imagename"];
            [self addSubview:imageView];
            [imageView mas_makeConstraints:^(MASConstraintMaker *make) {
                make.edges.equalTo(self);
            }];
            imageView;
    });
    ({
            UIImageView *imageView = [[UIImageView alloc]init];
            imageView.image = [UIImage imageNamed:@"imagename"];
            [self addSubview:imageView];
            [imageView mas_makeConstraints:^(MASConstraintMaker *make) {
                make.edges.equalTo(self);
            }];
    });
    



    pragma mark - 区块注释

    image.png
    // swift 中的写法
    // MARK: delegate & datasource
    // FIXME: 添加标记2
    
    //OC 中的写法
    #pragma mark - delegate & datasource
    



    guard

    func fooGuard(x: Int?) {
        guard let _x = x where x > 0 else {
            // 变量不符合条件判断时,执行下面代码
            return
        }
        // 使用x
        _x.description
    }
    



    奇怪的写法一func functionPerson<T>(person: Person, getter: (Person) -> T){}

    class Person: NSObject{
        var personAge = 18
        
    }
    func functionPerson<T>(person: Person, getter: (Person) -> T) {
        print(getter(person))
        // 打印结果 --- 18
    }
    
    // 调用
    func go(){
        //swift自动为闭包提供参数名缩写功能
        //可以直接通过$0和$1等来表示闭包中的第一个第二个参数
        //并且对应的参数类型会根据函数类型来进行判断
        functionPerson(person: Person.init(), getter: { $0.personAge })
    }
    



    参数类型的传递

    想实现的效果是对于分页TableView网络请求的封装 ,使用的数组转模型HandyJSON
    研究这里的原因: 调用static func deserialize(from array: [Any]?) -> [Element?]? {}是用[遵循HandyJSON代理的类]类型调用的

    public extension Array where Element: HandyJSON {
        static func deserialize(from array: [Any]?) -> [Element?]? {
            return JSONDeserializer<Element>.deserializeModelArrayFrom(array: array)
        }
    }
    
    import UIKit
    import HandyJSON
    class GLBaseModel: NSObject , HandyJSON {
        required override init(){}
        var id:String?
        func mapping(mapper: HelpingMapper) {
            /*字段映射
            mapper.specify(property: &id, name: "customId")
            mapper <<<
                self.id <-- "customId"*/
        }
    }
    class lgss_circle_inviteListModel: GLBaseModel {
        var commission = ""// (number, optional): 收益佣金 ,
        var headIcon = ""   // (string, optional): 用户头像 ,
        var userName = ""   // (string, optional): 用户姓名
    }
    /// GET /circle/inviteList 邀请好友列表
    func lgss_circle_inviteList(target: GLBaseTableViewController) {
        lgss_pagingRequest(target: target, path: "circle/inviteList", type: lgss_circle_inviteListModel.self)
        
    }
    /// ***********************************************************************************************
    /// ***********************************************************************************************
    ///  ***********************************************************************************************
    /// GLBaseTableViewController分页请求数据
    func lgss_pagingRequest<T:GLBaseModel>(target : GLBaseTableViewController, path : String, type : T.Type){
        let parameter = ["pageSize":target.gl_pageSize, "pageNum":target.gl_pageNumber]
        GLNetWorkRequest(GLApiGeneral.getForm(path: path, para: parameter), hudView: nil) { (resp) in
            let array = [T].deserialize(from: resp as? Array<Any>) as? [T]
            guard let _arr = array else {
                target.tableView.mj_header?.endRefreshing()
                target.tableView.mj_footer?.endRefreshing()
                return
            }
            if target.gl_pageNumber == 1{
                target.gl_listArray.removeAll()
            }
            if _arr.count < target.gl_pageSize {
                target.tableView.mj_header?.endRefreshing()
                target.tableView.mj_footer?.endRefreshingWithNoMoreData()
            }else{
                if target.gl_pageNumber == 1{
                    target.showRefreshFooter()
                }
                target.tableView.mj_header?.endRefreshing()
                target.tableView.mj_footer?.endRefreshing()
                target.gl_pageNumber += 1
            }
            target.gl_listArray.append(contentsOf: _arr)
            target.tableView.reloadData()
        }failed: { (any, code) in
            target.tableView.mj_header?.endRefreshing()
            target.tableView.mj_footer?.endRefreshing()
        } errorResult: {
            target.tableView.mj_header?.endRefreshing()
            target.tableView.mj_footer?.endRefreshing()
        }
    }
    



    关键字

    image.png
    image.png
        func userInfo() {
            self.rj_get_userInfo(with: "", age: 0)
        }
        @available(*, deprecated, message: "使用rj_get_userInfo_new替代")
        open func rj_get_userInfo( with name: String, age: Int, score: ((Double) -> Void)? = nil) -> Double? {
            score?(99)
            return 0.0
        }
        @discardableResult
        open func rj_get_userInfo_new(with name: String, age: Int, score: ((Double) -> Void)? = nil) -> Double? {
            score?(99)
            return 0.0
        }
    /*知识点一: 表示警告已过期的方法
    */
    @available(*, deprecated, message: "使用rj_get_userInfo_new替代")
    
    /*知识点二: 表示如果我们调用一个带有返回值的函数,但是不使用返回值,就会得到Xcode编译警告。
    该关键字就是为了消除警告,即可以不使用返回值
    */
    @discardableResult
    
    /*知识点三: 下边的方法自动生成两个方法,一个带有score参数,一个不带  ? = nil
    */
        open func rj_get_userInfo( with name: String, age: Int, score: ((Double) -> Void)? = nil) -> Double? {
            score?(99)
            return 0.0
        }
    

    open 、public 、internal 、fileprivate 、private

        open class ClosureEventMonitor: EventMonitor {
            open var sessionDidBecomeInvalidWithError: ((URLSession, Error?) -> Void)?
        }
        public enum ParameterEncoderFailureReason {
            public enum RequiredComponent {or during encoding.
                case url
                case httpMethod(rawValue: String)
            }
            case missingRequiredComponent(RequiredComponent)
            case encoderFailed(error: Error)
        }
        internal func widthConstraint() -> NSLayoutConstraint? {
            return constraint(with: self, attribute: .width)
        }
        fileprivate func unlock() {
            let error = pthread_mutex_unlock(mutex)
            precondition(error == 0, "Failed to unlock pthread_mutex")
        }
    
        private var mutableState = MutableState()
    

    required(必须实现的协议) 、optional(可选实现的协议)

    @protocol UITableViewDataSource<NSObject>
    @required
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
    @optional
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; 
    ... ...
    @end
    
    //1.当子类没实现任何构造方法,编译器就会认为子类可以使用父类中的所有指定构造器,required修饰的构造方法在子类中可以不写
    //2.当子类中定义了异于父类中的构造方法(参数名称不同、参数个数不同、参数类型不同),
    //那么父类中使用required修饰的构造方法在子类中必须实现,而且这个方法必须使用required关键字而不能使用override修饰
    class RJBaseView: UIView {
        override  init(frame: CGRect) {
            super.init(frame: frame)
            // code... ...
        }
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }
    

    convenience(便利构造器)

    ------
        convenience init(frame: CGRect , placeholder : NSString,isShowMore : Bool) {
            self.init(frame: frame)
            isShowMoreP = isShowMore
            placeholderP = placeholder
        }
        /*
         required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
         }
         */
    ------
        init(frame: CGRect , placeholder : NSString,isShowMore : Bool) {
            isShowMoreP = isShowMore
            placeholderP = placeholder
            super.init(frame: frame)
        }
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    ------
    

    throw、throws、rethrows

    总结

    1. throw <#Error#>
      1 <#Error#> 可以是NSError 例子:throw NSError.init(domain: NSString.init(format: "You must override %@ in a subclass.", #function) as String, code: 99, userInfo: nil)
      2 <#Error#> 可以是extension String : Error{} 例子:throw "throwErrorContent"
      3 <#Error#> 可以是enum RJEnumError : Error { case ErrorState(errorCode:Int, errorMessage:String) } 例子:throw RJEnumError.ErrorState(errorCode: 88, errorMessage: "我是自定义错误啊")
      4 其他自定义类型
    2. throw终止代码往下执行
      1Code after 'throw' will never be executed即: throw后边的代码无法被执行
      2 do{ try ... } catch { }do 中代码一旦throw异常,则终止do中代码往下运行,进入到catch
    3. rethrows 只能传递 参数中的 异常,不能自己产生异常'A function declared 'rethrows' may only throw if its parameter does'
        func throwsError(index aIndex:Int, closure:() throws -> Void) throws { 
            try closure()
            throw "在这里我可以throw哟"
        }
        func rethrowsError(index aIndex:Int, closure:() throws -> Void) rethrows {
            do {
                try closure()
            }
            catch {
                print("错误原因:\(error)")
                throw "我只可以在这里throw哟,如果不写do catch ,默认异常往上抛出"
            }
        }
    
        func throwErrorClosure() throws {
            throw "throwErrorClosure"
        }
        func throwErrorClosure2()  {
            print("没有异常")
        }
        func testThrowError(index aIndex:Int) {
            //报错(throws):Call can throw, but it is not marked with 'try' and the error is not handled
            throwsError(index: aIndex, closure: throwErrorClosure2)
            //正常(rethrows):没有异常的参数则不用try
            rethrowsError(index: aIndex, closure: throwErrorClosure2)
            do {
                //正常(throws):没有异常的参数需要try
                try throwsError(index: aIndex, closure: throwErrorClosure2)
                //正常(rethrows):有异常的参数需要try
                try rethrowsError(index: aIndex, closure: throwErrorClosure)
                // 一旦上边的代码抛出异常,则下边的代码不会执行,直接进入到catch
    
                //警告(rethrows): No calls to throwing functions occur within 'try' expression
                try rethrowsError(index: aIndex, closure: throwErrorClosure2)
                //Code ...
            }
            catch {
                print(error)
            }
        }
    

    抛异常NSException

    Swift #function 和 _cmd (Objective-C) : 获取当前方法

        func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
            let error = NSException(name: NSExceptionName.internalInconsistencyException,
                                    reason: NSString.init(format: "You must override %@ in a subclass.", #function) as String,
                                    userInfo: nil)
            print(error)
        }
    
    print: You must override tableView(_:didSelectRowAt:) in a subclass.
    

    swift 中throw 的对象不能是 NSException,只能是Error类型

    #define MASMethodNotImplemented() \
        @throw [NSException exceptionWithName:NSInternalInconsistencyException \
                                       reason:[NSString stringWithFormat:@"You must override %@ in a subclass.", NSStringFromSelector(_cmd)] \
                                     userInfo:nil]
    

    do{ try ... } catch { }

        func testThrowError() {
            do {
                try self.throwError()
            }
            catch {
                print("catch----Error")
                print(error.localizedDescription)
            }
        }
        func throwError() throws {
            throw NSError.init(domain: NSString.init(format: "You must override %@ in a subclass.", #function) as String, code: 99, userInfo: nil)
        }
    
    print:
    catch----Error
    未能完成操作。(You must override throwError() in a subclass.错误99。)
    

    switch

        switch switchV {
            case 1:// 不写大括号
                print("1111")
                fallthrough// 实现贯穿效果  功能同oc中的不写break
            // 可省略不写break
            default:
                print("2222")
            }
    

    自定义和系统错误

        func testThrowError(index aIndex:Int) {
            do {
                try self.throwError(index: aIndex)
            }
            catch RJEnumError.ErrorState(let errorCode ,let errorMessage){
                print("错误码:\(errorCode) 错误原因:\(errorMessage)")
            }
            catch {
                print("catch----Error")
                print(error.localizedDescription)
            }
        }
        func throwError(index aIndex:Int) throws {
            switch aIndex {
            case 0:
                print("SUCCESS")
            case 1:
                throw RJEnumError.ErrorState(errorCode: 88, errorMessage: "我是自定义错误啊")
            case 2:
                throw NSError.init(domain: NSString.init(format: "You must override %@ in a subclass.", #function) as String, code: 99, userInfo: nil)
            default: break
            }
            
        }
        enum RJEnumError : Error {
            case ErrorState(errorCode:Int, errorMessage:String)
        }
    
    print:
    SUCCESS
    错误码:88 错误原因:我是自定义错误啊
    catch----Error
    未能完成操作。(You must override throwError(index:) in a subclass.错误99。)
    

    () -> Void类型可以传给 () throws -> Void类型,反过来则不能传递
    即:() -> Void类型可转换为 () throws -> Void ,但() throws -> Void无法转换为() -> Void ,
    () -> Void表示抛出异常的可能性为 0 罢了

    字符串分割

        let string = "我是世界上最好的好人,你们说对吗"
        //string.components(separatedBy: T##StringProtocol)
        //string.components(separatedBy: T##CharacterSet)
        let resultArray1 = string.components(separatedBy: ",")
        let resultArray2 = string.components(separatedBy: CharacterSet.init(charactersIn: "世界好"))
        let resultArray3 = Array(string)
        
        print(resultArray1)//"," 单字符分割
        print(resultArray2)//"世""界""好" 三个字分割
        print(resultArray3)//字符串单字符","分开
        
        let s = "Hi! How are you? I'm fine. It is 6 p.m. Thank you! That's it."
        var sentences = [String]()
        s.enumerateSubstrings(in: s.startIndex..<s.endIndex, options: .bySentences) { (substring, substringRange, enclosingRange, stop) in
            sentences.append(substring!)
        }
        print(sentences)//英文文字分割
    
    print:
    ["我是世界上最好的好人", "你们说对吗"]
    ["我是", "", "上最", "的", "人,你们说对吗"]
    ["我", "是", "世", "界", "上", "最", "好", "的", "好", "人", ",", "你", "们", "说", "对", "吗"]
    ["Hi! ", "How are you? ", "I\'m fine. ", "It is 6 p.m. ", "Thank you! ", "That\'s it."]
    

    奇怪的写法二Result<Success, Failure>

    抛出错误
    Swift 5 已经伴随 Xcode 10.2 正式发布,该类型被加入到标准库

    @frozen : 将此属性应用于结构或枚举声明,以限制可以对类型进行更改的种类。

    @frozen public enum Result<Success, Failure> where Failure : Error {
    
        case success(Success)
    
        case failure(Failure)
    
        public func map<NewSuccess>(_ transform: (Success) -> NewSuccess) -> Result<NewSuccess, Failure>
    
        public func mapError<NewFailure>(_ transform: (Failure) -> NewFailure) -> Result<Success, NewFailure> where NewFailure : Error
    
        public func flatMap<NewSuccess>(_ transform: (Success) -> Result<NewSuccess, Failure>) -> Result<NewSuccess, Failure>
    
        public func flatMapError<NewFailure>(_ transform: (Failure) -> Result<Success, NewFailure>) -> Result<Success, NewFailure> where NewFailure : Error
        
        public func get() throws -> Success
        
        public init(catching body: () throws -> Success)
    }
    
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            grj_goHome { (result) in
                switch result {
                case .success(let result):
                    print("-----------------")
                    print(result)
                case .failure(let error):
                    print("+++++++++++++++++")
                    print(error)
                }
            }
        }
        static var staticNumber = 0
        func grj_goHome(completionHandler:((Result<Any,Error>)) -> Void) {
            if <#Class#>.staticNumber%2==0 {
                completionHandler(.success("你的健康码是绿色,可以回家"))
            }else{
                let error = NSError.init(domain: "错误:你的健康码不是绿色,不能回家", code: 66, userInfo: ["健康码":"不是绿色"])
                completionHandler(.failure(error))
            }
            <#Class#>.staticNumber += 1
        }
    
    print:
    -----------------
    你的健康码是绿色,可以回家
    +++++++++++++++++
    Error Domain=错误:你的健康码不是绿色,不能回家 Code=66 "(null)" UserInfo={健康码=不是绿色}
    

    相关文章

      网友评论

          本文标题:swift 有趣的swift

          本文链接:https://www.haomeiwen.com/subject/jdeqzktx.html