0%

在iOS7及以上系统,self.navigationController.navigationBar.hidden = NO;的情况下.

设置translucent为YES.即self.navigationController.navigationBar.translucent = YES;

不隐藏状态栏

self.view的位置和大小如下:

隐藏状态栏

执行流:

translucent为YES时,可以在viewDidLoad中子视图可以使用self.view的frame信息.

阅读全文 »

制作静态库注意事项

  1. 添加前缀防止冲突.
    类名,全局定义的变量(如全局变量,全局的枚举定义),类别方法名,宏,通知名称.需要添加前缀防止与宿主冲突.

  2. 使用static关键字限制作用域.
    对于全局变量,尽可能使用static限制作用域.否则容易与宿主重复定义导致编译错误.

Swift静态库注意事项

工程是Swift,OC混编.开发完成后,需要将工程制作为一个静态库.制作完成测试使用时,发现一运行就崩溃.提示:
Unknown class KDLHomeLotteryKindCollectionCell in Interface Builder file.应该是宿主工程在加载静态库对应的bundle里的XIB文件时出问题了.

原因分析及解决办法:
确定以及肯定的是系统在查找XIB对应的类时没有找到导致的.

在制作静态库和Bundle时,类和XIB文件被分离到各自的target.而XIB文件是被拖入到bundle中的,因此需要更改XIB之前的默认Module设置,尤其是创建时选择Swift语言.否则系统在查找XIB的类时是在Bundle这个Module中找,当然是找不到的,从而在加载时崩溃.

解决办法:
需要更改XIB对应类的所属Module为静态库的Module.或者不勾选Inherit Module From Target,并清空Module一栏.

note:Swift创建的XIB默认是选中Inherit Module From Target的.OC创建的XIB文件系统默认没有勾选.

eg:

Array中的map和flapMap的一点区别

注意:map和flapMap方法在很多类型里都有定义,一定要看清楚方法声明。

map的声明:

1
@inlinable public func map<T>(_ transform: (Element) throws -> T) rethrows -> [T]

它返回的是一个数组.闭包的返回值是一个新数组的元素. 默认情况下,只要闭包有可能返回一个optional类型元素,则map返回的将是一个[T?]数组.

flapMap的声明: 有两种声明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@available(swift, deprecated: 4.1, renamed: "compactMap(_:)", message: "Please use compactMap(_:) for the case where closure returns an optional value")
public func flatMap<ElementOfResult>(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]

