美文网首页
iOS 开发Tips1

iOS 开发Tips1

作者: 我是Damo | 来源:发表于2019-03-26 18:29 被阅读0次

1. 使用storyboard reference

点击需要缩小的控制器 ---> 菜单editor ---> Refactor to Storyboard

2. NSNumberFormatter

可以用来处理NSString和NSNumber之间的转化,可以满足基本的数据形式的转化

四舍五入到整数
货币的形式,带本地化的货币符号
科学计数形式
本地化拼写形式

3. Nil,nil,NULL,NSNull的区别

nil:定义一个对象为空值,例如: NSObject *obj = nil
Nil:定义类为空,例如:Class someClass = Nil
NULL:定义基本数据对象指针为空例如:int *point = NULL
NSNull:结合对象无法包含nil,用特定对象NSNull表示,注意:调用特定方法是注意剔除NSNull对象

4.defer

关键字可以用来包裹一段代码,这个代码块将会在当前作用域结束的时候被调用。这通常被用来对当前的代码进行一些清理工作,比如关闭打开的文件等。可以在同一个作用域中指定多个 defer 代码块,在当前作用域结束时,它们会以相反的顺序被调用,即先定义的后执行,后定义的先执行

openFile()
defer {
    // defer block 1
    closeFile()
}

startPortListener(42)
defer {
   // defer block 2
   stopPortListener(42)
}

这段代码在作用域结束的时候,第二个 defer 块将首先被调用,其次再调用第一个 defer 块。

5.associatedtype

swift中的协议(protocol)采用的是“Associated Types”的方式来实现泛型功能的,通过associatedtype关键字来声明一个类型的占位符作为协议定义的一部分。swift的协议不支持下面的定义方式:

protocol GeneratorType<Element> {
    public mutating func next() -> Element?
}
而是应该使用这样的定义方式:

protocol GeneratorType {
    associatedtype Element
    public mutating func next() -> Self.Element?
}

6.值类型和应用类型

7.控制台命令expression

expr self.loginBtn.backgroundColor = UIColor.blue
expr CATransaction.flush() //立刻刷新界面

8.正则

要在正则表达式中假如^ 和 表示从头到尾都要符合正则表达式 英文和数字:^[A-Za-z0-9]+

NSRegularExpressionCaseInsensitive             = 1 << 0,     // 不区分大小写字母模式
    NSRegularExpressionAllowCommentsAndWhitespace  = 1 << 1,     // 忽略掉正则表达式中的空格和#号之后的字符
    NSRegularExpressionIgnoreMetacharacters        = 1 << 2,     // 将正则表达式整体作为字符串处理
    NSRegularExpressionDotMatchesLineSeparators    = 1 << 3,     // 允许.匹配任何字符,包括换行符
    NSRegularExpressionAnchorsMatchLines           = 1 << 4,     // 允许^和$符号匹配行的开头和结尾
    NSRegularExpressionUseUnixLineSeparators       = 1 << 5,     // 设置\n为唯一的行分隔符,否则所有的都有效。
    NSRegularExpressionUseUnicodeWordBoundaries    = 1 << 6      // /使用Unicode TR#29标准作为词的边界,否则所有传统正则表达式的词边界都有效
    */

    //创建正则表达式对象
    NSRegularExpression *regex = [NSRegularExpression
                                  regularExpressionWithPattern:pattern
                                  options:NSRegularExpressionCaseInsensitive
                                  error:nil];

NSString *matchString = @"dsampoewaf";

// 2.2 设置进行匹配时的参数===>下面的options
/*
NSMatchingReportProgress         = 1 << 0,       // 找到最长的匹配字符串后调用block回调
NSMatchingReportCompletion       = 1 << 1,       // 找到任何一个匹配串后都回调一次block
NSMatchingAnchored               = 1 << 2,       // 从匹配范围的开始进行极限匹配
NSMatchingWithTransparentBounds  = 1 << 3,       // 允许匹配的范围超出设置的范围
NSMatchingWithoutAnchoringBounds = 1 << 4        // 禁止^和$自动匹配行开始和结束
*/

