目錄 11+
11. macOS 調(diào)用framework中類別的方法 編譯成功但運行報錯
12. macOS語言本地化/國際化同iOS一致块促,參見:iOS語言本地化/國際化一些技巧
13. macOS 打包問題記錄
14. macOS 完全清理App
15. xib嵌套
16. macOS 修改App名稱
17. macOS App Main Menu 工具欄
目錄1-10
1. 瀏覽器打開URL
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://www.baidu.com"]];
2. NSTextField超鏈接
//policy
NSFont *font = [NSFont systemFontOfSize:12];
attStr = [[NSMutableAttributedString alloc] initWithString:@"登錄即同意《用戶協(xié)議》和《隱私政策》"];
[attStr addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, 18)];
[attStr addAttribute:NSForegroundColorAttributeName value:[NSColor colorWithRed:175.0f/255.0f green:174.0f/255.0f blue:174.0f/255.0f alpha:1.0f] range:NSMakeRange(0, 18)];
NSRange range = [[attStr string] rangeOfString:@"《用戶協(xié)議》"];
//policy-1
[attStr addAttribute:NSFontAttributeName value:font range:range];
[attStr addAttribute:NSForegroundColorAttributeName value:[NSColor colorWithRed:5.0f/255.0f green:164.0f/255.0f blue:255.0f/255.0f alpha:1.0f] range:range];;
[attStr addAttribute:NSLinkAttributeName value:kCFPrivacyTerms_URL range:range];
//policy-2
range = [[attStr string] rangeOfString:@"《隱私政策》"];
[attStr addAttribute:NSFontAttributeName value:font range:range];
[attStr addAttribute:NSForegroundColorAttributeName value:[NSColor colorWithRed:5.0f/255.0f green:164.0f/255.0f blue:255.0f/255.0f alpha:1.0f] range:range];
[attStr addAttribute:NSLinkAttributeName value:kCFPrivacyPolicy_URL range:range];
self.tfPolicy.enabled = YES;
self.tfPolicy.editable = NO;//必須禁止輸入琳彩,否則點擊將彈出輸入鍵盤
self.tfPolicy.selectable = YES;// 超連接
self.tfPolicy.allowsEditingTextAttributes = YES;// 超連接
self.tfPolicy.attributedStringValue = attStr;
3. NSTextField光標顏色 NSTextFieldCell和NSSecureTextFieldCell垂直居中 附加視圖
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
// Drawing code here.
/*無效*/
// NSView *view = [[NSView alloc] initWithFrame:CGRectMake(0, 0, NSWidth(dirtyRect), NSHeight(dirtyRect))];
// view.layer.backgroundColor = [NSColor blueColor].CGColor;
// [self addSubview:view];
}
-(BOOL) becomeFirstResponder {
BOOL res = [super becomeFirstResponder];
if ( res && self.hadSetInsertionPointColor == NO ) {
NSTextView* textField = (NSTextView*)[self currentEditor];
if ( [textField respondsToSelector: @selector(setInsertionPointColor:)] ) {
self.hadSetInsertionPointColor = YES;
[textField setInsertionPointColor:self.insertionPointColor?:self.textColor];
}
}
return res;
}
@end
/**密碼輸入框NSSecureTextField內(nèi)容垂直居中問題
NSSecureTextField-NSSecureTextFieldCell:不垂直居中
NSSecureTextField-LTSecureTextFieldCell:不垂直居中
NSTextField-LTSecureTextFieldCell:垂直居中
分類方式:成為第一響應者后洒试,才有效;失去第一響應者后無效
*/
@interface LTSecureTextFieldCell : NSSecureTextFieldCell
/**邊界纸厉,可以自定義控制視圖等*/
@property (nonatomic, assign) NSEdgeInsets edgeInsets;
@end
@implementation LTTextFieldCell
#pragma mark - 1無效
//- (NSRect)titleRectForBounds:(NSRect)rect{
//
// NSRect titleRect = [super titleRectForBounds:rect];
// CGFloat minimHeight = self.cellSize.height;
// titleRect.origin.y += (titleRect.size.height - minimHeight)/2;
// titleRect.size.height = minimHeight;
// return titleRect;
//}
//
//-(void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView{
// [super drawWithFrame:cellFrame inView:controlView];
//}
//
//-(void)selectWithFrame:(NSRect)rect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)delegate start:(NSInteger)selStart length:(NSInteger)selLength{
//
// CGRect titleRect = [self titleRectForBounds:rect];
// titleRect.origin.y += 10;//self.oringeY;
// [super selectWithFrame:titleRect inView:controlView editor:textObj delegate:delegate start:selStart length:selLength];
// NSLog(@"titleRect = %@",NSStringFromRect(titleRect));
//
//}
#pragma mark - 2
- (NSRect)adjustedFrameToVerticallyCenterText:(NSRect)frame {
// super would normally draw text at the top of the cell
NSRect rect = CGRectMake(self.edgeInsets.left, self.edgeInsets.top, NSWidth(frame) - self.edgeInsets.left - self.edgeInsets.right, NSHeight(frame) - self.edgeInsets.top - self.edgeInsets.bottom);
CGFloat fontSize = self.font.boundingRectForFont.size.height;
NSInteger offset = floor((NSHeight(rect) - ceilf(fontSize))/2) - 2;
NSRect centeredRect = NSInsetRect(rect, 0, offset);
return centeredRect;
}
- (void)editWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)editor delegate:(id)delegate event:(NSEvent *)event {
[super editWithFrame:[self adjustedFrameToVerticallyCenterText:aRect] inView:controlView editor:editor delegate:delegate event:event];
}
- (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)editor delegate:(id)delegate start:(NSInteger)start length:(NSInteger)length {
[super selectWithFrame:[self adjustedFrameToVerticallyCenterText:aRect] inView:controlView editor:editor delegate:delegate start:start length:length];
}
- (void)drawInteriorWithFrame:(NSRect)frame inView:(NSView *)view {
[super drawInteriorWithFrame:[self adjustedFrameToVerticallyCenterText:frame] inView:view];
}
#pragma mark - 3
/**實際內(nèi)容區(qū)域:修改了cell的frame,導致在設置背景色時田盈,部分區(qū)域無效*/
//- (NSRect)drawingRectForBounds:(NSRect)rect {
//
// NSRect rect1 = [super drawingRectForBounds:rect];
// NSSize size = [self cellSizeForBounds:rect];
// CGFloat h = rect1.size.height - size.height;
// if ( h > 0 ) {
// rect1.size.height = size.height;
// rect1.origin.y += h * 0.5;
// }
//
// return rect1;
//}
@end
4. 設置NSTextView失去光標
/**設置NSTextView失去光標*/
[self.tvEmail.window makeFirstResponder:nil];
[self.tvSuggest.window makeFirstResponder:nil];
5. 遮罩層MaskView
定制事件傳遞
/**遮罩視圖
不調(diào)用super方法救赐,阻止了事件的傳遞;
當前:攔截了鼠標的右鍵切油,左鍵蝙斜,又不會影響上層的視圖點擊*/
@interface LTMaskView : NSView
/**
/ **在superview中根據(jù)子視圖的identifier匹配LTMaskView,
設置LTMaskView的部分事件繼續(xù)傳遞澎胡,不被攔截孕荠;并且在superview中也可以設置superview自身事件是否繼續(xù)傳遞娩鹉、攔截;
* /
[self.view.subviews enumerateObjectsUsingBlock:^(__kindof NSView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ( [@"LTMaskView" isEqualToString:obj.identifier] ) {
LTMaskView *maskView = (LTMaskView *)obj;
maskView.allowedEventMask = NSEventMaskLeftMouseDown;
}
}];
/ **與設置里的自定義鼠標主鍵無關(guān)
問題:present子視圖后稚伍,屏蔽了子視圖的動作弯予,只有superview的mouseDown事件了
* /
[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskLeftMouseDown handler:^NSEvent * _Nullable(NSEvent * _Nonnull aEvent) {
[self mouseDown:aEvent];
return nil;/ **事件被攔截,不會下傳* /
return aEvent;/ **事件繼續(xù)傳遞* /
}];
*/
@property (nonatomic, assign) NSEventMask allowedEventMask;
@end
#import "LTMaskView.h"
@implementation LTMaskView
- (instancetype)init {
if ( self = [super init] ) {
/**tag是只讀屬性个曙,但可以在xib中設置
self.tag = 10001;
*/
self.identifier = NSStringFromClass([self class]);
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
self.identifier = NSStringFromClass([self class]);
}
return self;
}
- (instancetype)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.identifier = NSStringFromClass([self class]);
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
}
- (void)mouseDown:(NSEvent *)event {
if ( self.allowedEventMask & NSEventMaskLeftMouseDown ) {
[super mouseDown:event];
}
}
- (void)rightMouseDown:(NSEvent *)event {
if ( self.allowedEventMask & NSEventMaskRightMouseDown ) {
[super rightMouseDown:event];
}
}
@end
6. 彈框NSAlert
- (void) testForWindow:(NSWindow *) window {
NSAlert *alert = [[NSAlert alloc] init];
alert.icon = nil;//[NSImage imageNamed:@"icon"];/**nil時锈嫩,默認APPicon*/
alert.alertStyle = NSAlertStyleWarning;
[alert addButtonWithTitle:@"確定"];
// [alert addButtonWithTitle:@"取消"];/**可以注釋*/
// alert.messageText = @"title";/**可以注釋*/
// alert.informativeText = @"msg";/**可以注釋*/
alert.showsSuppressionButton = NO;/**是否展示Don't ask again*/
/**
方式1
使用方式1的時候需要注意的是window不能為nil,
不要講NSAlert添加在HomeVC的ViewDidLoad中垦搬,此時Window還沒創(chuàng)建成功呼寸。
*/
[alert beginSheetModalForWindow:window completionHandler:^(NSModalResponse returnCode) {
if (returnCode == NSAlertFirstButtonReturn) {
NSLog(@"確定");
} else if (returnCode == NSAlertSecondButtonReturn) {
NSLog(@"取消");
} else {
NSLog(@"else");
}
}];
/*! 方式2
NSModalResponse response = [alert runModal];
if (response == NSModalResponseStop) {
}
if (response == NSModalResponseAbort) {
}
if (response == NSModalResponseContinue) {
}
*/
}
7. NSView tag
在xib或storyboard中可以設置tag;但是在代碼里猴贰,因為tag為readonly对雪,所以不可以設置tag。
8. layout 無效
[self.layer layoutIfNeeded];
[self.layer layoutSublayers];
9. NSBezierPath 圓角 在drawRect中繪制
https://stackoverflow.com/questions/23094140/nsbezierpath-appendbezierpathwitharcfrompoint-wont-draw
/**
當前繪圖的上下文為空米绕,因此無法繪制慌植。
即:只有在drawRect函數(shù)內(nèi)部才提供了繪制圖形上下文環(huán)境,
不能在非drawRect函數(shù)內(nèi)部通過NSBezierPath或者CGPathRef繪制內(nèi)容
*/
- (void) addArcToProView {
CGSize size = self.proView.bounds.size;
CGFloat h = size.height;
CGFloat w = self.tfPro_w.constant / 0.65f;/*重點义郑,計算*/
NSBezierPath *thePath = [NSBezierPath bezierPath]; // all drawing instruction goes to thePath.
/*線條*/
[NSBezierPath setDefaultLineWidth:5.0];
[[NSColor clearColor] set];/*必須設置為clearColor蝶柿,否則會顯示邊框*/
[thePath moveToPoint:NSMakePoint(w, h)];
[thePath lineToPoint:NSMakePoint(0, h)];
[thePath appendBezierPathWithArcFromPoint:NSMakePoint(0,0) toPoint:NSMakePoint(h,0) radius:h];
[thePath lineToPoint:NSMakePoint(w, 0)];
[thePath lineToPoint:NSMakePoint(w, h)];
[thePath stroke];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = CGRectMake(0, 0, w, h);
maskLayer.path = [[LTCGTool tool] getCGPathFromNSBezierPath:thePath];
self.proView.layer.mask = maskLayer;
}
#pragma mark - NSBezierPath
/// 獲取NSBezierPath的CGPath
/// 也可以使用分類的方式實現(xiàn)
/// @param path NSBezierPath
- (CGMutablePathRef)getCGPathFromNSBezierPath:(NSBezierPath *)path {
CGMutablePathRef cgPath = CGPathCreateMutable();
NSInteger n = [path elementCount];
for (NSInteger i = 0; i < n; i++) {
NSPoint ps[3];
switch ([path elementAtIndex:i associatedPoints:ps]) {
case NSBezierPathElementMoveTo: {
CGPathMoveToPoint(cgPath, NULL, ps[0].x, ps[0].y);
break;
}
case NSBezierPathElementLineTo: {
CGPathAddLineToPoint(cgPath, NULL, ps[0].x, ps[0].y);
break;
}
case NSBezierPathElementCurveTo: {
CGPathAddCurveToPoint(cgPath, NULL, ps[0].x, ps[0].y, ps[1].x, ps[1].y, ps[2].x, ps[2].y);
break;
}
case NSBezierPathElementClosePath: {
CGPathCloseSubpath(cgPath);
break;
}
default: NSAssert(0, @"Invalid NSBezierPathElement");
}
}
return cgPath;
}
10. NSScrollView
基本用法
//style,overloy會獨立出來scroll的部分非驮,背景透明
_scrollView.scrollerStyle = NSScrollerStyleOverlay;
// 水平和垂直的彈性屬性
_scrollView.horizontalScrollElasticity = NSScrollElasticityNone;
_scrollView.verticalScrollElasticity = NSScrollElasticityNone;
_scrollView.scrollerInsets = NSEdgeInsetsMake(0, 0, 0, -20);//NSEdgeInsets(top:0, left:0, bottom:0, right:-20)
_scrollView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
_scrollView.backgroundColor = [NSColor clearColor];
_scrollView.drawsBackground = NO;
- 設置偏移交汤,也可以給NSScrollView添加extension(Swift)或Category(OC)。
CGFloat pY = 0;
CGFloat h = NSHeight(_scrollView.bounds);
NSView *documentView = self.scrollView.documentView;
if ( NO == documentView.isFlipped ) {
pY = MAX(NSHeight(_scrollView.bounds), NSHeight(documentView.bounds));
}
[_scrollView scrollPoint:CGPointMake(0, pY - h + _scrollView.fittingSize.height)];// 設置無效
[documentView scrollPoint:CGPointMake(0, pY)];// 粗略值
[documentView scrollPoint:CGPointMake(0, pY - h + _scrollView.fittingSize.height)];// 更為準確的值
[_scrollView.contentView scrollToPoint:CGPointMake(0, pY - h + _scrollView.fittingSize.height)];// 更為準確的值
- NSScrollView與TitleBar重疊時劫笙,top會有偏移芙扎,下列方法清除偏移。
_scrollView.automaticallyAdjustsContentInsets = NO;
//_scrollView.contentInsets = NSEdgeInsetsMake(-44, 0, 0, 0);// 不用
- 自定義MYScrollView:禁止滑動填大;嵌套戒洼,滑動事件下傳;
@interface MYScrollView : NSScrollView
@end
@implementation MYScrollView
//- (void)reflectScrolledClipView:(NSClipView *)cView {
// /*禁止滑動失敗*/
//}
- (void)scrollWheel:(NSEvent *)event {
// NSLog(@"%@-%s", NSStringFromClass([self class]), __func__);
// NSLog(@"%s, %@, %@", __func__, self, @(event.phase));
// [super scrollWheel:event];/*禁止滑動:重載scrollWheel:,并且不調(diào)用super允华,無任何實現(xiàn)*/
/**嵌套圈浇,滑動事件下傳:NSScrollView內(nèi)嵌套一個MYScrollView,可以隨著外側(cè)的NSScrollView一起滾動*/
[self.nextResponder scrollWheel:event];
}
@end