/// Returns an array containing the concatenated results of calling the
/// given transformation with each element of this sequence.
///
/// Use this method to receive a single-level collection when your
/// transformation produces a sequence or collection for each element.
///
/// In this example, note the difference in the result of using `map` and
/// `flatMap` with a transformation that returns an array.
///
/// let numbers = [1, 2, 3, 4]
///
/// let mapped = numbers.map { Array(repeating: $0, count: $0) }
/// // [[1], [2, 2], [3, 3, 3], [4, 4, 4, 4]]
///
/// let flatMapped = numbers.flatMap { Array(repeating: $0, count: $0) }
/// // [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
///
/// In fact, `s.flatMap(transform)` is equivalent to
/// `Array(s.map(transform).joined())`.
///
/// - Parameter transform: A closure that accepts an element of this
/// sequence as its argument and returns a sequence or collection.
/// - Returns: The resulting flattened array.
///
/// - Complexity: O(*m* + *n*), where *n* is the length of this sequence
/// and *m* is the length of the result.
@inlinable public func flatMap<SegmentOfResult>(_ transform: (Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Element] where SegmentOfResult : Sequence

@inlinable public func compactMap<ElementOfResult>(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]

二者区别:

  1. flatMap可以用来展平一个数组:它把原序列里的元素变为一个序列,然后把这个序列的元素添加到结果序列中,相当于降维了。展的有多平得看transform的实现,不过最少是减一层。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    let links: [[String]] = [
    ["http://a1", "http://a2", "http://a3"],
    ["http://b1", "http://b2", "http://b3"],
    ["http://c1", "http://c2", "http://c3"],
    ]
    print(links)

    let flapLink = links.flatMap { (exlinks: [String]) -> [String] in
    return exlinks //因为links的元素就是数组所以这里直接返回就可以了。
    }
    print(flapLink) //["http://a1", "http://a2", "http://a3", "http://b1", "http://b2", "http://b3", "http://c1", "http://c2", "http://c3"]

    let d3: [[[Int]]] = [
    [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
    [[10, 11, 12], [13, 14, 15], [16, 17, 18]],
    [[19, 20, 21], [22, 23, 24], [25, 26, 27]],
    ]
    //[[Int]]
    let flapD1 = d3.flatMap { ele in
    return ele
    }
    //[Int]
    let flapD2 = d3.flatMap { ele in
    return ele.flatMap{$0}
    }

    let colors = ["♥", "♠", "♦", "♣"]
    let numbers = ["J", "Q", "K", "A"]
    let cards = colors.flatMap { color in
    return numbers.map { num in
    return "\(color)-\(num)"
    }
    }
    print(cards) //["♥-J", "♥-Q", "♥-K", "♥-A", "♠-J", "♠-Q", "♠-K", "♠-A", "♦-J", "♦-Q", "♦-K", "♦-A", "♣-J", "♣-Q", "♣-K", "♣-A"]
  2. flatMap可以将转化失败的nil元素剔除,而map则不能:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    let wq = ["123", "fsd", "dfsd", "34"]
    //类型是[Int?]
    let wqm = wq.map { (element) -> Int? in
    return Int(element)
    }
    print(wqm) //[Optional(123), nil, nil, Optional(34)]

    //类型是[Int]
    let wqfm = wq.flatMap { (element) -> Int? in
    return Int(element)
    }
    print(wqfm) //[123, 34]
阅读全文 »

Allocation Type介绍

官方文档

The following allocation type display settings filter the allocations in the detail pane based on their type.

Setting Description
All Heap & Anonymous VM Shows all malloc heap allocations and interesting VM regions such as graphics- and Core Data-related. Hides mapped files, dylibs, and some large reserved VM regions.
All Heap Allocations Shows all malloc heap allocations but no VM regions.
All VM Regions Shows all VM regions, including mapped files, dylibs, and the VM regions that include the malloc heap.

参考:Allocations Instrument

论坛上的解释

1

All heap allocations consist of the memory allocations your application makes. This is the allocation type you should focus on in Instruments.

All VM regions consist of the virtual memory the operating system reserves for your application. You cannot control the size of the virtual memory the operating system reserves.

All heap and anonymous vm is the sum of the All Heap Allocations and All VM Regions columns.

阅读全文 »

1
2
3
NSString *str = @"123456a";
NSData *dataStr = [str dataUsingEncoding:NSUTF8StringEncoding];
NSLog(@"%s %s", [str UTF8String], dataStr.bytes);

iOS9.0模拟器.
输出:123456a 123456a–˝ã˘
dataStr.bytes的二进制内容:31 32 33 34 35 36 61 D0 1D 13 FD 8B F9 07 00 10
出现上述情况的原因:
需要了解%s是如何打印c字符串的.
%s打印的时候遇到\0就停止,[str UTF8String]转换的时候,自动在字符数组的最后面加上了\0(A null-terminated UTF8 representation of the string.),但是data.bytes后面’不一定’是\0,所以打印data.bytes的时候会有额外的内容.

pod install和pod update

pod install

每次运行pod install命令,并且有下载安装新的库时,CocoaPods会把这些安装的库的版本都写在Podfile.lock文件里面。这个文件记录你每个安装库的版本号,并且锁定了这些版本。

后面再次运行的时候,它会解析Podfile.lock文件,对于存在在Podfile.lock文件中的则安装Podfile.lock文件中的版本的库而不会去检测该库是否有最新的版本可用,对于不在Podfile.lock文件中的,则根据Podfile文件指定的库版本下载安装.

pod install不会去更新已存在的库的版本.

举个栗子:

IGListKit 有v3.1.0,和v3.1.1两个版本

Podfile如下: pod 'IGListKit', '~> 3.1.0'

场景1:第一次安装,无Podfile.lock。

此时执行pod install,你会发现下载并安装的是3.1.1版本。因为Podfile中使用的是 ~> ,表明可以使用较新的一个小版本。

阅读全文 »

使用本地pod

创建Podspec文件:pod spec create XQPerson

修改XQPerson.podspec文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Pod::Spec.new do |s|
s.name = "XQPerson"
s.version = "0.0.1"
s.summary = "Use XQPerson to print hello."
s.description = <<-DESC
A pod used to print hello. this is just a simply pod.
DESC
s.homepage = "https://github.com/tonymillion/Reachability"
s.license = "MIT"
s.author = { "xq_120" => "xq_120455@yahoo.com" }
s.platform = :ios, "7.0"
s.source = { :git => "/Users/xuequan/Desktop/XQPerson/", :tag => "#{s.version}" }
s.source_files = "XQPerson/*.{h,m}"

s.framework = "Foundation"
# s.frameworks = "SomeFramework", "AnotherFramework"

# s.library = "iconv"
# s.libraries = "iconv", "xml2"

s.requires_arc = true

# s.dependency "JSONKit", "~> 1.4"

end

验证Spec文件:pod lib lint:

1
2
3
 -> XQPerson (0.0.1)

XQPerson passed validation.

准备好你的pod文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
xuequandeMacBook-Pro:XQPerson xuequan$ tree /Users/xuequan/Desktop/XQPerson -L 2
/Users/xuequan/Desktop/XQPerson
├── LICENSE
├── XQPerson
│   ├── XQPerson.h
│   └── XQPerson.m
├── XQPerson.podspec
└── XQPersonDemo
├── Podfile
├── Podfile.lock
├── Pods
├── XQPersonDemo
├── XQPersonDemo.xcodeproj
├── XQPersonDemo.xcworkspace
├── XQPersonDemoTests
└── XQPersonDemoUITests

打好tag.

使用本地pods时,Podfile有两种写法:

阅读全文 »

版本:SDWebImage v5.11.1

SDWebImage源码分析

本文主要分析解决以下几个疑问:

  1. 同一图片的请求,SD如何从缓存中查找出来(key的命名规则)?或者说查找过程是怎样的?
  2. SD工作过程以及是如何从服务器下载的?
  3. SD是如何缓存图片的?
  4. 当空间不足时,它的删除策略是什么(按时间顺序,还是图片质量)?
  5. SD图片缓存机制与系统的NSURLCache的区别,为什么SD说自己的性能要略高于系统的性能?

SDWebImageOptions的枚举值解释

在使用SD提供的UIImageView类别方法:

1
2
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock;

下载图片时,有一个SDWebImageOptions参数,它可以用来配置SD的下载、缓存等行为.该参数是一个枚举,它有很多可选的值.
下面将分析每个值的含义:
SDWebImageRetryFailed = 1 << 0,SD的注释

1
2
3
4
/**
* By default, when a URL fail to be downloaded, the URL is blacklisted so the library won't keep trying.
* This flag disable this blacklisting.
*/

翻译:
SD默认,当一个URL下载失败后(网址无效的情况导致的下载失败才会进入,其他比如网络差原因导致的失败不会进入黑名单),该URL将会进入黑名单,SD将不会继续尝试下载.该选项将不使能黑名单.即即使该URL下载失败了,也不会进入黑名单,以后可以继续尝试下载.

SDWebImageLowPriority = 1 << 1,SD的注释

阅读全文 »

Q:UIButton想要扩大它的响应区域?
A:重载UIButton的hitTest或pointInside.
重载hitTest:

1
2
3
4
5
6
7
8
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) return nil;
CGRect touchRect = CGRectInset(self.bounds, -40, -40);
if (CGRectContainsPoint(touchRect, point)) {
return self;
}
return [super hitTest:point withEvent:event];
}