// 2.3 设置匹配字符串的范围
NSRange range = NSMakeRange(0, matchString.length);

// 2.4 开始匹配
NSArray<NSTextCheckingResult *> *textCheckingResults = [regex matchesInString:matchString
                                                                      options:NSMatchingReportProgress
                                                                        range:range];

9.String去除两端空格和换行符

str.trimmingCharacters(in: .whitespacesAndNewlines)

10.@discardableResult

@discardableResult :默认情况下编译器就是会去检查返回参数是否有被使用,没有的话就会给出警告。如果你不想要这个警告,可以自己手动加上

11.删除Xcode缓存数据

  • 手动删除Derived Data文件夹
  • 调用xcodebuild clean 清空缓存
  • 调用 xcodebuild archive自动忽略缓存

12.设置app共享文件功能(可在iTunes -> 应用 ->文件共享 ->目标APP目录下放入文件)

在info.plist中设置Application supports iTunes file sharing(UIFileSharingEnabled) = yes

13.跨APP传输数据

  • UIPasteboard
    在app1中:
let borad = UIPasteboard(name: UIPasteboardName(rawValue: "myBorad"), create: true)

borad?.string = "存入数据"

app2:

let borad = UIPasteboard(name: UIPasteboardName(rawValue: "myBorad"), create: true)

dataLb.text = borad?.string

注意:APP的证书需要是一致的,不一致app2读取结果为空

  • Scheme
    APP1:
let str = "app2://message=读取数据" //app2为App2设置的scheme
let url = URL(string: str.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!)
        
if let _ = url,UIApplication.shared.canOpenURL(url!) {
            UIApplication.shared.open(url!, options: [:], completionHandler: nil)
            print("open url")
        }

**plist中 设置**
<key>LSApplicationQueriesSchemes</key>
    <array>
        <string>app2</string>
    </array>

APP2:

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
        if url.scheme == "app2" {
            let message = url.relativeString.removingPercentEncoding
            print("message = \(message)")
        }
        
        return true
    }

优点:不同证书间可以传递消息

  • Keychain

一. 将APP1和APP2中Xcode的capabilities中的Keychain Shareing打开,在KeyChainGroup中输入和APP2同一字符

APP1:(使用了KeychainSwift)

 keychain.set("value", forKey: "key")

APP2:

let str = keychain.get("key")
dataLb.text = str

优点:不同证书间可以传递消息

  • App Groups(iOS 8Later)

    APP1:
    打开Capabilities中的APP Groups,创建一个新的group
    APP2:
    打开Capabilities中的APP Groups,选择创建的group(证书需相同),测试的时候使用了中文的app名,添加group失败了,需要标准命名

UserDefaults:

APP1:
 let userDefult = UserDefaults(suiteName: "group.com.damo.shareData")
 let array = ["a","b","c"]
 userDefult?.setValue(array, forKey: "key")

APP2:
 let userDefult = UserDefaults(suiteName: "group.com.damo.shareData")
 let array = userDefult?.value(forKey: "key") as? Array<String>
 print(array ?? "")

FileManager:

APP1:
let array = ["a","b","c"]
        let data = NSKeyedArchiver.archivedData(withRootObject: array)
        
        var fileURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.damo.shareData")
        fileURL = fileURL?.appendingPathComponent("Library/Caches/good")

        
        do {s
            try data.write(to: fileURL!)
            
        } catch  {
            print("error")
        }

APP2:
var fileURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.damo.shareData")
         fileURL = fileURL?.appendingPathComponent("Library/Caches/good")
        
        do {
            let data = try Data.init(contentsOf: fileURL!)
            let array  = NSKeyedUnarchiver.unarchiveObject(with: data)
            
            print(array ?? "")
            
        } catch  {
            print("error")
        }
copy文件

fileManager remove item to path
or copy Location path to containing app path(Bundle取值)
有可能调用的时候文件还没有复制过去,审核可能也通不过

