iOS Dev Tips

AVPlayer 暂停继续播放

最近在开发一款视频直播的应用,其中有一个功能是进入后台暂停,再次进入前台后继续播放的问题,可以通过 Appdelegate 中处理这个问题,先上代码

- (void)applicationWillResignActive:(UIApplication *)application
{
   [player pause];
   pausedtime = player.currentTime
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
  [player seekToTime:pausedtime toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
  [player play];
}

思路是

MD5 加密

其他信息

内容解释+ (NSString *)md5:(NSString *)stringToEncrypt;方法 stringToEncrypt 待加密字符串 lowercaseString/uppercaseString 返回字符串为小写/大写

iOS 中关闭键盘

iOS 中经常需要用到关闭键盘,基本有三种方式

至于如何触发这些事件,看自己实际需求解决。

iPhone 分辨率

想想有点醉,某一个从事了四年 iOS 开发的人,居然至今连各代 iPhone 的分辨率都不知道,他也算是可以了。

官方链接:Screenshot specifications

Mac 下的应用

Icon 16px - 1024px,翻倍式。

iOS 开发之字体自定义

一天客户对我说:“*哥,你给我们做的这个应用,我们觉得字体不好看,能换个我们想要的字体么?”,同时递上了字体。

我说:“没问题!”,拿过新字体,开始工作。

重命名为 adai.ttf,直接拖入到项目资源中。

编辑 Info.plist 文件,添加 Fonts provided by application,Item 的值就是刚才我重命名的字体名字 adai.ttf。

然后调用方法 + (UIFont *)fontWithName:(NSString *)fontName size:(CGFloat)fontSize;,如 _lbTitle.font = [UIFont fontWithName:@"adai" size:20];

但是却不能正常显示,原来有时候字体名字并不是我重命名后的名字,咋办?

- (void)listAllFonts {
  NSArray *fontFamilies = [UIFont familyNames];
  for (NSString *fontFamily in fontFamilies) {
       NSArray *fontNames = [UIFont fontNamesForFamilyName:fontFamily];
       NSLog (@"%@: %@", fontFamily, fontNames);
  }
}

通过上面这段代码,列出字体名字,做了上面的修改,客户高兴的拿着修改字体后的应用回去了。

Swift 版本

查看字体

var i = 0
for family: String in UIFont.familyNames {
    print("\(i)---font---\(family)")
    for names: String in UIFont.fontNames(forFamilyName: family) {
        print("== \(names)")
    }
    i += 1
}

使用字体

let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
label.text = ""
let font = UIFont(name: "adai", size: 13)
if font != nil {
   label.font = font
}

隔了两三天,客户又来找:“*哥,我觉得新字体好看,但我们老板想看看其他几个字体,你能帮我多放几个字体进去么?”

我说:“你们真的麻烦,给你们弄个字体下载的吧。”,说完开工。

添加库 CoreText.framework 并引入文件 #import <CoreText/CoreText.h>

- (void)downloadFont
{
    NSString *URL_FONT = @"download_url/adai.otf";
    NSString *fontName = @"adai";
    NSData *dynamicFontData = [NSData dataWithContentsOfURL:[NSURL URLWithString:URL_FONT]];
    if (!dynamicFontData)
        return;
    CFErrorRef error;
    CGDataProviderRef providerRef = CGDataProviderCreateWithCFData((CFDataRef)dynamicFontData);
    CGFontRef font = CGFontCreateWithDataProvider(providerRef);
    if (! CTFontManagerRegisterGraphicsFont(font, &error))
    {
        CFStringRef errorDescription = CFErrorCopyDescription(error);
        NSLog(@"Failed to load font: %@", errorDescription);
        CFRelease(errorDescription);
    }
    else
        self.dynamicFontLabel.font = [UIFont fontWithName:fontName size:50];
    CFRelease(font);
    CFRelease(providerRef);
}

每次访问都要下载字体,那得多浪费流量,所以,又做了下判断,如果已经下载的就直接使用,没有下载的那就下载。

- (BOOL)hasFont:(NSString *)fontName
{
    UIFont* theFont = [UIFont fontWithName:fontName size:13.0];
    BOOL downloaded = (theFont && ([theFont.fontName compare:fontName] == NSOrderedSame || [theFont.familyName compare:fontName] == NSOrderedSame));
    return downloaded;
}

搞定,客户拿走了新应用。

ps. iOS 中自带的字体

0---项目字体---Devanagari Sangam MN
== DevanagariSangamMN
== DevanagariSangamMN-Bold
1---项目字体---Avenir Next
== AvenirNext-Medium
== AvenirNext-DemiBoldItalic
== AvenirNext-DemiBold
== AvenirNext-HeavyItalic
== AvenirNext-Regular
== AvenirNext-Italic
== AvenirNext-MediumItalic
== AvenirNext-UltraLightItalic
== AvenirNext-BoldItalic
== AvenirNext-Heavy
== AvenirNext-Bold
== AvenirNext-UltraLight
2---项目字体---Kohinoor Devanagari
== KohinoorDevanagari-Regular
== KohinoorDevanagari-Light
== KohinoorDevanagari-Semibold
3---项目字体---Times New Roman
== TimesNewRomanPS-ItalicMT
== TimesNewRomanPS-BoldItalicMT
== TimesNewRomanPS-BoldMT
== TimesNewRomanPSMT
4---项目字体---Gill Sans
== GillSans-Italic
== GillSans-SemiBold
== GillSans-UltraBold
== GillSans-Light
== GillSans-Bold
== GillSans
== GillSans-SemiBoldItalic
== GillSans-BoldItalic
== GillSans-LightItalic
5---项目字体---Kailasa
== Kailasa-Bold
== Kailasa
6---项目字体---Bradley Hand
== BradleyHandITCTT-Bold
7---项目字体---PingFang HK
== PingFangHK-Medium
== PingFangHK-Thin
== PingFangHK-Regular
== PingFangHK-Ultralight
== PingFangHK-Semibold
== PingFangHK-Light
8---项目字体---Savoye LET
== SavoyeLetPlain
9---项目字体---Odin Rounded
== Odin-Bold
10---项目字体---Trebuchet MS
== TrebuchetMS-Bold
== TrebuchetMS-Italic
== Trebuchet-BoldItalic
== TrebuchetMS
11---项目字体---Baskerville
== Baskerville-SemiBoldItalic
== Baskerville-SemiBold
== Baskerville-BoldItalic
== Baskerville
== Baskerville-Bold
== Baskerville-Italic
12---项目字体---Futura
== Futura-CondensedExtraBold
== Futura-Medium
== Futura-Bold
== Futura-CondensedMedium
== Futura-MediumItalic
13---项目字体---Arial Hebrew
== ArialHebrew-Bold
== ArialHebrew-Light
== ArialHebrew
14---项目字体---Bodoni 72
== BodoniSvtyTwoITCTT-Bold
== BodoniSvtyTwoITCTT-BookIta
== BodoniSvtyTwoITCTT-Book
15---项目字体---Hoefler Text
== HoeflerText-Italic
== HoeflerText-Black
== HoeflerText-Regular
== HoeflerText-BlackItalic
16---项目字体---Optima
== Optima-ExtraBlack
== Optima-BoldItalic
== Optima-Italic
== Optima-Regular
== Optima-Bold
17---项目字体---Futura MdCn BT
== FuturaBT-MediumCondensed
18---项目字体---DIN Condensed
== DINCondensed-Bold
19---项目字体---Noto Nastaliq Urdu
== NotoNastaliqUrdu
20---项目字体---Charter
== Charter-BlackItalic
== Charter-Bold
== Charter-Roman
== Charter-Black
== Charter-BoldItalic
== Charter-Italic
21---项目字体---Heiti TC
22---项目字体---Geeza Pro
== GeezaPro-Bold
== GeezaPro
23---项目字体---Bodoni Ornaments
== BodoniOrnamentsITCTT
24---项目字体---Kohinoor Telugu
== KohinoorTelugu-Regular
== KohinoorTelugu-Medium
== KohinoorTelugu-Light
25---项目字体---Helvetica Neue
== HelveticaNeue-UltraLightItalic
== HelveticaNeue-Medium
== HelveticaNeue-MediumItalic
== HelveticaNeue-UltraLight
== HelveticaNeue-Italic
== HelveticaNeue-Light
== HelveticaNeue-ThinItalic
== HelveticaNeue-LightItalic
== HelveticaNeue-Bold
== HelveticaNeue-Thin
== HelveticaNeue-CondensedBlack
== HelveticaNeue
== HelveticaNeue-CondensedBold
== HelveticaNeue-BoldItalic
26---项目字体---Party LET
== PartyLetPlain
27---项目字体---Symbol
== Symbol
28---项目字体---Bangla Sangam MN
29---项目字体---Hiragino Sans
== HiraginoSans-W3
== HiraginoSans-W6
30---项目字体---Hiragino Maru Gothic ProN
== HiraMaruProN-W4
31---项目字体---Cochin
== Cochin-Italic
== Cochin-Bold
== Cochin
== Cochin-BoldItalic
32---项目字体---Euphemia UCAS
== EuphemiaUCAS
== EuphemiaUCAS-Italic
== EuphemiaUCAS-Bold
33---项目字体---Academy Engraved LET
== AcademyEngravedLetPlain
34---项目字体---Helvetica
== Helvetica-Oblique
== Helvetica-BoldOblique
== Helvetica
== Helvetica-Light
== Helvetica-Bold
== Helvetica-LightOblique
35---项目字体---American Typewriter
== AmericanTypewriter-CondensedBold
== AmericanTypewriter-Condensed
== AmericanTypewriter-CondensedLight
== AmericanTypewriter
== AmericanTypewriter-Bold
== AmericanTypewriter-Semibold
== AmericanTypewriter-Light
36---项目字体---Didot
== Didot-Bold
== Didot
== Didot-Italic
37---项目字体---Courier New
== CourierNewPS-ItalicMT
== CourierNewPSMT
== CourierNewPS-BoldItalicMT
== CourierNewPS-BoldMT
38---项目字体---Courier
== Courier-BoldOblique
== Courier-Oblique
== Courier
== Courier-Bold
39---项目字体---Rockwell
== Rockwell-Italic
== Rockwell-Regular
== Rockwell-Bold

Xcode 项目工程的结构

这是我常用的项目工程结构,其中包含了 Pods.

ProjectName/
    Sourcecode 代码
        /M 模型
        /V 视图
        /C  控制器
    External   第三方引用,不管是自己写的类库和其它公司的都称第三方
    Supporting Files 默认的一些文件放在这里,比如 main.m Appdelegate.h/m Info.plist
    Res  图形素材
    Assets.xcassets
    Products
    Pods
    Frameworks
Pods

有时候项目小,不会使用 MVC 分开,那么就会用 Section 的方式,只要变更 Sourcecode里面的内容即可

Sourcecode 代码
  /Section1 板块1
  /Section2 板块2

iOS 中传值的问题

在 iOS 开发中,两界面之间的传值是常有的事情,传值的方式也有很多,比如 NSUserDefaults,再比如代理传值。

这里简单介绍下用代理传值

Url Scheme 使 APP 互相跳转及查看方法

在 iOS 开发中,Url Scheme 使得 app 之间相互跳转变得非常容易。

首先我们需要判断系统中是否安装了待跳转的 app,比如跳转到微信

if ([[UIApplication sharedApplication] canOpenURL:[NSURL  URLWithString:@"wexin://"]]){
    NSLog(@"已经安装");
}
else{
    NSLog(@"未安装");
}

如果安装了,则执行

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"weixin://"]];

