2015-11-13 56 views
0

下面的代碼被寫入夫特2.0創建的dispatch_block_t如何在Swift 2.0中實現copyWithZone?

let a: dispatch_block_t = { 
    self.pickImages() 
} 
let b: dispatch_block_t = { 
    self.takePicture() 
} 
let c: dispatch_block_t = { 
    self.pickVideos() 
} 
let d: dispatch_block_t = { 
    self.shootVideo() 
} 
let e: dispatch_block_t = { 
    self.recordAudio() 
} 
let f: dispatch_block_t = { 
    self.closeView() 
} 

let block1 = Block(block: a) 
let block2 = Block(block: b) 
let block3 = Block(block: c) 
let block4 = Block(block: d) 
let block5 = Block(block: e) 
let block6 = Block(block: f) 

let actionsArray: NSArray = [block1, block2, block3, block4, block5, block6] 

一個陣列和Block類被定義如下,

class Block: NSObject, NSCopying { 
    var block: dispatch_block_t 

    init(block: dispatch_block_t){ 
     self.block = block 
    } 

    func copyWithZone(zone: NSZone) -> AnyObject { 
     return self.block as! AnyObject 
    } 
} 

我可以創建dispatch_block_t的陣列與上述片的代碼。但是,我需要將此數組作爲參數傳遞給另一個函數,並且在傳遞此數組時遇到了一個問題。

我呼籲一個按鈕單擊事件這個功能,

menuView = btSimplePopUP(itemImage: imgs as [AnyObject], 
    andTitles: titles as [AnyObject], 
    andActionArray: actionsArray as [AnyObject], 
    addToViewController: self) 

,執行下面的代碼片段時,我得到一個錯誤,

- (instancetype)initWithImage:(UIImage *)image title:(NSString *)title action:(dispatch_block_t)action { 
if ((self = [super init])) { 
    _title = [title copy]; 
    _imageView = [[UIImageView alloc]initWithImage:image]; 
    _action = [action copy]; 
} 

return self; 
} 

和錯誤是,

無法將類型'() - >()'(0x15164018)的值轉換爲'Swift.AnyObject'(0x101e500c)。

我得到這個錯誤copyWithZone函數Block類。

爲btSimplePopUp的完整源代碼在這裏可以查看, https://github.com/balram3429/btSimplePopUp/blob/master/btSimplePopUp/btSimplePopUP.m

+0

你問的第三次同樣的問題,有什麼錯誤ü如果面臨轉換或打字 –

+0

以前,我不能創建一個dispatch_block_t數組。但是現在,我創建了這個數組。但是我不能在另一個類中定義的函數中處理它。 –

+0

'*** NSForwarding:警告:類'ProjName.Block'的對象0x7a5841b0沒有實現methodSignatureForSelector: - 提前出現無法識別的選擇器 - [ProjName.Block copy]'我在定義'copyWithZone'函數之前收到了這個錯誤'塊類。定義它後,我得到以下錯誤:'無法將類型'() - >()'(0x15164018)的值轉換爲'Swift.AnyObject'(0x101e500c).'。你有什麼想法來解決這個問題嗎? –

回答

1

dispatch_block_t是一個結構,而不是一個對象。實際上它是一個C結構。我不明白你爲什麼需要使用dispatch_block_t,爲什麼不只是傳遞閉包。如果必須將它傳遞給dispatch_函數,請將其包裝在調用站點的dispatch_block_t中。

要Swiftify此:

在夫特,dispatch_block_t是簡單地爲() ->()即一個別名的空隙功能/閉合返回Void。所以,你可以簡單地說

let a = { self.pickImages() } 
// etc 

let actionArray = [ a, b, c, ...] 

然而,pickImages是具有相同類型(在技術上它是咖喱在self但不要擔心這是什麼意思),你可以對A,B忘了這麼一個功能, C位,只是這樣做

let actionArray = [ self.pickImages, self.takePhoto, ... ] 

而且在斯威夫特,你可以在陣列中使用「對象」之一,任何時候你有一個參數,需要一個dispatch_block_t

dispatch_after(someTime, dispatch_get_main_queue(), actionArray[0]) 
+0

感謝您的回覆。我是iOS的新手。你可以請張貼一些示例代碼來通過關閉? –

+0

@DeepikaMasilamani爲你添加了一些代碼 – JeremyP

+0

[Apple's documentation says](https://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/)dispatch_block_t是void的一個typedef(^ )(空隙)'。這意味着它**是一個對象。 (這意味着它也是一個C結構,但它不是「不是對象」。) –

0

您需要修改您的Objc框架。您的btSimplePopUP應該像ActionContainer一樣從此示例中運行。 ActionObject是Swift dispatch_block_t的裝箱版本。如何在代碼中取消裝箱?請參閱ActionContainer作業功能。

// 
// Actions.h 
// test 
// 


#ifndef Actions_h 
#define Actions_h 
#import <Foundation/Foundation.h> 

@interface ActionObject : NSObject 
@property (nonatomic, copy) dispatch_block_t action; 
@end 


@interface ActionContainer : NSObject 
@property NSArray * actions; 
-(void)job; 
@end 

#endif /* Actions_h */ 

...

// 
// Actions.m 
// test 
// 


#import <Foundation/Foundation.h> 
#import "Actions.h" 


@implementation ActionObject 

-(instancetype)initWithAction: (dispatch_block_t)someaction { 
    if ((self = [super init])) { 
     _action = [someaction copy]; 
    } 
    return self; 
} 

@end 

@implementation ActionContainer 
-(void)job { 
    if (_actions != nil) { 
     NSUInteger count = _actions.count; 
     NSUInteger i; 
     for (i = 0; i < count; i++) { 
      ActionObject *action = _actions[i]; 
      action.action(); 
     } 

    } 
} 

@end 

...

// 
// Use this file to import your target's public headers that you would like to expose to Swift. 
// 

#import "Actions.h" 

...

// 
// main.swift 
// test 
// 


import Foundation 

let a = ActionObject() 
a.action = { 
    print("swift a action") 
} 
let b = ActionObject() 
b.action = { 
    print("swift b action") 
} 
let arr: NSArray = [a,b] 

let actions = ActionContainer() 
actions.actions = arr as [AnyObject] 
actions.job() 

農產品

swift a action 
swift b action 
Program ended with exit code: 0 

...

@implementation ActionContainer 
-(void)job { 
    if (_actions != nil) { 
     NSUInteger count = _actions.count; 
     NSUInteger i; 
     for (i = 0; i < count; i++) { 
      ActionObject *action = _actions[i]; 
      // myAction is 'unboxed' swift block 
      // you can save it, run it 
      // somwhere in you ObjectiveC code 
      dispatch_block_t myAction = action.action; 
      // run it 
      myAction(); 
     } 

    } 
} 
+0

@Deepica Masilamani如果你仍然不知道如何修改你自己的代碼,發佈你的整個項目在github上,我可以嘗試修改它爲你。沒有必要一次又一次地提出同樣的問題。沒有機會將swift dispatch_block_t強制轉換爲AnyObject。 – user3441734

+0

我會努力讓它工作,如果我不能,我會在git中發佈我的項目。感謝您的幫助@action3441734 –

+0

action.action()只是運行它(以演示其功能)。值是action.action。你可以保存它在btPopUpItem – user3441734