container app的文件目录里只有Library目录(含Crash,Preferences),container app不能单独存在,必须包含在一个app中,能够调起extension的app被称为host app

14.URL Types 中role选项

  • viewer : 该应用程序可以读取和呈现该类型的数据
  • editor : 该应用程序可以读取、操作和保存类型
  • none : 该应用程序不理解数据,但只是声明有关类型的信息(例如,Finder声明字体的图标)

15.指定pod库中使用的swift版本

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['SWIFT_VERSION'] = '3.2'
    end 
  end
end

16.nullable和nonnull

当然,试想一下如果每一个参数都需要指定 _nullable 或者 _nonnull,未免不是太麻烦了!好在苹果给我们提供了一对宏定义: NS_ASSUME_NONNULL_BEGIN 和 NS_ASSUME_NONNULL_END

NS_ASSUME_NONNULL_BEGIN

@interface DemoVC_1 : UIViewController

//需要指定 nullable
@property (nonatomic, copy, nullable) NSString *name;

//NS_ASSUME_NONNULL_BEGIN 和 NS_ASSUME_NONNULL_END 之间,此处 ID 没有指定则默认为 nonnull
- (instancetype)initWithID:(NSString *)ID;

@end


NS_ASSUME_NONNULL_END

17.Xcode 测量 pre-main 时间

只需要在 Edit scheme -> Run -> Arguments 中将环境变量 DYLD_PRINT_STATISTICS 设为 1
还有一个方法获取更详细的时间,只需将环境变量

Total pre-main time: 921.98 milliseconds (100.0%)
         dylib loading time:  93.77 milliseconds (10.1%)
        rebase/binding time: 648.85 milliseconds (70.3%)
            ObjC setup time:  79.35 milliseconds (8.6%)
           initializer time:  99.83 milliseconds (10.8%)
           slowest intializers :
               libSystem.dylib :   8.90 milliseconds (0.9%)
   libBacktraceRecording.dylib :  25.85 milliseconds (2.8%)
    libMainThreadChecker.dylib :  34.99 milliseconds (3.7%)

DYLD_PRINT_STATISTICS_DETAILS 设为 1

  total time: 1.4 seconds (100.0%)
  total images loaded:  223 (0 from dyld shared cache)
  total segments mapped: 661, into 89997 pages with 6002 pages pre-fetched
  total images loading time: 397.74 milliseconds (27.5%)
  total load time in ObjC:  90.22 milliseconds (6.2%)
  total debugger pause time: 298.94 milliseconds (20.6%)
  total dtrace DOF registration time:   0.10 milliseconds (0.0%)
  total rebase fixups:  2,087,201
  total rebase fixups time: 838.45 milliseconds (58.0%)
  total binding fixups: 240,006
  total binding fixups time:  36.59 milliseconds (2.5%)
  total weak binding fixups time:   0.57 milliseconds (0.0%)
  total redo shared cached bindings time:  36.35 milliseconds (2.5%)
  total bindings lazily fixed up: 0 of 0
  total time in initializers and ObjC +load:  80.78 milliseconds (5.5%)
                           libSystem.dylib :   4.87 milliseconds (0.3%)
               libBacktraceRecording.dylib :  17.51 milliseconds (1.2%)
                            CoreFoundation :  13.87 milliseconds (0.9%)
                                Foundation :   6.08 milliseconds (0.4%)
                libMainThreadChecker.dylib :  30.00 milliseconds (2.0%)
                                   ModelIO :   6.30 milliseconds (0.4%)
total symbol trie searches:    119652
total symbol table binary searches:    0
total images defining weak symbols:  28
total images using weak symbols:  66

18.CFAbsoluteTimeGetCurrent()

绝对时间以秒为单位,相对于2001年1月1日00:00:00时的绝对参考日期。一个正数代表一个日期之后的日期,一个负数代表一个日期之前的日期。例如,绝对时间-32940326相当于1999年12月16日的17:54:34。对这个函数的重复调用不能保证单调递增的结果。由于与外部时间引用同步或由于显式的用户更改,系统时间可能会减少。