这样就可以打开微信,那么是怎么知道这里的 wexin:// 即 Url Scheme 的呢?

更多使用说明,可以去看 Apple Developer Documents。

iOS 版本升级的提醒功能

虽然 Apple 禁止在 App 中提示升级,而且所有在 App 内部提示升级的 App 都无法通过审核,所以绕过审核人员就是这个功能的重点。

需要注意的是,这是违背开发者标准的,所以,这里我只是说明下思路,具体实现自行解决。

iOS 中拍照

拍照功能是应用中常有的,下面介绍两个拍照方式

AFNetworking Post 复杂的 Json

AFNetworking 是 iOS 下一个非常好用的类库,一般它在做 POST 请求的时候,单一 Json 格式较多,如下

NSDictionary *params = @{@"key0":"value0", @"key1":"value1", @"key2":"value2"};
[manager POST:URL_REQUEST parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {

} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

}];

但有时候在 Json 会相对复杂点,比如

{
    "key0":"value0",
    "keys":[
        {
            "key1":"value1",
            "key2":"value2"
        },
        {
            "key1":"value1",
            "key2":"value2"
        },
        {
            "key1":"value1",
            "key2":"value2"
        },
        {
            "key1":"value1",
            "key2":"value2"
        }
    ]
}

这时候就需要构造这部分参数,最简单的方法,循环