或重载pointInside:

1
2
3
4
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event {
BOOL rs = CGRectContainsPoint(CGRectInset(self.bounds, -40, -40), point);
return rs;
}

这里推荐重写pointInside方法.因为重写hitTest方法需要注意判断view的一些属性:if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) return nil;如果不判断会出Bug,比如设置按钮hidden为YES了,但是摸到按钮的区域,按钮的响应方法一样会被调用.而重写pointInside方法则不需要考虑这些.

PS:如果设置了userInteractionEnabled=NO;即使重写hitTest返回按钮自己,按钮的响应方法也不会回调.应该是系统在回调之前又判断了一下该属性的值.

userInteractionEnabled的说明如下:

When set to NO, touch, press, keyboard, and focus events intended for the view are ignored and removed from the event queue. When set to YES, events are delivered to the view normally. The default value of this property is YES.

During an animation, user interactions are temporarily disabled for all views involved in the animation, regardless of the value in this property. You can disable this behavior by specifying the UIViewAnimationOptionAllowUserInteraction option when configuring the animation.

当btn作为第一响应者被返回时,如果userInteractionEnabled属性为NO,则与它相关的事件(触摸,按压)都将被忽略.因此btn的响应方法不会被调用.

Q:点击子视图超出父视图的区域仍让子视图响应事件?
A:必须重载父视图(**父视图父视图父视图**三遍!!!)的pointInside方法.这是由于如果父视图的pointInside返回NO的话,其上的子视图就不会进行hitTest,因此重载子视图的相关方法将无效.

阅读全文 »