19.类属性

.h文件中定义一个class修饰的属性

@property (class,nonatomic, strong) NSString *str;

static NSString *_str = nil;

@implementation ViewController
需自己实现set和get方法
+  (NSString *)str {
    if (_str == nil) {
        _str = @"default";
    }
    return _str;
}

+  (void)setStr:(NSString *)str {
    _str = str;
}
@end

20.git回到指定版本

git reset --hard commit_id
git log可以查看提交历史,以便确定要回退到哪个版本
后悔了用git reflog查看命令历史,以便确定要回到未来的哪个版本。

21.将系统添加允许任意来源的软件

sudo spctl --master-disable

22.显示隐藏系统文件

扩:打开系统隐藏文件夹
打开:defaults write com.apple.finder AppleShowAllFiles -boolean true ; killall Finder
关闭:defaults write com.apple.finder AppleShowAllFiles -boolean false ; killall Finder
Command + shift+ .

23.网络检索的技巧

双引号和书名号(“”《》):表示查询词不能被拆分,在搜索结果中必须完整出现

通配符(、?):比如我要搜索一个单词,但是我忘记了它其中一个字母是什么,我们就可以使用通配符“?”来代替,

圆括号(【】):使用的关键词是词组的情况下容易被百度拆分为两个关键词进行搜索,这样就容易带来一大堆的无效搜索,而加上圆括号以后就会默认这是一个完整的词来进行搜索

加减号(+、-):加(+)减(-)号的使用就很常见了,多个关键词进行(+)代表着搜索结果必须包含所有关键词,而(-)则表示搜索结果不包括被减去的那个关键词

Intitle语法(格式——intitle:关键字):顾名思义,intitle表示搜索结果必须在标题里,这样就可以去除文章内容含有我们关键词的无用搜索结果了。 在查询词前加上“intitle:”,冒号“:”要用英文半角,后面不加空格;如果有2个以上的查询词,可以在所有词前面加上“allintitle:”,格式与前面相同。

filetype语法(格式——filetype:后缀关键词):这个就应该强烈推荐了,找资料特别方便,在filetype后面加上文件的后缀就可以轻松的找到需要的资料进行下载了。。在查询词后,输入“filetype:” “文件格式(如果doc/pdf/xls等)”,冒号“:”要用英文半角,紧接文件格式。搜索特定的文件格式,即搜索结果都是你指定的那种格式。

并行搜索(|):在两个查询词A和B中间加入“|”,搜索结果会包含词语A和B中的任意一个,不必同时包含这两个词

24.设置导航栏的位置

//设置导航栏背景图片为一个空的image,导航栏这样就透明了,自动顶到状态栏
    [self.navigationController.navigationBar setBackgroundImage:[[UIImage alloc] init] forBarMetrics:UIBarMetricsDefault];

25.lldb改变控件颜色

改变颜色:
(lldb) expr ((UIView *)0x174197010).backgroundColor = [UIColor redColor]
e (void)[CATransaction flush]. //及时刷新界面

26.字体跟随Label的宽度改变font

_lblMonth.adjustsFontSizeToFitWidth = true;

27.编辑状态下UITableViewCell圆圈视图

类名:UITableViewCellEditControl
宽度:为47
视图与contentView有交叉,图层在contentView之上,交叉部分的宽度为9
修改编辑状态下系统的默认图片:

XXXCell.m

-(void)layoutSubviews
{
    for (UIControl *control in self.subviews){
        if ([control isMemberOfClass:NSClassFromString(@"UITableViewCellEditControl")]){
            for (UIView *view in control.subviews)
            {
                if ([view isKindOfClass: [UIImageView class]]) {
                    UIImageView *image=(UIImageView *)view;
                    if (self.selected) {
                        image.image=[UIImage imageNamed:@"selected"];
                    }
                    else
                    {
                        image.image=[UIImage imageNamed:@"normal"];
                    }
                }
            }
        }
    }
    [super layoutSubviews];
}


- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
    [super setEditing:editing animated:animated];
        for (UIControl *control in self.subviews){
            if ([control isMemberOfClass:NSClassFromString(@"UITableViewCellEditControl")]){
                for (UIView *view in control.subviews)
                {
                    if ([view isKindOfClass: [UIImageView class]]) {
                        UIImageView *image=(UIImageView *)view;
                        if (!self.selected) {
                            image.image=[UIImage imageNamed:@"normal"];
                        }
                    }
                }
            }
        }

}

28.UITableView选中时,分割线颜色变浅

- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated {
    [super setHighlighted:highlighted animated:YES];
    self.bottomLine.backgroundColor = RGBCOLOR(204, 204, 204);
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];
    self.bottomLine.backgroundColor = RGBCOLOR(204, 204, 204);
}

29.通过View拿到控制器

    func currentVC() -> UIViewController? {
        var nextView = self.superview
        while nextView != nil {
            let nextResponse = nextView!.next
            if nextResponse?.isKind(of: UIViewController.self) ?? false {
                return nextResponse! as? UIViewController
            }
            nextView = nextView!.superview
        }
        return nil
    }

30,在导航栏添加按钮

用customview添加:默认渲染成灰色
用initWithImge添加:默认渲染成半透明

31.dispatch OC

dispatch中调用控制器,当控制器pop时,会延长控制器的生命周期至block中diamante执行结束,weakSelf解决,

32 在方法中修改参数的值

若是全局变量,

- (void)test:(NSArray * __strong *)str {
}

33.在协议中定义属性

相当于定义了set和get方法,.m文件中使用@sychonize 属性;

34.__kindof

在属性或者是方法返回值前加,表示可以为子类(iOS 9)

35 inline

static inline UIViewController *RTSafeUnwrapViewController(UIViewController *controller) {
    if ([controller isKindOfClass:[RTContainerController class]]) {
        return ((RTContainerController *)controller).contentViewController;
    }
    return controller;
}

static自不用多说,表示在当前文件中应用,如 static A, 在其它文件中也可以出现static A.不会导致重名的错误.
inline.内联函数.
作用:替代宏.

为什么inline能取代宏?


优点相比于函数:

inline函数避免了普通函数的,在汇编时必须调用call的缺点:取消了函数的参数压栈,减少了调用的开销,提高效率.所以执行速度确比一般函数的执行速度要快.
2)集成了宏的优点,使用时直接用代码替换(像宏一样);


优点相比于宏:

  1. 避免了宏的缺点:需要预编译.因为inline内联函数也是函数,不需要预编译.

  2. 编译器在调用一个内联函数时,会首先检查它的参数的类型,保证调用正确。然后进行一系列的相关检查,就像对待任何一个真正的函数一样。这样就消除了它的隐患和局限性。

  3. 可以使用所在类的保护成员及私有成员。


inline内联函数的说明:

1.内联函数只是我们向编译器提供的申请,编译器不一定采取inline形式调用函数.
2.内联函数不能承载大量的代码.如果内联函数的函数体过大,编译器会自动放弃内联.
3.内联函数内不允许使用循环语句或开关语句.
4.内联函数的定义须在调用之前.

36. attribute

1.在编译时会报过时警告

- (void)method1:( NSString *)string __attribute__((deprecated("使用#method2")));

2.告诉编译器方法不可用,如果使用了就会编译失败,提示错误。比如自定义了初始化方法,为了防止别人调用init初始化

@property (strong,nonatomic) id var1 NS_UNAVAILABLE;
    - (void)method9 NS_UNAVAILABLE;
    - (void)method10 UNAVAILABLE_ATTRIBUTE;
    - (void)method11 __attribute__((unavailable("不能用,不能用,不能用")));

  1. 它主要作用于变量,当变量的作用域结束时,会调用指定的函数。这个属性用得好,简直是爽得不要不要的。