NSMutableArray *paramArrays = [NSMutableArray array];
for (int i = 0; i < _keycontent.count ; i++ ) {
    GCShoppingCartProductModel *model = _keycontent[i];
    NSDictionary *temp = @{@"key1":"value1",@"key2":"value2"};

    [paramArrays addObject:temp];
}
NSDictionary *params = @{@"key0":"value0",@"keys":paramArrays};

至于其他请求部分还是一样。

根据经纬度计算距离

Label 上文字显示不一样

// 创建Attributed
NSMutableAttributedString *noteStr = [[NSMutableAttributedString alloc] initWithString:_label.text];
// 需要改变的第一个文字的位置
NSUInteger firstLoc = [[noteStr string] rangeOfString:@"金"].location + 1;
// 需要改变的最后一个文字的位置
NSUInteger secondLoc = [[noteStr string] rangeOfString:@"元"].location;
// 需要改变的区间
NSRange range = NSMakeRange(firstLoc, secondLoc - firstLoc);
// 改变颜色
[noteStr addAttribute:NSForegroundColorAttributeName value:[UIColor greenColor] range:range];
// 改变字体大小及类型
[noteStr addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"Helvetica-BoldOblique" size:27] range:range];
// 为label添加Attributed
[_label setAttributedText:noteStr];

iOS 判断 uiscrollview 是向上滚动

- (void)scrollViewDidScroll:(UIScrollView *)scrollView

{

    int currentPostion = scrollView.contentOffset.y;

    if (currentPostion - _lastPosition > 20  && currentPostion > 0) {

        _lastPosition = currentPostion;

        NSLog(@"ScrollUp now");

        [self hideTabBar:YES];

        [self.navigationController setNavigationBarHidden:YES animated:YES];

    }

    else if ((_lastPosition - currentPostion > 20) && (currentPostion  <= scrollView.contentSize.height-scrollView.bounds.size.height-20) ) 

    {

        _lastPosition = currentPostion;

        NSLog(@"ScrollDown now");

       [self hideTabBar:NO];

        [self.navigationController setNavigationBarHidden:NO animated:YES];

    }
}

倒计时

© 2008 - 2021 · TOURCODER.COM ·