- (void)createXcode  {
    NSObject *xcode __attribute__((cleanup(xcodeCleanUp))) = [NSObject new];
    NSLog(@"%@",xcode);
}

// 指定一个cleanup方法,注意入参是所修饰变量的地址,类型要一样
// 对于指向objc对象的指针(id *),如果不强制声明__strong默认是__autoreleasing,造成类型不匹配
static void xcodeCleanUp(__strong NSObject **xcode){
    NSLog(@"cleanUp call %@",*xcode);
}

- (void)createBlock {
    __strong void(^block)() __attribute__((cleanup(blockCleanup))) = ^{
        NSLog(@"Call Block");
    };
}

static void blockCleanup(__strong void(^*block)(void))  {
    (*block)();
}


4.availability
这个参数是指定变量(方法)的使用版本范围,这个很好用。
拿一下官方的作为例子,UITableViewCell里面找的

NS_DEPRECATED_IOS(2_0, 3_0)
 
#define NS_DEPRECATED_IOS(_iosIntro, _iosDep, ...) CF_DEPRECATED_IOS(_iosIntro, _iosDep, __VA_ARGS__)

#define CF_DEPRECATED_IOS(_iosIntro, _iosDep, ...) __attribute__((availability(ios,introduced=_iosIntro,deprecated=_iosDep,message="" __VA_ARGS__)))

上面定义的NS_DEPRECATED_IOS(2_0, 3_0)展开为attribute

__attribute__((availability(ios,introduced=2_0,deprecated=3_0,message="" __VA_ARGS__)))

availability属性是一个以逗号为分隔的参数列表,以平台的名称开始,包含一些放在附加信息里的一些里程碑式的声明。

introduced:第一次出现的版本。
deprecated:声明要废弃的版本,意味着用户要迁移为其他API
obsoleted: 声明移除的版本,意味着完全移除,再也不能使用它
unavailable:在这些平台都不可用
message 一些关于废弃和移除的信息
属性支持的平台:iOS , macosx(我看了一下系统的宏,现在有swift关键字了)

5.overloadable
函数名相同,需重载

__attribute__((overloadable)) void add(int num){
    NSLog(@"Add Int %i",num);
}

__attribute__((overloadable)) void add(NSString * num){
    NSLog(@"Add NSString %@",num);
}

__attribute__((overloadable)) void add(NSNumber * num){
    NSLog(@"Add NSNumber %@",num);
}

6、 objc_designated_initializer

这个属性是指定内部实现的初始化方法。

- (instancetype)initNoDesignated ;
- (instancetype)initNoDesignated12 NS_DESIGNATED_INITIALIZER;
- (instancetype)initDesignated NS_DESIGNATED_INITIALIZER;
上面的NS_DESIGNATED_INITIALIZER展开就是:__attribute__((objc_designated_initializer))

7、objc_subclassing_restricted

这个顾名思义就是相当于java的final关键字了,意是说它不能有子类。用于类注意不加逗号

__attribute__((objc_subclassing_restricted)) //Final类 ,java的final关键字
@interface CustomObject : NSObject  
如果有子类继承他的话,就会报错

8.objc_requires_super

这个也挺有意思的,意思是子类重写这个方法的时候,必须调用[super xxx]

    #define NS_REQUIRES_SUPER __attribute__((objc_requires_super))
    - (void)method2 __attribute__((objc_requires_super));

37. will/did MoveToParentViewController

当我们向我们的视图控制器容器中调用removeFromParentViewController方法时,必须要先调用该方法,且parent参数为nil:
[将要删除的视图控制器 willMoveToParentViewController:nil];

addChildViewController 自动调用
[将要添加的视图控制器 willMoveToParentViewController:self];

38 visibleViewController && topViewController

visibleViewController 就是当前显示的控制器
topViewController 是某个导航栈的栈顶视图
visibleViewController和哪个导航栈没有关系,只是当前显示的控制器,也就是说任意一个导航的visibleViewController所返回的值应该是一样的,
但是topViewController 就是某个导航栈的栈顶视图,和导航嘻嘻相关
换句话说如果在仅有一个导航栈上

39.UI单元测试

KIF 或者SwiftMonkey

40 使用腾讯的WeTest检查上线前预审

41.模态效果

self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
self.modalPresentationStyle = UIModalPresentationFullScreen;

42.Flurry来做iOS用户行为分析

目前市面上针对移动应用的用户数据跟踪统计工具还是比较多的。

  • 全球范围内Google Analytics,Flurry,Mixpanel都比较流行;
  • 国内而言,友盟,TalkingData,百度,诸葛io也都有自己的产品,而且有些功能设计上有自己的独到之处;
    在这些工具中,我选择了Flurry,主要原因如下:
  • 用户数据收集的网络问题。我的应用既有国内用户,也有国外用户,需要兼顾;考虑到大部分国内工具国际友人访问速度受限,基本可以忽略;而Google Analytics被墙,虽然有同学反映数据收集不受影响,依然不太方便吧;
  • 隐私保护策略。一般而言国际大牌厂商在隐私数据处理上会更慎重;
  • 免费。Flurry是免费的。

43.RAM

保持应用的内存需求处于RAM的较低占比是一个非常好的主意,使用量尽量不超过80% ~ 85%,例如 iPhone 5S大约有1GB的RAM,分配给一个应用的堆(栈大小固定,512KB,1M,2M,堆的大小是有手机系统决定)的大小最多不到512M,

扩展:iPhone ~iPhone 3S RAM: 128MB
iPhone 3GS RAM: 256 MB
iPhone 4 ~ iPhone 4s RAM: 512MB
iPhone 5 ~ iPhone 6P RAM: 1 GB
iPhone 6s ~iPhone 7,iPhoneSe,iPhone 8 RAM: 2GB
iPhone 7p,iPhone 8p,iPhoneX RAM : 3GB

扩展:

arm64 armv7s armv7
iphone5s iPhone5 iPhone4
iphone6 iPhone5C iPhone4S
iphone6 plus iPad4(iPad with Retina Display) iPad
iphone6s iPad2
iPhone6s plus iPad3(The New iPad)
iPad Air iPad mini
iPad mini2 (iPad mini with Retina Display) iPod Touch 3G

44.autoreleasepool

使用场景:
1.创建一个很多临时对象的循环时.在循环中使用autoreleasepool快可以为每个迭代释放内存.虽然迭代前后的内存使用相同,但你的应用的最大内存需求可以大大降低
2.创建一个线程时,
每个线程都有自己的autoreleasepool,对于任何自定义的线程,必须创建自己的autoreleasepool

//不良代码
{
    @autoreleasepool {
        NSUInteger usercount = self.count;
        for (NSUInteger i = 0; i < usercount; i++) {
            NSString *str = [NSString stringWithFormat:@"%d",I];
            
        }
    }


}

//好的代码
{
  @autoreleasepool {
        NSUInteger usercount = self.count;
        for (NSUInteger i = 0; i < usercount; i++) {
            @autoreleasepool {
            NSString *str = [NSString stringWithFormat:@"%d",I];
            }
        }
    }
}
- (void)myThreadStart:(id)obj {
  @autoreleasepool {
  //新线程的diamante
  }
}

//其他地方
  NSThread *mythread = [[NSThread alloc] initWithTarget:self selector:@selector(myThreadStart:) object:nil];
    [mythread start];

45.ARC

ARC中属性不能以new开头,以确保与MRC的互操作性

//不允许
@property NSString *newTitle; 

//允许
@property (getter=getNewTitle) NSString *newTitle;

//属性修饰符
Model *__strong str1 = [[Model alloc] init];
    Model * __weak str2 = [[Model alloc] init];
    Model * __unsafe_unretained str3 = [[Model alloc] init];
    Model * __autoreleasing str4 = [[Model alloc] init];

1.创建对象后引用计数为1,被引用期间不会被回收
2.创建对象后引用计数为0,对象立刻释放,且str2将被设置为nil
3.创建对象后引用计数为1,对象被立刻释放,但str3不会被置为nil
4.创建对象后引用计数为1,当方法返回时对象立刻释放

assign在ARC之前是默认的持有关系限定符,ARC下assign表示 __unsafe_unretained

46.UIPageControll换图

[_pageControl setValue:[UIImage imageNamed:@"pageNomal"] forKeyPath:@"pageImage"];
 [_pageControl setValue:[UIImage imageNamed:@"pageSelect"] forKeyPath:@"currentPageImage"];

47.打印SEL

NSLog(@"%s", sel_getName(aSelector)) ;

48.UITableView (group)

两个section中间间距过大,设置footView的高度为0.01

49苹果等宽字体

Menlo、 Courier New、 Courier 和 _typewriter

50UILabel两端对齐

只有一行效果不大,

NSString *string = @"死垃圾法拉盛骄傲了京234d大件垃圾放辣椒;阿附近啊安静地方辣椒粉;安抚辣椒粉垃圾发阿附近啊;激发阿两地分居;埃及法";
    NSMutableAttributedString *mAttriStr = [[NSMutableAttributedString alloc] initWithString:string];
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    paragraphStyle.alignment = NSTextAlignmentJustified;
    paragraphStyle.paragraphSpacing = 11.0;
    paragraphStyle.paragraphSpacingBefore = 10;
    paragraphStyle.firstLineHeadIndent = 0.0;
    paragraphStyle.headIndent = 0.0;
    NSDictionary *dict = @{NSForegroundColorAttributeName : [UIColor grayColor],
                           NSFontAttributeName: [UIFont systemFontOfSize:15],
                           NSParagraphStyleAttributeName : paragraphStyle,
                           NSUnderlineStyleAttributeName: [NSNumber numberWithInteger:NSUnderlineStyleNone]
                           };
    [mAttriStr setAttributes:dict range:NSMakeRange(0, mAttriStr.length)];
    self.textLb.attributedText = mAttriStr;
屏幕快照 2018-03-22 下午1.42.03.png

相关文章

  • iOS 开发Tips1

    1. 使用storyboard reference 点击需要缩小的控制器 ---> 菜单editor ---> ...

  • 精品的博客

    tips1: 非常好的Pop实现思路 iOS 微信右上角下拉菜单效果之CMPopTipView,各种角度各种位置 ...

  • 1001--OpenGL MAC 环境搭建

    tips1:针对有开发经验的开发者,细枝末节比如:拖入文件放的位置什么,添加文件后的截图等,不做赘述 tips2:...

  • iOS开发优秀博客和软件推荐

    iOSBlogAndTools iOS开发优秀博客和软件推荐 iOS开发中文博客 iOS开发工具 iOS开发网站 ...

  • 收录 : iOS支付开发

    iOS 银联支付开发流程iOS 微信支付开发流程iOS 支付宝支付开发流程iOS Apple Pay开发流程App...

  • IOS开发问题索引(四)

    全系列文章索引: IOS开发问题索引(一) IOS开发问题索引(二) IOS开发问题索引(三) IOS开发问题索引...

  • IOS开发问题索引(八)

    全系列文章索引: IOS开发问题索引(一) IOS开发问题索引(二) IOS开发问题索引(三) IOS开发问题索引...

  • IOS开发问题索引(七)

    全系列文章索引: IOS开发问题索引(一) IOS开发问题索引(二) IOS开发问题索引(三) IOS开发问题索引...

  • IOS开发问题索引(六)

    全系列文章索引: IOS开发问题索引(一) IOS开发问题索引(二) IOS开发问题索引(三) IOS开发问题索引...

  • IOS开发问题索引(五)

    全系列文章索引: IOS开发问题索引(一) IOS开发问题索引(二) IOS开发问题索引(三) IOS开发问题索引...

网友评论

      本文标题:iOS 开发Tips1

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